Før sentralisert brukerliste
This commit is contained in:
parent
974c41ca4d
commit
ee198150c2
18 changed files with 684 additions and 337 deletions
|
|
@ -2,22 +2,27 @@ package com.kbs.kbsintranett;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.DatePickerDialog;
|
import android.app.DatePickerDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
import retrofit2.Response;
|
import retrofit2.Response;
|
||||||
|
|
@ -26,15 +31,18 @@ public class AddTaskBottomSheet extends BottomSheetDialogFragment {
|
||||||
|
|
||||||
private EditText etTitle, etDesc;
|
private EditText etTitle, etDesc;
|
||||||
private Button btnDate, btnUsers, btnSave;
|
private Button btnDate, btnUsers, btnSave;
|
||||||
private TextView txtDatePreview, txtUsersPreview;
|
private TextView txtSheetTitle, txtDatePreview, txtUsersPreview;
|
||||||
|
|
||||||
private Calendar dueDate = Calendar.getInstance();
|
private Calendar dueDate = Calendar.getInstance();
|
||||||
private List<User> allUsersFromApi = new ArrayList<>();
|
private List<User> allUsersFromApi = new ArrayList<>();
|
||||||
private List<User> filteredUsers = new ArrayList<>();
|
private List<User> filteredUsers = new ArrayList<>();
|
||||||
private List<User> selectedUsers = new ArrayList<>();
|
private List<User> selectedUsers = new ArrayList<>();
|
||||||
|
|
||||||
|
private TaskItem taskToEdit = null; // NYTT: Hold på oppgaven som skal endres
|
||||||
|
|
||||||
public interface OnTaskAddedListener {
|
public interface OnTaskAddedListener {
|
||||||
void onTaskAdded(TaskItem task);
|
void onTaskAdded(TaskItem task);
|
||||||
|
void onTaskUpdated(TaskItem task); // NYTT
|
||||||
}
|
}
|
||||||
|
|
||||||
private OnTaskAddedListener listener;
|
private OnTaskAddedListener listener;
|
||||||
|
|
@ -43,11 +51,32 @@ public class AddTaskBottomSheet extends BottomSheetDialogFragment {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NYTT: Metode for å sette oppgaven som skal redigeres
|
||||||
|
public void setTaskToEdit(TaskItem task) {
|
||||||
|
this.taskToEdit = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||||
|
BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
|
||||||
|
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
|
||||||
|
dialog.setOnShowListener(dialogInterface -> {
|
||||||
|
BottomSheetDialog d = (BottomSheetDialog) dialogInterface;
|
||||||
|
View bottomSheet = d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
|
||||||
|
if (bottomSheet != null) {
|
||||||
|
BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
View v = inflater.inflate(R.layout.bottom_sheet_add_task, container, false);
|
View v = inflater.inflate(R.layout.bottom_sheet_add_task, container, false);
|
||||||
|
|
||||||
|
txtSheetTitle = v.findViewById(R.id.txt_sheet_title); // Pass på at denne IDen finnes i XML
|
||||||
etTitle = v.findViewById(R.id.et_task_title);
|
etTitle = v.findViewById(R.id.et_task_title);
|
||||||
etDesc = v.findViewById(R.id.et_task_desc);
|
etDesc = v.findViewById(R.id.et_task_desc);
|
||||||
btnDate = v.findViewById(R.id.btn_task_date);
|
btnDate = v.findViewById(R.id.btn_task_date);
|
||||||
|
|
@ -56,7 +85,16 @@ public class AddTaskBottomSheet extends BottomSheetDialogFragment {
|
||||||
txtDatePreview = v.findViewById(R.id.txt_date_preview);
|
txtDatePreview = v.findViewById(R.id.txt_date_preview);
|
||||||
txtUsersPreview = v.findViewById(R.id.txt_users_preview);
|
txtUsersPreview = v.findViewById(R.id.txt_users_preview);
|
||||||
|
|
||||||
dueDate.add(Calendar.DAY_OF_MONTH, 1);
|
if (taskToEdit != null) {
|
||||||
|
txtSheetTitle.setText("Rediger Oppgave");
|
||||||
|
etTitle.setText(taskToEdit.getTitle());
|
||||||
|
etDesc.setText(taskToEdit.getDescription());
|
||||||
|
dueDate.setTimeInMillis(taskToEdit.getDueDate());
|
||||||
|
btnSave.setText("Oppdater Oppgave");
|
||||||
|
} else {
|
||||||
|
dueDate.add(Calendar.DAY_OF_MONTH, 1);
|
||||||
|
}
|
||||||
|
|
||||||
updateDatePreview();
|
updateDatePreview();
|
||||||
|
|
||||||
btnDate.setOnClickListener(view -> {
|
btnDate.setOnClickListener(view -> {
|
||||||
|
|
@ -81,6 +119,18 @@ public class AddTaskBottomSheet extends BottomSheetDialogFragment {
|
||||||
if (response.isSuccessful() && response.body() != null) {
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
allUsersFromApi = response.body();
|
allUsersFromApi = response.body();
|
||||||
filterUsersByHierarchy();
|
filterUsersByHierarchy();
|
||||||
|
|
||||||
|
// Hvis vi redigerer, må vi mappe eksisterende deltakere til selectedUsers listen
|
||||||
|
if (taskToEdit != null) {
|
||||||
|
selectedUsers.clear();
|
||||||
|
Map<String, Boolean> currentAssignees = taskToEdit.getAssigneeStatus();
|
||||||
|
for (User u : allUsersFromApi) {
|
||||||
|
if (currentAssignees.containsKey(u.getEmail())) {
|
||||||
|
selectedUsers.add(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateUsersPreview();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -91,34 +141,30 @@ public class AddTaskBottomSheet extends BottomSheetDialogFragment {
|
||||||
private void filterUsersByHierarchy() {
|
private void filterUsersByHierarchy() {
|
||||||
filteredUsers.clear();
|
filteredUsers.clear();
|
||||||
UserManager me = UserManager.getInstance();
|
UserManager me = UserManager.getInstance();
|
||||||
|
|
||||||
// 1. Hvis Admin/Editor, legg til alle
|
|
||||||
if (me.isEditorOrAbove()) {
|
|
||||||
filteredUsers.addAll(allUsersFromApi);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Finn mine roller/avdelinger
|
|
||||||
List<String> myRoles = new ArrayList<>();
|
List<String> myRoles = new ArrayList<>();
|
||||||
|
User self = null;
|
||||||
|
|
||||||
for (User u : allUsersFromApi) {
|
for (User u : allUsersFromApi) {
|
||||||
if (u.getEmail().equalsIgnoreCase(me.getUserEmail())) {
|
if (u.getEmail().equalsIgnoreCase(me.getUserEmail())) {
|
||||||
|
self = u;
|
||||||
for (String r : u.getRoles()) myRoles.add(r.toLowerCase());
|
for (String r : u.getRoles()) myRoles.add(r.toLowerCase());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Filtrer logikk (Identisk med CreateEventFragment)
|
if (me.isEditorOrAbove()) {
|
||||||
|
filteredUsers.addAll(allUsersFromApi);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (User u : allUsersFromApi) {
|
for (User u : allUsersFromApi) {
|
||||||
// Alltid legg til seg selv
|
|
||||||
if (u.getEmail().equalsIgnoreCase(me.getUserEmail())) {
|
if (u.getEmail().equalsIgnoreCase(me.getUserEmail())) {
|
||||||
if (!filteredUsers.contains(u)) filteredUsers.add(u);
|
if (!filteredUsers.contains(u)) filteredUsers.add(u);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasAccess = false;
|
boolean hasAccess = false;
|
||||||
for (String role : u.getRoles()) {
|
for (String role : u.getRoles()) {
|
||||||
String r = role.toLowerCase();
|
String r = role.toLowerCase();
|
||||||
// Sjekk om vi deler en avdelingsrolle
|
|
||||||
if ((r.equals("serviceavdelingen") && myRoles.contains("serviceavdelingen")) ||
|
if ((r.equals("serviceavdelingen") && myRoles.contains("serviceavdelingen")) ||
|
||||||
(r.equals("automasjonsavdelingen") && myRoles.contains("automasjonsavdelingen")) ||
|
(r.equals("automasjonsavdelingen") && myRoles.contains("automasjonsavdelingen")) ||
|
||||||
(r.equals("prosjektavdelingen") && myRoles.contains("prosjektavdelingen")) ||
|
(r.equals("prosjektavdelingen") && myRoles.contains("prosjektavdelingen")) ||
|
||||||
|
|
@ -128,10 +174,7 @@ public class AddTaskBottomSheet extends BottomSheetDialogFragment {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (hasAccess && !filteredUsers.contains(u)) filteredUsers.add(u);
|
||||||
if (hasAccess && !filteredUsers.contains(u)) {
|
|
||||||
filteredUsers.add(u);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,28 +183,44 @@ public class AddTaskBottomSheet extends BottomSheetDialogFragment {
|
||||||
Toast.makeText(getContext(), "Henter tilgjengelige personer...", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Henter tilgjengelige personer...", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] names = new String[filteredUsers.size()];
|
String[] names = new String[filteredUsers.size()];
|
||||||
boolean[] checked = new boolean[filteredUsers.size()];
|
boolean[] checked = new boolean[filteredUsers.size()];
|
||||||
for (int i = 0; i < filteredUsers.size(); i++) {
|
for (int i = 0; i < filteredUsers.size(); i++) {
|
||||||
names[i] = filteredUsers.get(i).getName();
|
names[i] = filteredUsers.get(i).getName();
|
||||||
checked[i] = selectedUsers.contains(filteredUsers.get(i));
|
// Sjekk om e-posten finnes i de valgte brukernes liste
|
||||||
|
boolean isSelected = false;
|
||||||
|
for(User su : selectedUsers) {
|
||||||
|
if(su.getEmail().equalsIgnoreCase(filteredUsers.get(i).getEmail())) {
|
||||||
|
isSelected = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checked[i] = isSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
new AlertDialog.Builder(getContext())
|
new AlertDialog.Builder(getContext())
|
||||||
.setTitle("Tildel til...")
|
.setTitle("Tildel til...")
|
||||||
.setMultiChoiceItems(names, checked, (dialog, which, isChecked) -> {
|
.setMultiChoiceItems(names, checked, (dialog, which, isChecked) -> {
|
||||||
if (isChecked) selectedUsers.add(filteredUsers.get(which));
|
User user = filteredUsers.get(which);
|
||||||
else selectedUsers.remove(filteredUsers.get(which));
|
if (isChecked) {
|
||||||
})
|
boolean alreadyIn = false;
|
||||||
.setPositiveButton("OK", (dialog, which) -> {
|
for(User su : selectedUsers) if(su.getEmail().equalsIgnoreCase(user.getEmail())) alreadyIn = true;
|
||||||
if (selectedUsers.isEmpty()) txtUsersPreview.setText("Kun meg");
|
if(!alreadyIn) selectedUsers.add(user);
|
||||||
else if (selectedUsers.size() == 1) txtUsersPreview.setText(selectedUsers.get(0).getName());
|
} else {
|
||||||
else txtUsersPreview.setText(selectedUsers.size() + " personer valgt");
|
User toRemove = null;
|
||||||
|
for(User su : selectedUsers) if(su.getEmail().equalsIgnoreCase(user.getEmail())) toRemove = su;
|
||||||
|
if(toRemove != null) selectedUsers.remove(toRemove);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
.setPositiveButton("OK", (dialog, which) -> updateUsersPreview())
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateUsersPreview() {
|
||||||
|
if (selectedUsers.isEmpty()) txtUsersPreview.setText("Kun meg");
|
||||||
|
else if (selectedUsers.size() == 1) txtUsersPreview.setText(selectedUsers.get(0).getName());
|
||||||
|
else txtUsersPreview.setText(selectedUsers.size() + " personer valgt");
|
||||||
|
}
|
||||||
|
|
||||||
private void updateDatePreview() {
|
private void updateDatePreview() {
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault());
|
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault());
|
||||||
txtDatePreview.setText("Frist: " + sdf.format(dueDate.getTime()));
|
txtDatePreview.setText("Frist: " + sdf.format(dueDate.getTime()));
|
||||||
|
|
@ -174,14 +233,64 @@ public class AddTaskBottomSheet extends BottomSheetDialogFragment {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskItem task = new TaskItem(title, etDesc.getText().toString(), dueDate.getTimeInMillis());
|
if (taskToEdit != null) {
|
||||||
if (selectedUsers.isEmpty()) {
|
// REDIGER MODUS: Oppdater eksisterende objekt
|
||||||
task.addAssignee(UserManager.getInstance().getUserEmail());
|
// Vi må beholde ID, Creator osv, men oppdatere innhold og deltakere
|
||||||
} else {
|
// OBS: Hvis vi fjerner deltakere som allerede hadde gjort oppgaven, forsvinner deres status.
|
||||||
for (User u : selectedUsers) task.addAssignee(u.getEmail());
|
// Dette er akseptabel oppførsel for enkelthets skyld.
|
||||||
}
|
|
||||||
|
|
||||||
if (listener != null) listener.onTaskAdded(task);
|
// Lag en kopi av gamle statuser for å bevare "Fullført" for de som fortsatt er med
|
||||||
|
Map<String, Boolean> oldStatus = taskToEdit.getAssigneeStatus();
|
||||||
|
taskToEdit.getAssigneeStatus().clear();
|
||||||
|
|
||||||
|
if (selectedUsers.isEmpty()) {
|
||||||
|
String myEmail = UserManager.getInstance().getUserEmail();
|
||||||
|
taskToEdit.addAssignee(myEmail);
|
||||||
|
if (oldStatus.containsKey(myEmail)) taskToEdit.setParticipantStatus(myEmail, oldStatus.get(myEmail));
|
||||||
|
} else {
|
||||||
|
for (User u : selectedUsers) {
|
||||||
|
taskToEdit.addAssignee(u.getEmail());
|
||||||
|
if (oldStatus.containsKey(u.getEmail())) {
|
||||||
|
taskToEdit.setParticipantStatus(u.getEmail(), oldStatus.get(u.getEmail()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sjekk om tittelen eller beskrivelsen faktisk har endret seg for å sette titlene på nytt
|
||||||
|
// (Vi bruker reflection her eller bare setter verdiene direkte siden de er private i TaskItem)
|
||||||
|
// Siden jeg ikke endret TaskItem til å ha public settlere, antar jeg at du legger til disse
|
||||||
|
// eller at vi bare lager en ny TaskItem med samme ID.
|
||||||
|
|
||||||
|
// Vi simulerer oppdatering av feltene (Sørg for at TaskItem har disse setterene!)
|
||||||
|
// Hvis du ikke har setttere, legg dem til i TaskItem.java:
|
||||||
|
// public void setTitle(String t) { this.title = t; }
|
||||||
|
// public void setDescription(String d) { this.description = d; }
|
||||||
|
// public void setDueDate(long d) { this.dueDate = d; }
|
||||||
|
|
||||||
|
// Jeg skriver logikken slik at den forventer setttere:
|
||||||
|
updateTaskFields(taskToEdit, title, etDesc.getText().toString(), dueDate.getTimeInMillis());
|
||||||
|
|
||||||
|
if (listener != null) listener.onTaskUpdated(taskToEdit);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// NY OPPGAVE MODUS
|
||||||
|
TaskItem newTask = new TaskItem(title, etDesc.getText().toString(), dueDate.getTimeInMillis());
|
||||||
|
if (selectedUsers.isEmpty()) {
|
||||||
|
newTask.addAssignee(UserManager.getInstance().getUserEmail());
|
||||||
|
} else {
|
||||||
|
for (User u : selectedUsers) newTask.addAssignee(u.getEmail());
|
||||||
|
}
|
||||||
|
if (listener != null) listener.onTaskAdded(newTask);
|
||||||
|
}
|
||||||
dismiss();
|
dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hjelpemetode (forutsetter at du legger til disse tre setterne i TaskItem.java)
|
||||||
|
private void updateTaskFields(TaskItem t, String title, String desc, long date) {
|
||||||
|
// Her kaller vi setterne vi nå legger til i TaskItem
|
||||||
|
// Se punkt 5 nedenfor for oppdatert TaskItem.java
|
||||||
|
t.setTitle(title);
|
||||||
|
t.setDescription(desc);
|
||||||
|
t.setDueDate(date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,7 +6,6 @@ import android.os.Looper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
@ -15,6 +14,7 @@ import androidx.fragment.app.Fragment;
|
||||||
import androidx.navigation.Navigation;
|
import androidx.navigation.Navigation;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
|
|
@ -26,7 +26,7 @@ public class CalendarFullFragment extends Fragment {
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private TextView emptyView;
|
private TextView emptyView;
|
||||||
private Button btnAddEvent;
|
private FloatingActionButton fabAddEvent;
|
||||||
private LinearLayoutManager layoutManager;
|
private LinearLayoutManager layoutManager;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
@ -41,16 +41,14 @@ public class CalendarFullFragment extends Fragment {
|
||||||
recyclerView = view.findViewById(R.id.recycler_full_calendar);
|
recyclerView = view.findViewById(R.id.recycler_full_calendar);
|
||||||
progressBar = view.findViewById(R.id.loading_full_calendar);
|
progressBar = view.findViewById(R.id.loading_full_calendar);
|
||||||
emptyView = view.findViewById(R.id.empty_view_calendar);
|
emptyView = view.findViewById(R.id.empty_view_calendar);
|
||||||
btnAddEvent = view.findViewById(R.id.btn_add_calendar_event);
|
fabAddEvent = view.findViewById(R.id.fab_add_calendar_event);
|
||||||
|
|
||||||
layoutManager = new LinearLayoutManager(getContext());
|
layoutManager = new LinearLayoutManager(getContext());
|
||||||
recyclerView.setLayoutManager(layoutManager);
|
recyclerView.setLayoutManager(layoutManager);
|
||||||
|
|
||||||
// VIKTIG: Ingen referanse til btn_back_calendar her lenger.
|
|
||||||
|
|
||||||
if (!UserManager.getInstance().getWriteableCalendars().isEmpty() || UserManager.getInstance().isEditorOrAbove()) {
|
if (!UserManager.getInstance().getWriteableCalendars().isEmpty() || UserManager.getInstance().isEditorOrAbove()) {
|
||||||
btnAddEvent.setVisibility(View.VISIBLE);
|
fabAddEvent.setVisibility(View.VISIBLE);
|
||||||
btnAddEvent.setOnClickListener(v -> Navigation.findNavController(view).navigate(R.id.navigation_create_event));
|
fabAddEvent.setOnClickListener(v -> Navigation.findNavController(view).navigate(R.id.navigation_create_event));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,25 @@ package com.kbs.kbsintranett;
|
||||||
|
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.cardview.widget.CardView;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
|
|
||||||
|
|
@ -21,17 +28,21 @@ public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
public static final int TYPE_SECTION_TITLE = 2;
|
public static final int TYPE_SECTION_TITLE = 2;
|
||||||
public static final int TYPE_CALENDAR_ITEM = 3;
|
public static final int TYPE_CALENDAR_ITEM = 3;
|
||||||
public static final int TYPE_NEWS_ITEM = 4;
|
public static final int TYPE_NEWS_ITEM = 4;
|
||||||
|
public static final int TYPE_TASK_ITEM = 5;
|
||||||
|
public static final int TYPE_EMPTY_TASKS = 6;
|
||||||
|
|
||||||
private final List<Object> items;
|
private final List<Object> items;
|
||||||
private final OnHomeClickListener listener;
|
private final OnHomeClickListener listener;
|
||||||
|
|
||||||
public interface OnHomeClickListener {
|
public interface OnHomeClickListener {
|
||||||
void onProfileClick();
|
|
||||||
void onCreateEventClick();
|
void onCreateEventClick();
|
||||||
void onViewAllCalendarClick();
|
void onViewAllCalendarClick();
|
||||||
void onViewAllNewsClick();
|
void onViewAllNewsClick();
|
||||||
|
void onViewAllTasksClick();
|
||||||
void onCalendarItemClick(CalendarEvent event);
|
void onCalendarItemClick(CalendarEvent event);
|
||||||
void onNewsItemClick(WpPost post);
|
void onNewsItemClick(WpPost post);
|
||||||
|
void onTaskItemClick(TaskItem task);
|
||||||
|
void onTaskStatusChanged(TaskItem task, boolean isDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HomeAdapter(List<Object> items, OnHomeClickListener listener) {
|
public HomeAdapter(List<Object> items, OnHomeClickListener listener) {
|
||||||
|
|
@ -46,6 +57,8 @@ public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
if (item instanceof SectionTitleItem) return TYPE_SECTION_TITLE;
|
if (item instanceof SectionTitleItem) return TYPE_SECTION_TITLE;
|
||||||
if (item instanceof CalendarEvent) return TYPE_CALENDAR_ITEM;
|
if (item instanceof CalendarEvent) return TYPE_CALENDAR_ITEM;
|
||||||
if (item instanceof WpPost) return TYPE_NEWS_ITEM;
|
if (item instanceof WpPost) return TYPE_NEWS_ITEM;
|
||||||
|
if (item instanceof TaskItem) return TYPE_TASK_ITEM;
|
||||||
|
if (item instanceof EmptyTasksItem) return TYPE_EMPTY_TASKS;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,6 +73,10 @@ public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
return new SectionTitleViewHolder(inflater.inflate(R.layout.item_home_section_title, parent, false));
|
return new SectionTitleViewHolder(inflater.inflate(R.layout.item_home_section_title, parent, false));
|
||||||
case TYPE_CALENDAR_ITEM:
|
case TYPE_CALENDAR_ITEM:
|
||||||
return new CalendarViewHolder(inflater.inflate(R.layout.item_calendar, parent, false));
|
return new CalendarViewHolder(inflater.inflate(R.layout.item_calendar, parent, false));
|
||||||
|
case TYPE_TASK_ITEM:
|
||||||
|
return new TaskViewHolder(inflater.inflate(R.layout.item_task, parent, false));
|
||||||
|
case TYPE_EMPTY_TASKS:
|
||||||
|
return new EmptyViewHolder(inflater.inflate(R.layout.item_home_empty_tasks, parent, false));
|
||||||
case TYPE_NEWS_ITEM:
|
case TYPE_NEWS_ITEM:
|
||||||
return new NewsViewHolder(inflater.inflate(R.layout.item_news, parent, false));
|
return new NewsViewHolder(inflater.inflate(R.layout.item_news, parent, false));
|
||||||
default:
|
default:
|
||||||
|
|
@ -79,7 +96,8 @@ public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
SectionTitleViewHolder vh = (SectionTitleViewHolder) holder;
|
SectionTitleViewHolder vh = (SectionTitleViewHolder) holder;
|
||||||
vh.title.setText(section.title);
|
vh.title.setText(section.title);
|
||||||
vh.btnViewAll.setOnClickListener(v -> {
|
vh.btnViewAll.setOnClickListener(v -> {
|
||||||
if (section.isCalendar) listener.onViewAllCalendarClick();
|
if (section.type == SectionTitleItem.TYPE_CALENDAR) listener.onViewAllCalendarClick();
|
||||||
|
else if (section.type == SectionTitleItem.TYPE_TASKS) listener.onViewAllTasksClick();
|
||||||
else listener.onViewAllNewsClick();
|
else listener.onViewAllNewsClick();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -90,28 +108,49 @@ public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
vh.month.setText(event.getMonth());
|
vh.month.setText(event.getMonth());
|
||||||
vh.time.setText(event.getTime());
|
vh.time.setText(event.getTime());
|
||||||
vh.title.setText(event.getTitle());
|
vh.title.setText(event.getTitle());
|
||||||
|
|
||||||
boolean isPrivate = event.getDescription() != null && event.getDescription().contains("#deltakere:");
|
boolean isPrivate = event.getDescription() != null && event.getDescription().contains("#deltakere:");
|
||||||
int color;
|
|
||||||
try {
|
try {
|
||||||
color = Color.parseColor(isPrivate ? "#673AB7" : event.getCalendarColor());
|
int color = Color.parseColor(isPrivate ? "#673AB7" : event.getCalendarColor());
|
||||||
|
vh.dateBox.setBackgroundTintList(ColorStateList.valueOf(color));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
color = Color.parseColor("#0069B3");
|
vh.dateBox.setBackgroundTintList(ColorStateList.valueOf(Color.parseColor("#0069B3")));
|
||||||
}
|
}
|
||||||
vh.dateBox.setBackgroundTintList(ColorStateList.valueOf(color));
|
|
||||||
vh.itemView.setOnClickListener(v -> listener.onCalendarItemClick(event));
|
vh.itemView.setOnClickListener(v -> listener.onCalendarItemClick(event));
|
||||||
}
|
}
|
||||||
|
else if (holder instanceof TaskViewHolder) {
|
||||||
|
TaskItem task = (TaskItem) item;
|
||||||
|
TaskViewHolder vh = (TaskViewHolder) holder;
|
||||||
|
vh.title.setText(task.getTitle());
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("dd. MMM", Locale.getDefault());
|
||||||
|
vh.date.setText("Frist: " + sdf.format(new Date(task.getDueDate())));
|
||||||
|
|
||||||
|
String myEmail = UserManager.getInstance().getUserEmail();
|
||||||
|
boolean myStatus = task.getParticipantStatus(myEmail);
|
||||||
|
vh.checkBox.setChecked(myStatus);
|
||||||
|
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
boolean isOverdue = task.getDueDate() < now && !task.isFullyCompleted() && !myStatus;
|
||||||
|
|
||||||
|
if (isOverdue) {
|
||||||
|
vh.cardView.setCardBackgroundColor(ContextCompat.getColor(vh.itemView.getContext(), R.color.kbs_soft_light_pink_beige));
|
||||||
|
vh.date.setTextColor(ContextCompat.getColor(vh.itemView.getContext(), R.color.kbs_logo_accent_red));
|
||||||
|
} else {
|
||||||
|
vh.cardView.setCardBackgroundColor(Color.WHITE);
|
||||||
|
vh.date.setTextColor(ContextCompat.getColor(vh.itemView.getContext(), R.color.kbs_muted_blue_gray));
|
||||||
|
}
|
||||||
|
|
||||||
|
vh.checkBox.setOnClickListener(v -> listener.onTaskStatusChanged(task, vh.checkBox.isChecked()));
|
||||||
|
vh.itemView.setOnClickListener(v -> listener.onTaskItemClick(task));
|
||||||
|
}
|
||||||
else if (holder instanceof NewsViewHolder) {
|
else if (holder instanceof NewsViewHolder) {
|
||||||
WpPost post = (WpPost) item;
|
WpPost post = (WpPost) item;
|
||||||
NewsViewHolder vh = (NewsViewHolder) holder;
|
NewsViewHolder vh = (NewsViewHolder) holder;
|
||||||
vh.title.setText(post.getTitleStr());
|
vh.title.setText(post.getTitleStr());
|
||||||
vh.excerpt.setText(post.getExcerptStr());
|
vh.excerpt.setText(post.getExcerptStr());
|
||||||
vh.date.setText(post.date);
|
vh.date.setText(post.date);
|
||||||
|
|
||||||
String cat = post.getCategoryName();
|
String cat = post.getCategoryName();
|
||||||
vh.category.setText(cat);
|
vh.category.setText(cat);
|
||||||
vh.category.setVisibility(cat.isEmpty() ? View.GONE : View.VISIBLE);
|
vh.category.setVisibility(cat.isEmpty() ? View.GONE : View.VISIBLE);
|
||||||
|
|
||||||
String imgUrl = post.getFeaturedImageUrl();
|
String imgUrl = post.getFeaturedImageUrl();
|
||||||
if (imgUrl != null) {
|
if (imgUrl != null) {
|
||||||
vh.image.setVisibility(View.VISIBLE);
|
vh.image.setVisibility(View.VISIBLE);
|
||||||
|
|
@ -129,7 +168,6 @@ public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- VIEW HOLDERS ---
|
// --- VIEW HOLDERS ---
|
||||||
|
|
||||||
static class CreateButtonViewHolder extends RecyclerView.ViewHolder {
|
static class CreateButtonViewHolder extends RecyclerView.ViewHolder {
|
||||||
Button btnCreate;
|
Button btnCreate;
|
||||||
CreateButtonViewHolder(View v) { super(v); btnCreate = v.findViewById(R.id.btn_create_event); }
|
CreateButtonViewHolder(View v) { super(v); btnCreate = v.findViewById(R.id.btn_create_event); }
|
||||||
|
|
@ -143,13 +181,26 @@ public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
static class CalendarViewHolder extends RecyclerView.ViewHolder {
|
static class CalendarViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView day, month, title, time;
|
TextView day, month, title, time;
|
||||||
LinearLayout dateBox;
|
LinearLayout dateBox;
|
||||||
CalendarViewHolder(View v) {
|
CalendarViewHolder(View view) {
|
||||||
|
super(view);
|
||||||
|
day = view.findViewById(R.id.cal_day);
|
||||||
|
month = view.findViewById(R.id.cal_month);
|
||||||
|
title = view.findViewById(R.id.cal_title);
|
||||||
|
time = view.findViewById(R.id.cal_time);
|
||||||
|
dateBox = view.findViewById(R.id.date_box_background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TaskViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView title, date;
|
||||||
|
CheckBox checkBox;
|
||||||
|
CardView cardView;
|
||||||
|
TaskViewHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
day = v.findViewById(R.id.cal_day);
|
title = v.findViewById(R.id.task_title);
|
||||||
month = v.findViewById(R.id.cal_month);
|
date = v.findViewById(R.id.task_date);
|
||||||
title = v.findViewById(R.id.cal_title);
|
checkBox = v.findViewById(R.id.task_checkbox);
|
||||||
time = v.findViewById(R.id.cal_time);
|
cardView = (CardView) v;
|
||||||
dateBox = v.findViewById(R.id.date_box_background);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,10 +217,18 @@ public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class EmptyViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
EmptyViewHolder(View v) { super(v); }
|
||||||
|
}
|
||||||
|
|
||||||
// --- WRAPPER KLASSER ---
|
// --- WRAPPER KLASSER ---
|
||||||
public static class CreateButtonItem {}
|
public static class CreateButtonItem {}
|
||||||
|
public static class EmptyTasksItem {}
|
||||||
public static class SectionTitleItem {
|
public static class SectionTitleItem {
|
||||||
String title; boolean isCalendar;
|
public static final int TYPE_CALENDAR = 0;
|
||||||
public SectionTitleItem(String t, boolean c) { this.title = t; this.isCalendar = c; }
|
public static final int TYPE_NEWS = 1;
|
||||||
|
public static final int TYPE_TASKS = 2;
|
||||||
|
String title; int type;
|
||||||
|
public SectionTitleItem(String t, int type) { this.title = t; this.type = type; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.Toast;
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
@ -19,8 +20,10 @@ import androidx.navigation.Navigation;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
@ -37,6 +40,7 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis
|
||||||
|
|
||||||
private List<CalendarEvent> currentEvents = new ArrayList<>();
|
private List<CalendarEvent> currentEvents = new ArrayList<>();
|
||||||
private List<WpPost> currentNews = new ArrayList<>();
|
private List<WpPost> currentNews = new ArrayList<>();
|
||||||
|
private List<TaskItem> currentTasks = new ArrayList<>();
|
||||||
private int activeNetworkCalls = 0;
|
private int activeNetworkCalls = 0;
|
||||||
|
|
||||||
private ActivityResultLauncher<String> requestPermissionLauncher;
|
private ActivityResultLauncher<String> requestPermissionLauncher;
|
||||||
|
|
@ -67,22 +71,17 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
swipeRefreshLayout.setOnRefreshListener(this::refreshData);
|
swipeRefreshLayout.setOnRefreshListener(this::refreshData);
|
||||||
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 33) {
|
|
||||||
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshData();
|
refreshData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshData() {
|
private void refreshData() {
|
||||||
if (activeNetworkCalls > 0) return;
|
if (activeNetworkCalls > 0) return;
|
||||||
activeNetworkCalls = 2;
|
activeNetworkCalls = 3;
|
||||||
if (mainProgressBar != null) mainProgressBar.setVisibility(View.VISIBLE);
|
if (mainProgressBar != null) mainProgressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
fetchCalendarData();
|
fetchCalendarData();
|
||||||
fetchNewsData();
|
fetchNewsData();
|
||||||
|
fetchTaskData();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fetchCalendarData() {
|
private void fetchCalendarData() {
|
||||||
|
|
@ -106,12 +105,10 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis
|
||||||
} else {
|
} else {
|
||||||
apiEvents = CacheManager.getCachedCalendarEvents(getContext());
|
apiEvents = CacheManager.getCachedCalendarEvents(getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CalendarEvent e : apiEvents) CalendarManager.formatEventForUI(e);
|
for (CalendarEvent e : apiEvents) CalendarManager.formatEventForUI(e);
|
||||||
currentEvents = CalendarManager.mergeAndSort(apiEvents, deviceEvents);
|
currentEvents = CalendarManager.mergeAndSort(apiEvents, deviceEvents);
|
||||||
checkLoadingComplete();
|
checkLoadingComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call<List<CalendarEvent>> call, Throwable t) {
|
public void onFailure(Call<List<CalendarEvent>> call, Throwable t) {
|
||||||
List<CalendarEvent> cached = CacheManager.getCachedCalendarEvents(getContext());
|
List<CalendarEvent> cached = CacheManager.getCachedCalendarEvents(getContext());
|
||||||
|
|
@ -137,7 +134,6 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis
|
||||||
formatNewsDates(currentNews);
|
formatNewsDates(currentNews);
|
||||||
checkLoadingComplete();
|
checkLoadingComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Call<List<WpPost>> call, Throwable t) {
|
public void onFailure(Call<List<WpPost>> call, Throwable t) {
|
||||||
currentNews = CacheManager.getCachedNewsPosts(getContext());
|
currentNews = CacheManager.getCachedNewsPosts(getContext());
|
||||||
|
|
@ -147,6 +143,26 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fetchTaskData() {
|
||||||
|
RetrofitClient.getApiService().getTasks().enqueue(new Callback<List<TaskItem>>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<List<TaskItem>> call, Response<List<TaskItem>> response) {
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
currentTasks = response.body();
|
||||||
|
CacheManager.saveTasks(getContext(), currentTasks);
|
||||||
|
} else {
|
||||||
|
currentTasks = CacheManager.getTasks(getContext());
|
||||||
|
}
|
||||||
|
checkLoadingComplete();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<List<TaskItem>> call, Throwable t) {
|
||||||
|
currentTasks = CacheManager.getTasks(getContext());
|
||||||
|
checkLoadingComplete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void formatNewsDates(List<WpPost> posts) {
|
private void formatNewsDates(List<WpPost> posts) {
|
||||||
SimpleDateFormat rawFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
|
SimpleDateFormat rawFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
|
||||||
SimpleDateFormat targetFormat = new SimpleDateFormat("dd. MMM yyyy", Locale.getDefault());
|
SimpleDateFormat targetFormat = new SimpleDateFormat("dd. MMM yyyy", Locale.getDefault());
|
||||||
|
|
@ -170,45 +186,97 @@ public class HomeFragment extends Fragment implements HomeAdapter.OnHomeClickLis
|
||||||
|
|
||||||
private void buildAndDisplayList() {
|
private void buildAndDisplayList() {
|
||||||
List<Object> items = new ArrayList<>();
|
List<Object> items = new ArrayList<>();
|
||||||
|
String myEmail = UserManager.getInstance().getUserEmail();
|
||||||
|
|
||||||
// 1. Kalender Seksjon (Knappen "Ny hendelse" er fjernet herfra)
|
items.add(new HomeAdapter.SectionTitleItem("Kommende hendelser", HomeAdapter.SectionTitleItem.TYPE_CALENDAR));
|
||||||
items.add(new HomeAdapter.SectionTitleItem("Kommende hendelser", true));
|
|
||||||
String today = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
|
String today = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
|
||||||
int count = 0;
|
int calCount = 0;
|
||||||
for (CalendarEvent e : currentEvents) {
|
for (CalendarEvent e : currentEvents) {
|
||||||
if (e.getRawDate() != null && e.getRawDate().compareTo(today) >= 0) {
|
if (e.getRawDate() != null && e.getRawDate().compareTo(today) >= 0) {
|
||||||
items.add(e);
|
items.add(e);
|
||||||
count++;
|
calCount++;
|
||||||
}
|
}
|
||||||
if (count >= 3) break;
|
if (calCount >= 3) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Nyheter Seksjon
|
items.add(new HomeAdapter.SectionTitleItem("Mine oppgaver", HomeAdapter.SectionTitleItem.TYPE_TASKS));
|
||||||
items.add(new HomeAdapter.SectionTitleItem("Siste nytt", false));
|
List<TaskItem> myActiveTasks = new ArrayList<>();
|
||||||
|
for (TaskItem t : currentTasks) {
|
||||||
|
if (t.isUserParticipant(myEmail) && !t.getParticipantStatus(myEmail) && !t.isFullyCompleted()) {
|
||||||
|
myActiveTasks.add(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myActiveTasks.isEmpty()) {
|
||||||
|
items.add(new HomeAdapter.EmptyTasksItem());
|
||||||
|
} else {
|
||||||
|
Collections.sort(myActiveTasks, (t1, t2) -> Long.compare(t1.getDueDate(), t2.getDueDate()));
|
||||||
|
for (int i = 0; i < Math.min(myActiveTasks.size(), 3); i++) {
|
||||||
|
items.add(myActiveTasks.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items.add(new HomeAdapter.SectionTitleItem("Siste nytt", HomeAdapter.SectionTitleItem.TYPE_NEWS));
|
||||||
items.addAll(currentNews);
|
items.addAll(currentNews);
|
||||||
|
|
||||||
adapter = new HomeAdapter(items, this);
|
adapter = new HomeAdapter(items, this);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onProfileClick() {}
|
@Override public void onCreateEventClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_create_event); }
|
||||||
@Override public void onCreateEventClick() {
|
@Override public void onViewAllCalendarClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_calendar_full); }
|
||||||
Navigation.findNavController(getView()).navigate(R.id.navigation_create_event);
|
@Override public void onViewAllNewsClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_news_full); }
|
||||||
}
|
@Override public void onViewAllTasksClick() { Navigation.findNavController(getView()).navigate(R.id.navigation_tasks); }
|
||||||
@Override public void onViewAllCalendarClick() {
|
|
||||||
Navigation.findNavController(getView()).navigate(R.id.navigation_calendar_full);
|
|
||||||
}
|
|
||||||
@Override public void onViewAllNewsClick() {
|
|
||||||
Navigation.findNavController(getView()).navigate(R.id.navigation_news_full);
|
|
||||||
}
|
|
||||||
@Override public void onCalendarItemClick(CalendarEvent event) {
|
@Override public void onCalendarItemClick(CalendarEvent event) {
|
||||||
CalendarDetailsBottomSheet sheet = new CalendarDetailsBottomSheet(event);
|
CalendarDetailsBottomSheet sheet = new CalendarDetailsBottomSheet(event);
|
||||||
sheet.setOnEventChangeListener(this::refreshData);
|
sheet.setOnEventChangeListener(this::refreshData);
|
||||||
sheet.show(getParentFragmentManager(), "CalendarDetails");
|
sheet.show(getParentFragmentManager(), "CalendarDetails");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onNewsItemClick(WpPost post) {
|
@Override public void onNewsItemClick(WpPost post) {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putSerializable("post_data", post);
|
bundle.putSerializable("post_data", post);
|
||||||
Navigation.findNavController(getView()).navigate(R.id.navigation_news_detail, bundle);
|
Navigation.findNavController(getView()).navigate(R.id.navigation_news_detail, bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void onTaskItemClick(TaskItem task) {
|
||||||
|
TaskDetailsBottomSheet sheet = new TaskDetailsBottomSheet(task, new TaskDetailsBottomSheet.OnTaskChangeListener() {
|
||||||
|
@Override public void onTaskChanged() { saveAndSyncTasks(); }
|
||||||
|
@Override public void onTaskDeleted(TaskItem taskToDelete) {
|
||||||
|
currentTasks.remove(taskToDelete);
|
||||||
|
saveAndSyncTasks();
|
||||||
|
}
|
||||||
|
@Override public void onEditRequested(TaskItem taskToEdit) {
|
||||||
|
AddTaskBottomSheet editDialog = new AddTaskBottomSheet();
|
||||||
|
editDialog.setTaskToEdit(taskToEdit);
|
||||||
|
editDialog.setOnTaskAddedListener(new AddTaskBottomSheet.OnTaskAddedListener() {
|
||||||
|
@Override public void onTaskAdded(TaskItem task) {}
|
||||||
|
@Override public void onTaskUpdated(TaskItem task) {
|
||||||
|
saveAndSyncTasks();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editDialog.show(getChildFragmentManager(), "EditTask");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sheet.show(getChildFragmentManager(), "TaskDetails");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void onTaskStatusChanged(TaskItem task, boolean isDone) {
|
||||||
|
String myEmail = UserManager.getInstance().getUserEmail();
|
||||||
|
task.setParticipantStatus(myEmail, isDone);
|
||||||
|
if (task.getCreatedByEmail().equalsIgnoreCase(myEmail) && isDone) {
|
||||||
|
task.setFullyCompleted(true);
|
||||||
|
}
|
||||||
|
saveAndSyncTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveAndSyncTasks() {
|
||||||
|
CacheManager.saveTasks(getContext(), currentTasks);
|
||||||
|
buildAndDisplayList();
|
||||||
|
RetrofitClient.getApiService().syncTasks(currentTasks).enqueue(new Callback<JsonElement>() {
|
||||||
|
@Override public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {}
|
||||||
|
@Override public void onFailure(Call<JsonElement> call, Throwable t) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -40,10 +40,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
// Din oppdaterte linje:
|
|
||||||
public static final String GOOGLE_WEB_CLIENT_ID = BuildConfig.WEB_CLIENT_ID;
|
public static final String GOOGLE_WEB_CLIENT_ID = BuildConfig.WEB_CLIENT_ID;
|
||||||
|
|
||||||
private static final String TAG = "MainActivity";
|
|
||||||
private NavController navController;
|
private NavController navController;
|
||||||
private DrawerLayout drawerLayout;
|
private DrawerLayout drawerLayout;
|
||||||
private AppBarConfiguration appBarConfiguration;
|
private AppBarConfiguration appBarConfiguration;
|
||||||
|
|
@ -73,7 +70,18 @@ public class MainActivity extends AppCompatActivity {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
||||||
NavigationUI.setupWithNavController(navigationView, navController);
|
|
||||||
|
// Vi bruker en tilpasset listener for å sikre at Hjem og andre punkter alltid fungerer
|
||||||
|
navigationView.setNavigationItemSelectedListener(item -> {
|
||||||
|
boolean handled = NavigationUI.onNavDestinationSelected(item, navController);
|
||||||
|
if (handled || item.getItemId() == R.id.navigation_home) {
|
||||||
|
if (item.getItemId() == R.id.navigation_home) {
|
||||||
|
navController.navigate(R.id.navigation_home);
|
||||||
|
}
|
||||||
|
drawerLayout.closeDrawer(GravityCompat.START);
|
||||||
|
}
|
||||||
|
return handled;
|
||||||
|
});
|
||||||
|
|
||||||
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
||||||
if (destination.getId() == R.id.navigation_login) {
|
if (destination.getId() == R.id.navigation_login) {
|
||||||
|
|
@ -82,7 +90,6 @@ public class MainActivity extends AppCompatActivity {
|
||||||
} else {
|
} else {
|
||||||
toolbar.setVisibility(View.VISIBLE);
|
toolbar.setVisibility(View.VISIBLE);
|
||||||
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
|
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
|
||||||
// Oppdater navn hver gang vi bytter skjerm for å være sikker
|
|
||||||
updateNavHeader(navigationView);
|
updateNavHeader(navigationView);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -90,9 +97,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
setupTaskReminders();
|
setupTaskReminders();
|
||||||
createNotificationChannel();
|
createNotificationChannel();
|
||||||
|
|
||||||
requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {});
|
requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> {});
|
||||||
|
|
||||||
checkNotificationPermission();
|
checkNotificationPermission();
|
||||||
checkExactAlarmPermission();
|
checkExactAlarmPermission();
|
||||||
checkLoginState();
|
checkLoginState();
|
||||||
|
|
@ -102,7 +107,6 @@ public class MainActivity extends AppCompatActivity {
|
||||||
View headerView = navigationView.getHeaderView(0);
|
View headerView = navigationView.getHeaderView(0);
|
||||||
TextView name = headerView.findViewById(R.id.nav_header_name);
|
TextView name = headerView.findViewById(R.id.nav_header_name);
|
||||||
TextView email = headerView.findViewById(R.id.nav_header_email);
|
TextView email = headerView.findViewById(R.id.nav_header_email);
|
||||||
|
|
||||||
UserManager user = UserManager.getInstance();
|
UserManager user = UserManager.getInstance();
|
||||||
if (user.isLoggedIn()) {
|
if (user.isLoggedIn()) {
|
||||||
name.setText(user.getUserDisplayName());
|
name.setText(user.getUserDisplayName());
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
@ -30,7 +29,7 @@ public class NewsFullFragment extends Fragment {
|
||||||
private RecyclerView recyclerViewCategories;
|
private RecyclerView recyclerViewCategories;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private NewsAdapter newsAdapter;
|
private NewsAdapter newsAdapter;
|
||||||
private List<WpPost> allPosts = new ArrayList<>(); // Holder på ALLE postene
|
private List<WpPost> allPosts = new ArrayList<>();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -45,7 +44,6 @@ public class NewsFullFragment extends Fragment {
|
||||||
recyclerViewNews = view.findViewById(R.id.recycler_news_full);
|
recyclerViewNews = view.findViewById(R.id.recycler_news_full);
|
||||||
recyclerViewCategories = view.findViewById(R.id.recycler_categories);
|
recyclerViewCategories = view.findViewById(R.id.recycler_categories);
|
||||||
progressBar = view.findViewById(R.id.loading_news_full);
|
progressBar = view.findViewById(R.id.loading_news_full);
|
||||||
ImageView backBtn = view.findViewById(R.id.btn_back_news);
|
|
||||||
|
|
||||||
// Setup Nyhetsliste
|
// Setup Nyhetsliste
|
||||||
recyclerViewNews.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerViewNews.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
|
@ -54,15 +52,12 @@ public class NewsFullFragment extends Fragment {
|
||||||
recyclerViewCategories.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
|
recyclerViewCategories.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||||
setupCategories();
|
setupCategories();
|
||||||
|
|
||||||
backBtn.setOnClickListener(v -> Navigation.findNavController(view).navigateUp());
|
|
||||||
|
|
||||||
fetchAllNews();
|
fetchAllNews();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupCategories() {
|
private void setupCategories() {
|
||||||
// Listen over kategorier du ønsket
|
|
||||||
List<String> categories = Arrays.asList(
|
List<String> categories = Arrays.asList(
|
||||||
"Alle", // Standard vis alt
|
"Alle",
|
||||||
"Avtaler og invitasjoner", "BHT", "Bilhold", "Cordel",
|
"Avtaler og invitasjoner", "BHT", "Bilhold", "Cordel",
|
||||||
"Ferieavvikling", "Fest og moro", "Generell drift",
|
"Ferieavvikling", "Fest og moro", "Generell drift",
|
||||||
"HMS", "IT og sikkerhet", "Miljøfyrtårn", "Møtereferat", "SMX"
|
"HMS", "IT og sikkerhet", "Miljøfyrtårn", "Møtereferat", "SMX"
|
||||||
|
|
@ -76,7 +71,6 @@ public class NewsFullFragment extends Fragment {
|
||||||
|
|
||||||
private void fetchAllNews() {
|
private void fetchAllNews() {
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
// Hent 50 siste (bør holde for en "Siste nytt" liste, ellers må vi paginere)
|
|
||||||
RetrofitClient.getApiService().getAllPosts().enqueue(new Callback<List<WpPost>>() {
|
RetrofitClient.getApiService().getAllPosts().enqueue(new Callback<List<WpPost>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Call<List<WpPost>> call, Response<List<WpPost>> response) {
|
public void onResponse(Call<List<WpPost>> call, Response<List<WpPost>> response) {
|
||||||
|
|
@ -87,7 +81,6 @@ public class NewsFullFragment extends Fragment {
|
||||||
allPosts = response.body();
|
allPosts = response.body();
|
||||||
formatDates(allPosts);
|
formatDates(allPosts);
|
||||||
|
|
||||||
// Vis alle i starten
|
|
||||||
newsAdapter = new NewsAdapter(new ArrayList<>(allPosts), post -> {
|
newsAdapter = new NewsAdapter(new ArrayList<>(allPosts), post -> {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putSerializable("post_data", post);
|
bundle.putSerializable("post_data", post);
|
||||||
|
|
@ -110,29 +103,23 @@ public class NewsFullFragment extends Fragment {
|
||||||
|
|
||||||
private void filterNews(String category) {
|
private void filterNews(String category) {
|
||||||
if (newsAdapter == null) return;
|
if (newsAdapter == null) return;
|
||||||
|
|
||||||
List<WpPost> filteredList = new ArrayList<>();
|
List<WpPost> filteredList = new ArrayList<>();
|
||||||
|
|
||||||
if (category.equals("Alle")) {
|
if (category.equals("Alle")) {
|
||||||
filteredList.addAll(allPosts);
|
filteredList.addAll(allPosts);
|
||||||
} else {
|
} else {
|
||||||
for (WpPost post : allPosts) {
|
for (WpPost post : allPosts) {
|
||||||
// Vi sjekker om kategorinavnet matcher
|
|
||||||
if (post.getCategoryName().equals(category)) {
|
if (post.getCategoryName().equals(category)) {
|
||||||
filteredList.add(post);
|
filteredList.add(post);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Oppdater adapteren med den filtrerte listen
|
|
||||||
newsAdapter.updateList(filteredList);
|
newsAdapter.updateList(filteredList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void formatDates(List<WpPost> posts) {
|
private void formatDates(List<WpPost> posts) {
|
||||||
SimpleDateFormat rawFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
|
SimpleDateFormat rawFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
|
||||||
rawFormat.setTimeZone(TimeZone.getTimeZone("Europe/Oslo"));
|
|
||||||
SimpleDateFormat targetFormat = new SimpleDateFormat("dd. MMM yyyy", Locale.getDefault());
|
SimpleDateFormat targetFormat = new SimpleDateFormat("dd. MMM yyyy", Locale.getDefault());
|
||||||
targetFormat.setTimeZone(TimeZone.getTimeZone("Europe/Oslo"));
|
|
||||||
|
|
||||||
for (WpPost post : posts) {
|
for (WpPost post : posts) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import android.view.ViewGroup;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.cardview.widget.CardView;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -46,18 +48,38 @@ public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.ViewHolder> {
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("dd. MMM", Locale.getDefault());
|
SimpleDateFormat sdf = new SimpleDateFormat("dd. MMM", Locale.getDefault());
|
||||||
holder.date.setText("Frist: " + sdf.format(new Date(task.getDueDate())));
|
holder.date.setText("Frist: " + sdf.format(new Date(task.getDueDate())));
|
||||||
|
|
||||||
|
// Vis hvem som tildelte oppgaven hvis det ikke er meg selv (Nytt krav)
|
||||||
|
if (task.getCreatedByEmail() != null && !task.getCreatedByEmail().equalsIgnoreCase(currentUserEmail)) {
|
||||||
|
holder.creator.setText("Tildelt av: " + task.getCreatedByName());
|
||||||
|
holder.creator.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
holder.creator.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
boolean myStatus = task.getParticipantStatus(currentUserEmail);
|
boolean myStatus = task.getParticipantStatus(currentUserEmail);
|
||||||
holder.checkBox.setChecked(myStatus);
|
holder.checkBox.setChecked(myStatus);
|
||||||
|
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
boolean isOverdue = task.getDueDate() < now && !task.isFullyCompleted() && !myStatus;
|
||||||
|
|
||||||
|
if (isOverdue) {
|
||||||
|
holder.cardView.setCardBackgroundColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.kbs_soft_light_pink_beige));
|
||||||
|
holder.date.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.kbs_logo_accent_red));
|
||||||
|
holder.date.setText("FORFALT: " + sdf.format(new Date(task.getDueDate())));
|
||||||
|
} else {
|
||||||
|
holder.cardView.setCardBackgroundColor(Color.WHITE);
|
||||||
|
holder.date.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.kbs_muted_blue_gray));
|
||||||
|
}
|
||||||
|
|
||||||
if (myStatus || task.isFullyCompleted()) {
|
if (myStatus || task.isFullyCompleted()) {
|
||||||
holder.title.setPaintFlags(holder.title.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
holder.title.setPaintFlags(holder.title.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
|
||||||
holder.title.setTextColor(Color.GRAY);
|
holder.title.setTextColor(Color.GRAY);
|
||||||
} else {
|
holder.cardView.setCardBackgroundColor(Color.parseColor("#F5F5F5"));
|
||||||
|
} else if (!isOverdue) {
|
||||||
holder.title.setPaintFlags(holder.title.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
|
holder.title.setPaintFlags(holder.title.getPaintFlags() & (~Paint.STRIKE_THRU_TEXT_FLAG));
|
||||||
holder.title.setTextColor(Color.BLACK);
|
holder.title.setTextColor(Color.BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vis fremdrift (f.eks 1/3 fullført)
|
|
||||||
int total = task.getAssigneeStatus().size();
|
int total = task.getAssigneeStatus().size();
|
||||||
int done = 0;
|
int done = 0;
|
||||||
for (Boolean b : task.getAssigneeStatus().values()) if (b) done++;
|
for (Boolean b : task.getAssigneeStatus().values()) if (b) done++;
|
||||||
|
|
@ -71,14 +93,17 @@ public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.ViewHolder> {
|
||||||
public int getItemCount() { return tasks.size(); }
|
public int getItemCount() { return tasks.size(); }
|
||||||
|
|
||||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView title, date, progress;
|
TextView title, date, creator, progress;
|
||||||
CheckBox checkBox;
|
CheckBox checkBox;
|
||||||
|
CardView cardView;
|
||||||
ViewHolder(View v) {
|
ViewHolder(View v) {
|
||||||
super(v);
|
super(v);
|
||||||
title = v.findViewById(R.id.task_title);
|
title = v.findViewById(R.id.task_title);
|
||||||
date = v.findViewById(R.id.task_date);
|
date = v.findViewById(R.id.task_date);
|
||||||
|
creator = v.findViewById(R.id.task_creator);
|
||||||
progress = v.findViewById(R.id.task_progress);
|
progress = v.findViewById(R.id.task_progress);
|
||||||
checkBox = v.findViewById(R.id.task_checkbox);
|
checkBox = v.findViewById(R.id.task_checkbox);
|
||||||
|
cardView = (CardView) v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.kbs.kbsintranett;
|
package com.kbs.kbsintranett;
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
@ -25,6 +24,7 @@ public class TaskDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||||
public interface OnTaskChangeListener {
|
public interface OnTaskChangeListener {
|
||||||
void onTaskChanged();
|
void onTaskChanged();
|
||||||
void onTaskDeleted(TaskItem task);
|
void onTaskDeleted(TaskItem task);
|
||||||
|
void onEditRequested(TaskItem task); // NYTT
|
||||||
}
|
}
|
||||||
|
|
||||||
public TaskDetailsBottomSheet(TaskItem task, OnTaskChangeListener listener) {
|
public TaskDetailsBottomSheet(TaskItem task, OnTaskChangeListener listener) {
|
||||||
|
|
@ -42,7 +42,9 @@ public class TaskDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||||
TextView desc = v.findViewById(R.id.detail_task_desc);
|
TextView desc = v.findViewById(R.id.detail_task_desc);
|
||||||
LinearLayout participantsContainer = v.findViewById(R.id.container_participants_status);
|
LinearLayout participantsContainer = v.findViewById(R.id.container_participants_status);
|
||||||
SwitchMaterial switchNotify = v.findViewById(R.id.switch_notifications);
|
SwitchMaterial switchNotify = v.findViewById(R.id.switch_notifications);
|
||||||
|
LinearLayout ownerActions = v.findViewById(R.id.layout_owner_actions);
|
||||||
Button btnDelete = v.findViewById(R.id.btn_delete_task);
|
Button btnDelete = v.findViewById(R.id.btn_delete_task);
|
||||||
|
Button btnEdit = v.findViewById(R.id.btn_edit_task);
|
||||||
|
|
||||||
title.setText(task.getTitle());
|
title.setText(task.getTitle());
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("EEEE dd. MMMM yyyy", Locale.getDefault());
|
SimpleDateFormat sdf = new SimpleDateFormat("EEEE dd. MMMM yyyy", Locale.getDefault());
|
||||||
|
|
@ -53,7 +55,7 @@ public class TaskDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||||
desc.setVisibility(View.VISIBLE);
|
desc.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// List opp alle deltakere og deres status
|
participantsContainer.removeAllViews();
|
||||||
for (Map.Entry<String, Boolean> entry : task.getAssigneeStatus().entrySet()) {
|
for (Map.Entry<String, Boolean> entry : task.getAssigneeStatus().entrySet()) {
|
||||||
TextView t = new TextView(getContext());
|
TextView t = new TextView(getContext());
|
||||||
String status = entry.getValue() ? "✅ Fullført" : "⏳ Pågår";
|
String status = entry.getValue() ? "✅ Fullført" : "⏳ Pågår";
|
||||||
|
|
@ -68,13 +70,16 @@ public class TaskDetailsBottomSheet extends BottomSheetDialogFragment {
|
||||||
if (listener != null) listener.onTaskChanged();
|
if (listener != null) listener.onTaskChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Kun eier kan slette oppgaven
|
if (task.getCreatedByEmail().equalsIgnoreCase(UserManager.getInstance().getUserEmail())) {
|
||||||
if (task.getCreatedByEmail().equals(UserManager.getInstance().getUserEmail())) {
|
ownerActions.setVisibility(View.VISIBLE);
|
||||||
btnDelete.setVisibility(View.VISIBLE);
|
|
||||||
btnDelete.setOnClickListener(view -> {
|
btnDelete.setOnClickListener(view -> {
|
||||||
if (listener != null) listener.onTaskDeleted(task);
|
if (listener != null) listener.onTaskDeleted(task);
|
||||||
dismiss();
|
dismiss();
|
||||||
});
|
});
|
||||||
|
btnEdit.setOnClickListener(view -> {
|
||||||
|
if (listener != null) listener.onEditRequested(task);
|
||||||
|
dismiss();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,10 @@ public class TaskItem implements Serializable {
|
||||||
private String createdByEmail;
|
private String createdByEmail;
|
||||||
private String createdByName;
|
private String createdByName;
|
||||||
|
|
||||||
// Key: Bruker-epost, Value: Har fullført (true/false)
|
|
||||||
private Map<String, Boolean> assigneeStatus = new HashMap<>();
|
private Map<String, Boolean> assigneeStatus = new HashMap<>();
|
||||||
|
|
||||||
private boolean notificationsEnabled = true;
|
private boolean notificationsEnabled = true;
|
||||||
private boolean isFullyCompleted = false; // Satt av eier eller når alle er ferdige
|
private boolean isFullyCompleted = false;
|
||||||
|
|
||||||
public TaskItem(String title, String description, long dueDate) {
|
public TaskItem(String title, String description, long dueDate) {
|
||||||
this.id = UUID.randomUUID().toString();
|
this.id = UUID.randomUUID().toString();
|
||||||
|
|
@ -28,15 +27,7 @@ public class TaskItem implements Serializable {
|
||||||
this.createdByName = UserManager.getInstance().getUserDisplayName();
|
this.createdByName = UserManager.getInstance().getUserDisplayName();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hjelpemetoder
|
// Getters
|
||||||
public void addAssignee(String email) { assigneeStatus.put(email, false); }
|
|
||||||
public void setParticipantStatus(String email, boolean done) { assigneeStatus.put(email, done); }
|
|
||||||
public boolean getParticipantStatus(String email) { return assigneeStatus.getOrDefault(email, false); }
|
|
||||||
|
|
||||||
public boolean isUserParticipant(String email) { return assigneeStatus.containsKey(email); }
|
|
||||||
public Map<String, Boolean> getAssigneeStatus() { return assigneeStatus; }
|
|
||||||
|
|
||||||
// Getters / Setters
|
|
||||||
public String getId() { return id; }
|
public String getId() { return id; }
|
||||||
public String getTitle() { return title; }
|
public String getTitle() { return title; }
|
||||||
public String getDescription() { return description; }
|
public String getDescription() { return description; }
|
||||||
|
|
@ -44,7 +35,19 @@ public class TaskItem implements Serializable {
|
||||||
public String getCreatedByEmail() { return createdByEmail; }
|
public String getCreatedByEmail() { return createdByEmail; }
|
||||||
public String getCreatedByName() { return createdByName; }
|
public String getCreatedByName() { return createdByName; }
|
||||||
public boolean isNotificationsEnabled() { return notificationsEnabled; }
|
public boolean isNotificationsEnabled() { return notificationsEnabled; }
|
||||||
public void setNotificationsEnabled(boolean enabled) { this.notificationsEnabled = enabled; }
|
|
||||||
public boolean isFullyCompleted() { return isFullyCompleted; }
|
public boolean isFullyCompleted() { return isFullyCompleted; }
|
||||||
public void setFullyCompleted(boolean fullyCompleted) { isFullyCompleted = fullyCompleted; }
|
|
||||||
|
// Setters (NYTT FOR REDIGERING)
|
||||||
|
public void setTitle(String title) { this.title = title; }
|
||||||
|
public void setDescription(String description) { this.description = description; }
|
||||||
|
public void setDueDate(long dueDate) { this.dueDate = dueDate; }
|
||||||
|
public void setNotificationsEnabled(boolean enabled) { this.notificationsEnabled = enabled; }
|
||||||
|
public void setFullyCompleted(boolean fullyCompleted) { this.isFullyCompleted = fullyCompleted; }
|
||||||
|
|
||||||
|
// Participant logikk
|
||||||
|
public void addAssignee(String email) { assigneeStatus.put(email, false); }
|
||||||
|
public void setParticipantStatus(String email, boolean done) { assigneeStatus.put(email, done); }
|
||||||
|
public boolean getParticipantStatus(String email) { return assigneeStatus.getOrDefault(email, false); }
|
||||||
|
public boolean isUserParticipant(String email) { return assigneeStatus.containsKey(email); }
|
||||||
|
public Map<String, Boolean> getAssigneeStatus() { return assigneeStatus; }
|
||||||
}
|
}
|
||||||
|
|
@ -4,21 +4,29 @@ import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.google.android.material.tabs.TabLayout;
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
public class TasksFragment extends Fragment implements TaskAdapter.OnTaskClickListener {
|
public class TasksFragment extends Fragment implements TaskAdapter.OnTaskClickListener {
|
||||||
|
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private TaskAdapter adapter;
|
private TaskAdapter adapter;
|
||||||
private TabLayout tabLayout;
|
private TabLayout tabLayout;
|
||||||
|
private SwipeRefreshLayout swipeRefresh;
|
||||||
private List<TaskItem> allTasks = new ArrayList<>();
|
private List<TaskItem> allTasks = new ArrayList<>();
|
||||||
private String myEmail;
|
private String myEmail;
|
||||||
|
|
||||||
|
|
@ -35,14 +43,25 @@ public class TasksFragment extends Fragment implements TaskAdapter.OnTaskClickLi
|
||||||
myEmail = UserManager.getInstance().getUserEmail();
|
myEmail = UserManager.getInstance().getUserEmail();
|
||||||
tabLayout = view.findViewById(R.id.task_tabs);
|
tabLayout = view.findViewById(R.id.task_tabs);
|
||||||
recyclerView = view.findViewById(R.id.recycler_tasks);
|
recyclerView = view.findViewById(R.id.recycler_tasks);
|
||||||
|
swipeRefresh = view.findViewById(R.id.swipe_refresh_tasks);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
|
||||||
|
setupTabs();
|
||||||
|
|
||||||
FloatingActionButton fab = view.findViewById(R.id.fab_add_task);
|
FloatingActionButton fab = view.findViewById(R.id.fab_add_task);
|
||||||
fab.setOnClickListener(v -> {
|
fab.setOnClickListener(v -> {
|
||||||
AddTaskBottomSheet dialog = new AddTaskBottomSheet();
|
AddTaskBottomSheet dialog = new AddTaskBottomSheet();
|
||||||
dialog.setOnTaskAddedListener(task -> {
|
dialog.setOnTaskAddedListener(new AddTaskBottomSheet.OnTaskAddedListener() {
|
||||||
allTasks.add(0, task);
|
@Override
|
||||||
saveAndRefresh();
|
public void onTaskAdded(TaskItem task) {
|
||||||
|
allTasks.add(0, task);
|
||||||
|
saveAndSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTaskUpdated(TaskItem task) {
|
||||||
|
saveAndSync();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
dialog.show(getChildFragmentManager(), "AddTask");
|
dialog.show(getChildFragmentManager(), "AddTask");
|
||||||
});
|
});
|
||||||
|
|
@ -53,12 +72,41 @@ public class TasksFragment extends Fragment implements TaskAdapter.OnTaskClickLi
|
||||||
@Override public void onTabReselected(TabLayout.Tab tab) {}
|
@Override public void onTabReselected(TabLayout.Tab tab) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
loadTasks();
|
swipeRefresh.setOnRefreshListener(this::fetchTasksFromServer);
|
||||||
}
|
|
||||||
|
|
||||||
private void loadTasks() {
|
|
||||||
allTasks = CacheManager.getTasks(getContext());
|
allTasks = CacheManager.getTasks(getContext());
|
||||||
filterAndDisplay();
|
filterAndDisplay();
|
||||||
|
fetchTasksFromServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupTabs() {
|
||||||
|
tabLayout.removeAllTabs();
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText("Mine"));
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText("Fullførte"));
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText("Tildelt andre"));
|
||||||
|
if (UserManager.getInstance().isEditorOrAbove()) {
|
||||||
|
tabLayout.addTab(tabLayout.newTab().setText("Alle"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchTasksFromServer() {
|
||||||
|
swipeRefresh.setRefreshing(true);
|
||||||
|
RetrofitClient.getApiService().getTasks().enqueue(new Callback<List<TaskItem>>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<List<TaskItem>> call, Response<List<TaskItem>> response) {
|
||||||
|
swipeRefresh.setRefreshing(false);
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
allTasks = response.body();
|
||||||
|
CacheManager.saveTasks(getContext(), allTasks);
|
||||||
|
filterAndDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<List<TaskItem>> call, Throwable t) {
|
||||||
|
swipeRefresh.setRefreshing(false);
|
||||||
|
Toast.makeText(getContext(), "Kunne ikke synkronisere oppgaver", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterAndDisplay() {
|
private void filterAndDisplay() {
|
||||||
|
|
@ -66,21 +114,31 @@ public class TasksFragment extends Fragment implements TaskAdapter.OnTaskClickLi
|
||||||
int selectedTab = tabLayout.getSelectedTabPosition();
|
int selectedTab = tabLayout.getSelectedTabPosition();
|
||||||
|
|
||||||
for (TaskItem t : allTasks) {
|
for (TaskItem t : allTasks) {
|
||||||
if (selectedTab == 0) { // MINE (Oppgaver tildelt meg som ikke er fullført av meg ennå)
|
boolean isParticipant = t.isUserParticipant(myEmail);
|
||||||
if (t.isUserParticipant(myEmail) && !t.getParticipantStatus(myEmail) && !t.isFullyCompleted()) {
|
boolean isCreator = t.getCreatedByEmail().equalsIgnoreCase(myEmail);
|
||||||
filtered.add(t);
|
boolean iHaveDoneIt = t.getParticipantStatus(myEmail);
|
||||||
}
|
boolean hasOtherParticipants = false;
|
||||||
} else if (selectedTab == 1) { // TILDELT ANDRE (Oppgaver jeg har laget, uansett om jeg er med selv)
|
for (String email : t.getAssigneeStatus().keySet()) {
|
||||||
if (t.getCreatedByEmail().equals(myEmail) && !t.isFullyCompleted()) {
|
if (!email.equalsIgnoreCase(myEmail)) { hasOtherParticipants = true; break; }
|
||||||
filtered.add(t);
|
}
|
||||||
}
|
|
||||||
} else { // FULLFØRTE (Alt som er arkivert som ferdig)
|
switch (selectedTab) {
|
||||||
if (t.isFullyCompleted() || (t.isUserParticipant(myEmail) && t.getParticipantStatus(myEmail))) {
|
case 0: // MINE
|
||||||
filtered.add(t);
|
if (isParticipant && !iHaveDoneIt && !t.isFullyCompleted()) filtered.add(t);
|
||||||
}
|
break;
|
||||||
|
case 1: // FULLFØRTE
|
||||||
|
if (t.isFullyCompleted() || (isParticipant && iHaveDoneIt)) filtered.add(t);
|
||||||
|
break;
|
||||||
|
case 2: // TILDELT ANDRE
|
||||||
|
if (isCreator && !t.isFullyCompleted() && hasOtherParticipants) filtered.add(t);
|
||||||
|
break;
|
||||||
|
case 3: // ALLE
|
||||||
|
if (!t.isFullyCompleted()) filtered.add(t);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (selectedTab == 1) Collections.sort(filtered, (t1, t2) -> Long.compare(t2.getDueDate(), t1.getDueDate()));
|
||||||
|
else Collections.sort(filtered, (t1, t2) -> Long.compare(t1.getDueDate(), t2.getDueDate()));
|
||||||
adapter = new TaskAdapter(filtered, this);
|
adapter = new TaskAdapter(filtered, this);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
@ -88,15 +146,21 @@ public class TasksFragment extends Fragment implements TaskAdapter.OnTaskClickLi
|
||||||
@Override
|
@Override
|
||||||
public void onTaskClick(TaskItem task) {
|
public void onTaskClick(TaskItem task) {
|
||||||
TaskDetailsBottomSheet sheet = new TaskDetailsBottomSheet(task, new TaskDetailsBottomSheet.OnTaskChangeListener() {
|
TaskDetailsBottomSheet sheet = new TaskDetailsBottomSheet(task, new TaskDetailsBottomSheet.OnTaskChangeListener() {
|
||||||
@Override
|
@Override public void onTaskChanged() { saveAndSync(); }
|
||||||
public void onTaskChanged() {
|
@Override public void onTaskDeleted(TaskItem taskToDelete) {
|
||||||
saveAndRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTaskDeleted(TaskItem taskToDelete) {
|
|
||||||
allTasks.remove(taskToDelete);
|
allTasks.remove(taskToDelete);
|
||||||
saveAndRefresh();
|
saveAndSync();
|
||||||
|
}
|
||||||
|
@Override public void onEditRequested(TaskItem taskToEdit) {
|
||||||
|
AddTaskBottomSheet editDialog = new AddTaskBottomSheet();
|
||||||
|
editDialog.setTaskToEdit(taskToEdit);
|
||||||
|
editDialog.setOnTaskAddedListener(new AddTaskBottomSheet.OnTaskAddedListener() {
|
||||||
|
@Override public void onTaskAdded(TaskItem task) {} // Ikke i bruk her
|
||||||
|
@Override public void onTaskUpdated(TaskItem task) {
|
||||||
|
saveAndSync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editDialog.show(getChildFragmentManager(), "EditTask");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
sheet.show(getChildFragmentManager(), "TaskDetails");
|
sheet.show(getChildFragmentManager(), "TaskDetails");
|
||||||
|
|
@ -105,18 +169,22 @@ public class TasksFragment extends Fragment implements TaskAdapter.OnTaskClickLi
|
||||||
@Override
|
@Override
|
||||||
public void onStatusChanged(TaskItem task, boolean isDone) {
|
public void onStatusChanged(TaskItem task, boolean isDone) {
|
||||||
task.setParticipantStatus(myEmail, isDone);
|
task.setParticipantStatus(myEmail, isDone);
|
||||||
|
boolean hasOthers = false;
|
||||||
// Logikk: Hvis den som opprettet oppgaven merker den som ferdig,
|
for (String email : task.getAssigneeStatus().keySet()) {
|
||||||
// regnes hele oppgaven som ferdig for alle (arkiveres).
|
if (!email.equalsIgnoreCase(myEmail)) { hasOthers = true; break; }
|
||||||
if (task.getCreatedByEmail().equals(myEmail) && isDone) {
|
}
|
||||||
|
if (task.getCreatedByEmail().equalsIgnoreCase(myEmail) && isDone && !hasOthers) {
|
||||||
task.setFullyCompleted(true);
|
task.setFullyCompleted(true);
|
||||||
}
|
}
|
||||||
|
saveAndSync();
|
||||||
saveAndRefresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveAndRefresh() {
|
private void saveAndSync() {
|
||||||
CacheManager.saveTasks(getContext(), allTasks);
|
CacheManager.saveTasks(getContext(), allTasks);
|
||||||
filterAndDisplay();
|
filterAndDisplay();
|
||||||
|
RetrofitClient.getApiService().syncTasks(allTasks).enqueue(new Callback<JsonElement>() {
|
||||||
|
@Override public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {}
|
||||||
|
@Override public void onFailure(Call<JsonElement> call, Throwable t) {}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,20 +17,47 @@ import retrofit2.http.PartMap;
|
||||||
import retrofit2.http.Query;
|
import retrofit2.http.Query;
|
||||||
|
|
||||||
public interface WordPressApiService {
|
public interface WordPressApiService {
|
||||||
|
|
||||||
|
// --- NYHETER ---
|
||||||
@GET("wp-json/wp/v2/posts?per_page=10&_embed")
|
@GET("wp-json/wp/v2/posts?per_page=10&_embed")
|
||||||
Call<List<WpPost>> getPosts();
|
Call<List<WpPost>> getPosts();
|
||||||
@GET("wp-json/kbs/v1/forms/{id}")
|
|
||||||
Call<GravityForm> getForm(@Path("id") int formId);
|
|
||||||
|
|
||||||
@POST("wp-json/gf/v2/forms/{id}/submissions")
|
@GET("wp-json/wp/v2/posts?per_page=50&_embed")
|
||||||
Call<JsonElement> submitForm(@Path("id") int formId, @Body FormSubmission submission);
|
Call<List<WpPost>> getAllPosts();
|
||||||
|
|
||||||
|
|
||||||
|
// --- AUTENTISERING & ENHET ---
|
||||||
@POST("wp-json/kbs/v1/login")
|
@POST("wp-json/kbs/v1/login")
|
||||||
Call<LoginResponse> googleLogin(@Body LoginRequest request);
|
Call<LoginResponse> googleLogin(@Body LoginRequest request);
|
||||||
|
|
||||||
|
@POST("wp-json/kbs/v1/device/register")
|
||||||
|
Call<JsonElement> registerDevice(@Body RegisterDeviceRequest request);
|
||||||
|
|
||||||
|
@GET("wp-json/kbs/v1/users")
|
||||||
|
Call<List<User>> getUsersList();
|
||||||
|
|
||||||
|
|
||||||
|
// --- KALENDER ---
|
||||||
|
@GET("wp-json/kbs/v1/calendar/events")
|
||||||
|
Call<List<CalendarEvent>> getCalendarEvents();
|
||||||
|
|
||||||
|
@POST("wp-json/kbs/v1/calendar/create")
|
||||||
|
Call<JsonElement> createCalendarEvent(@Body CreateEventRequest request);
|
||||||
|
|
||||||
|
@POST("wp-json/kbs/v1/calendar/update")
|
||||||
|
Call<JsonElement> updateCalendarEvent(@Body CreateEventRequest request);
|
||||||
|
|
||||||
|
@POST("wp-json/kbs/v1/calendar/delete")
|
||||||
|
Call<JsonElement> deleteCalendarEvent(@Body CreateEventRequest request);
|
||||||
|
|
||||||
|
|
||||||
|
// --- SKJEMAER (GRAVITY FORMS) ---
|
||||||
@GET("wp-json/kbs/v1/forms")
|
@GET("wp-json/kbs/v1/forms")
|
||||||
Call<List<GravityForm>> getFormsList();
|
Call<List<GravityForm>> getFormsList();
|
||||||
|
|
||||||
|
@GET("wp-json/kbs/v1/forms/{id}")
|
||||||
|
Call<GravityForm> getForm(@Path("id") int formId);
|
||||||
|
|
||||||
@Multipart
|
@Multipart
|
||||||
@POST("wp-json/gf/v2/forms/{id}/submissions")
|
@POST("wp-json/gf/v2/forms/{id}/submissions")
|
||||||
Call<JsonElement> submitMultipartForm(
|
Call<JsonElement> submitMultipartForm(
|
||||||
|
|
@ -39,16 +66,6 @@ public interface WordPressApiService {
|
||||||
@Part List<MultipartBody.Part> files
|
@Part List<MultipartBody.Part> files
|
||||||
);
|
);
|
||||||
|
|
||||||
@GET("wp-json/kbs/v1/calendar/events")
|
|
||||||
Call<List<CalendarEvent>> getCalendarEvents();
|
|
||||||
|
|
||||||
@POST("wp-json/kbs/v1/calendar/create")
|
|
||||||
Call<JsonElement> createCalendarEvent(@Body CreateEventRequest request);
|
|
||||||
|
|
||||||
// NYTT ENDEPUNKT
|
|
||||||
@GET("wp-json/kbs/v1/users")
|
|
||||||
Call<List<User>> getUsersList();
|
|
||||||
|
|
||||||
@GET("wp-json/gf/v2/entries")
|
@GET("wp-json/gf/v2/entries")
|
||||||
Call<GravityEntryResponse> getEntries(
|
Call<GravityEntryResponse> getEntries(
|
||||||
@Query("form_ids") int formId,
|
@Query("form_ids") int formId,
|
||||||
|
|
@ -59,9 +76,8 @@ public interface WordPressApiService {
|
||||||
@GET("wp-json/gf/v2/entries/{entry_id}")
|
@GET("wp-json/gf/v2/entries/{entry_id}")
|
||||||
Call<JsonElement> getSingleEntry(@Path("entry_id") String entryId);
|
Call<JsonElement> getSingleEntry(@Path("entry_id") String entryId);
|
||||||
|
|
||||||
@GET("wp-json/wp/v2/posts?per_page=50&_embed")
|
|
||||||
Call<List<WpPost>> getAllPosts();
|
|
||||||
|
|
||||||
|
// --- HÅNDBOK ---
|
||||||
@GET("wp-json/kbs/v1/handbook")
|
@GET("wp-json/kbs/v1/handbook")
|
||||||
Call<List<HandbookItem>> getHandbookItems();
|
Call<List<HandbookItem>> getHandbookItems();
|
||||||
|
|
||||||
|
|
@ -71,12 +87,11 @@ public interface WordPressApiService {
|
||||||
@GET("wp-json/kbs/v1/lookup-id")
|
@GET("wp-json/kbs/v1/lookup-id")
|
||||||
Call<JsonObject> lookupPageId(@Query("url") String url);
|
Call<JsonObject> lookupPageId(@Query("url") String url);
|
||||||
|
|
||||||
@POST("wp-json/kbs/v1/calendar/update")
|
|
||||||
Call<JsonElement> updateCalendarEvent(@Body CreateEventRequest request);
|
|
||||||
|
|
||||||
@POST("wp-json/kbs/v1/calendar/delete")
|
// --- OPPGAVER (SYNKRONISERING) ---
|
||||||
Call<JsonElement> deleteCalendarEvent(@Body CreateEventRequest request);
|
@GET("wp-json/kbs/v1/tasks")
|
||||||
|
Call<List<TaskItem>> getTasks();
|
||||||
|
|
||||||
@POST("wp-json/kbs/v1/device/register")
|
@POST("wp-json/kbs/v1/tasks/sync")
|
||||||
Call<JsonElement> registerDevice(@Body RegisterDeviceRequest request);
|
Call<JsonElement> syncTasks(@Body List<TaskItem> tasks);
|
||||||
}
|
}
|
||||||
|
|
@ -1,84 +1,92 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:fillViewport="true">
|
||||||
android:padding="24dp"
|
|
||||||
android:background="@color/white">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Ny Oppgave"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/black"
|
|
||||||
android:layout_marginBottom="16dp"/>
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/et_task_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="Hva skal gjøres?"
|
|
||||||
android:inputType="textCapSentences"
|
|
||||||
android:layout_marginBottom="8dp"/>
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/et_task_desc"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="Beskrivelse (valgfritt)"
|
|
||||||
android:inputType="textMultiLine"
|
|
||||||
android:minLines="2"
|
|
||||||
android:gravity="top"
|
|
||||||
android:layout_marginBottom="16dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:orientation="vertical"
|
||||||
android:gravity="center_vertical"
|
android:padding="24dp"
|
||||||
android:layout_marginBottom="12dp">
|
android:background="@color/white">
|
||||||
<Button
|
|
||||||
android:id="@+id/btn_task_date"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Sett frist" />
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txt_date_preview"
|
android:id="@+id/txt_sheet_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Frist: -"
|
android:text="Ny Oppgave"
|
||||||
android:layout_marginStart="8dp"/>
|
android:textSize="20sp"
|
||||||
</LinearLayout>
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_task_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="Hva skal gjøres?"
|
||||||
|
android:inputType="textCapSentences"
|
||||||
|
android:layout_marginBottom="8dp"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_task_desc"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="Beskrivelse (valgfritt)"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:minLines="2"
|
||||||
|
android:gravity="top"
|
||||||
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginBottom="12dp">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_task_date"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Sett frist" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txt_date_preview"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Frist: -"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginBottom="24dp">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_task_users"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Velg deltakere" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txt_users_preview"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Kun meg"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:layout_marginBottom="24dp">
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btn_task_users"
|
android:id="@+id/btn_save_task"
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Velg deltakere" />
|
android:text="Lagre Oppgave"
|
||||||
<TextView
|
android:backgroundTint="@color/kbs_logo_blue"
|
||||||
android:id="@+id/txt_users_preview"
|
android:textColor="@color/white"
|
||||||
android:layout_width="wrap_content"
|
android:layout_marginBottom="16dp"/>
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Kun meg"
|
|
||||||
android:layout_marginStart="8dp"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
<Button
|
|
||||||
android:id="@+id/btn_save_task"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Lagre Oppgave"
|
|
||||||
android:backgroundTint="@color/kbs_logo_blue"
|
|
||||||
android:textColor="@color/white"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@ -65,13 +65,32 @@
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
android:layout_marginBottom="24dp"/>
|
android:layout_marginBottom="24dp"/>
|
||||||
|
|
||||||
<Button
|
<LinearLayout
|
||||||
android:id="@+id/btn_delete_task"
|
android:id="@+id/layout_owner_actions"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Slett oppgave"
|
android:orientation="horizontal"
|
||||||
android:backgroundTint="@color/kbs_logo_accent_red"
|
android:visibility="gone">
|
||||||
android:textColor="@color/white"
|
|
||||||
android:visibility="gone"/>
|
<Button
|
||||||
|
android:id="@+id/btn_delete_task"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Slett"
|
||||||
|
android:backgroundTint="@color/kbs_logo_accent_red"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:layout_marginEnd="8dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_edit_task"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Endre"
|
||||||
|
android:backgroundTint="@color/kbs_logo_blue"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
@ -1,44 +1,42 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@color/white">
|
android:background="@color/white">
|
||||||
|
|
||||||
<!-- Knappen ligger nå helt øverst i fragmentet (under den globale toolbaren) -->
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
<Button
|
android:id="@+id/recycler_full_calendar"
|
||||||
android:id="@+id/btn_add_calendar_event"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="80dp" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loading_full_calendar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="+ Ny Kalenderhendelse"
|
android:layout_gravity="center"/>
|
||||||
android:backgroundTint="@color/kbs_logo_blue"
|
|
||||||
android:textColor="@color/white"
|
<TextView
|
||||||
android:layout_margin="16dp"
|
android:id="@+id/empty_view_calendar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Ingen hendelser funnet"
|
||||||
|
android:layout_gravity="center"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<FrameLayout
|
<!-- NY FAB: Flytende knapp nederst til høyre -->
|
||||||
android:layout_width="match_parent"
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:layout_height="match_parent">
|
android:id="@+id/fab_add_calendar_event"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="24dp"
|
||||||
|
android:src="@android:drawable/ic_input_add"
|
||||||
|
app:backgroundTint="@color/kbs_logo_blue"
|
||||||
|
app:tint="@color/white"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:contentDescription="Ny hendelse" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
</FrameLayout>
|
||||||
android:id="@+id/recycler_full_calendar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:clipToPadding="false" />
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/loading_full_calendar"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/empty_view_calendar"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Ingen hendelser funnet"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
</FrameLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@ -5,31 +5,7 @@
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:background="@color/kbs_very_light_blue">
|
android:background="@color/kbs_very_light_blue">
|
||||||
|
|
||||||
<RelativeLayout
|
<!-- Redundant header er fjernet. Kun kategorilisten og nyhetslisten er igjen. -->
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="16dp"
|
|
||||||
android:background="@android:color/white"
|
|
||||||
android:elevation="4dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/btn_back_news"
|
|
||||||
android:layout_width="32dp"
|
|
||||||
android:layout_height="32dp"
|
|
||||||
android:src="@android:drawable/ic_menu_revert"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:contentDescription="Tilbake"
|
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Siste nytt"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@android:color/black"
|
|
||||||
android:layout_centerInParent="true"/>
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recycler_categories"
|
android:id="@+id/recycler_categories"
|
||||||
|
|
|
||||||
|
|
@ -13,21 +13,7 @@
|
||||||
android:background="@color/white"
|
android:background="@color/white"
|
||||||
app:tabSelectedTextColor="@color/kbs_logo_blue"
|
app:tabSelectedTextColor="@color/kbs_logo_blue"
|
||||||
app:tabIndicatorColor="@color/kbs_logo_blue">
|
app:tabIndicatorColor="@color/kbs_logo_blue">
|
||||||
|
<!-- Faner legges til programmatisk i TasksFragment.java -->
|
||||||
<com.google.android.material.tabs.TabItem
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Mine" />
|
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabItem
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Tildelt andre" />
|
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabItem
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Fullførte" />
|
|
||||||
</com.google.android.material.tabs.TabLayout>
|
</com.google.android.material.tabs.TabLayout>
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
|
|
||||||
10
app/src/main/res/layout/item_home_empty_tasks.xml
Normal file
10
app/src/main/res/layout/item_home_empty_tasks.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Ingen oppgaver tildelt"
|
||||||
|
android:textColor="@color/kbs_muted_blue_gray"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingVertical="8dp" />
|
||||||
|
|
@ -44,6 +44,15 @@
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
android:textColor="@color/kbs_muted_blue_gray" />
|
android:textColor="@color/kbs_muted_blue_gray" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/task_creator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Tildelt av: -"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:textColor="@color/kbs_logo_blue"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/task_progress"
|
android:id="@+id/task_progress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -51,7 +60,7 @@
|
||||||
android:text="Fremdrift: 0/0"
|
android:text="Fremdrift: 0/0"
|
||||||
android:textSize="11sp"
|
android:textSize="11sp"
|
||||||
android:textStyle="italic"
|
android:textStyle="italic"
|
||||||
android:textColor="@color/kbs_logo_blue"
|
android:textColor="@color/kbs_muted_blue_gray"
|
||||||
android:layout_marginTop="2dp"/>
|
android:layout_marginTop="2dp"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue