Før caching
This commit is contained in:
parent
91f8c2c0c7
commit
5497e68110
4 changed files with 91 additions and 86 deletions
39
app/google-services.json
Normal file
39
app/google-services.json
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "738325360287",
|
||||||
|
"project_id": "intranet-glogin-452614",
|
||||||
|
"storage_bucket": "intranet-glogin-452614.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:738325360287:android:c97082eedba86b85b43caa",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.kbs.kbsintranett"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [
|
||||||
|
{
|
||||||
|
"client_id": "738325360287-cidl3plnqv9ei74vm9vm5muustj6eenb.apps.googleusercontent.com",
|
||||||
|
"client_type": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyC0vrXCWJNLzrgOk1ChWeFpYlqxKPqxUf0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": [
|
||||||
|
{
|
||||||
|
"client_id": "738325360287-cidl3plnqv9ei74vm9vm5muustj6eenb.apps.googleusercontent.com",
|
||||||
|
"client_type": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
|
|
@ -43,14 +43,15 @@ 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;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.navigation.Navigation;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
@ -102,11 +103,12 @@ public class FormsFragment extends Fragment {
|
||||||
|
|
||||||
private LinearLayout formContainer;
|
private LinearLayout formContainer;
|
||||||
private LinearLayout historyContainer;
|
private LinearLayout historyContainer;
|
||||||
private View historyWrapper; // Wrapper for historikk-modulen
|
private View historyWrapper;
|
||||||
private TextView txtStatus;
|
private TextView txtStatus;
|
||||||
private TextView lblHistory;
|
private TextView lblHistory;
|
||||||
private ProgressBar loadingSpinner;
|
private ProgressBar loadingSpinner;
|
||||||
private ImageView btnToggleHistory;
|
private ImageView btnToggleHistory;
|
||||||
|
private Toolbar toolbar; // NYTT
|
||||||
|
|
||||||
// --- HOVEDSKJEMA STATE ---
|
// --- HOVEDSKJEMA STATE ---
|
||||||
private Map<String, View> fieldWrappers = new HashMap<>();
|
private Map<String, View> fieldWrappers = new HashMap<>();
|
||||||
|
|
@ -118,7 +120,7 @@ public class FormsFragment extends Fragment {
|
||||||
private Map<String, View> childInputViews = new HashMap<>();
|
private Map<String, View> childInputViews = new HashMap<>();
|
||||||
private Map<String, Boolean> childRequiredFieldsMap = new HashMap<>();
|
private Map<String, Boolean> childRequiredFieldsMap = new HashMap<>();
|
||||||
private Map<String, Uri> childFileUploads = new HashMap<>();
|
private Map<String, Uri> childFileUploads = new HashMap<>();
|
||||||
// Lagring av Nested Entries
|
|
||||||
private List<NestedEntry> nestedEntries = new ArrayList<>();
|
private List<NestedEntry> nestedEntries = new ArrayList<>();
|
||||||
private LinearLayout nestedEntriesContainer;
|
private LinearLayout nestedEntriesContainer;
|
||||||
private TextView totalAmountView;
|
private TextView totalAmountView;
|
||||||
|
|
@ -184,12 +186,17 @@ public class FormsFragment extends Fragment {
|
||||||
lblHistory = view.findViewById(R.id.lbl_history);
|
lblHistory = view.findViewById(R.id.lbl_history);
|
||||||
loadingSpinner = view.findViewById(R.id.loading_spinner);
|
loadingSpinner = view.findViewById(R.id.loading_spinner);
|
||||||
|
|
||||||
|
// NYTT: Finn toolbar og sett listener
|
||||||
|
toolbar = view.findViewById(R.id.forms_toolbar);
|
||||||
|
if (toolbar != null) {
|
||||||
|
toolbar.setNavigationOnClickListener(v -> Navigation.findNavController(view).navigateUp());
|
||||||
|
}
|
||||||
|
|
||||||
btnToggleHistory = view.findViewById(R.id.btn_toggle_history);
|
btnToggleHistory = view.findViewById(R.id.btn_toggle_history);
|
||||||
if (btnToggleHistory != null) {
|
if (btnToggleHistory != null) {
|
||||||
btnToggleHistory.setOnClickListener(v -> toggleHistoryVisibility());
|
btnToggleHistory.setOnClickListener(v -> toggleHistoryVisibility());
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- FIKS FOR NULLPOINTER EXCEPTION PÅ LAYOUTTRANSITION ---
|
|
||||||
if (view instanceof ViewGroup) {
|
if (view instanceof ViewGroup) {
|
||||||
LayoutTransition transition = ((ViewGroup) view).getLayoutTransition();
|
LayoutTransition transition = ((ViewGroup) view).getLayoutTransition();
|
||||||
if (transition == null) {
|
if (transition == null) {
|
||||||
|
|
@ -198,7 +205,6 @@ public class FormsFragment extends Fragment {
|
||||||
}
|
}
|
||||||
transition.enableTransitionType(LayoutTransition.CHANGING);
|
transition.enableTransitionType(LayoutTransition.CHANGING);
|
||||||
}
|
}
|
||||||
// ----------------------------------------------------------
|
|
||||||
|
|
||||||
if (formContainer == null) {
|
if (formContainer == null) {
|
||||||
formContainer = new LinearLayout(getContext());
|
formContainer = new LinearLayout(getContext());
|
||||||
|
|
@ -229,11 +235,9 @@ public class FormsFragment extends Fragment {
|
||||||
if (historyWrapper == null || btnToggleHistory == null) return;
|
if (historyWrapper == null || btnToggleHistory == null) return;
|
||||||
|
|
||||||
if (historyWrapper.getVisibility() == View.VISIBLE) {
|
if (historyWrapper.getVisibility() == View.VISIBLE) {
|
||||||
// Skjul historikk
|
|
||||||
historyWrapper.setVisibility(View.GONE);
|
historyWrapper.setVisibility(View.GONE);
|
||||||
btnToggleHistory.setImageResource(android.R.drawable.arrow_down_float);
|
btnToggleHistory.setImageResource(android.R.drawable.arrow_down_float);
|
||||||
} else {
|
} else {
|
||||||
// Vis historikk
|
|
||||||
historyWrapper.setVisibility(View.VISIBLE);
|
historyWrapper.setVisibility(View.VISIBLE);
|
||||||
btnToggleHistory.setImageResource(android.R.drawable.arrow_up_float);
|
btnToggleHistory.setImageResource(android.R.drawable.arrow_up_float);
|
||||||
}
|
}
|
||||||
|
|
@ -300,20 +304,17 @@ public class FormsFragment extends Fragment {
|
||||||
nestedEntries.clear();
|
nestedEntries.clear();
|
||||||
updateStatus("");
|
updateStatus("");
|
||||||
|
|
||||||
// Reset visibility of history on new load
|
// NYTT: Sett tittelen i Toolbaren i stedet for å legge til en TextView
|
||||||
|
if (toolbar != null) {
|
||||||
|
toolbar.setTitle(getCleanTitle(form.title));
|
||||||
|
}
|
||||||
|
|
||||||
if (historyWrapper != null) {
|
if (historyWrapper != null) {
|
||||||
historyWrapper.setVisibility(View.VISIBLE);
|
historyWrapper.setVisibility(View.VISIBLE);
|
||||||
if (btnToggleHistory != null) btnToggleHistory.setImageResource(android.R.drawable.arrow_up_float);
|
if (btnToggleHistory != null) btnToggleHistory.setImageResource(android.R.drawable.arrow_up_float);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView title = new TextView(getContext());
|
// Beskrivelse legges fortsatt inn som innhold
|
||||||
title.setText(getCleanTitle(form.title));
|
|
||||||
title.setTextSize(24);
|
|
||||||
title.setTypeface(null, Typeface.BOLD);
|
|
||||||
title.setTextColor(Color.BLACK);
|
|
||||||
title.setPadding(0, 0, 0, 20);
|
|
||||||
formContainer.addView(title);
|
|
||||||
|
|
||||||
if (form.description != null && !form.description.isEmpty()) {
|
if (form.description != null && !form.description.isEmpty()) {
|
||||||
TextView formDesc = new TextView(getContext());
|
TextView formDesc = new TextView(getContext());
|
||||||
String cleanDesc = form.description.replaceFirst("^\\d+\\.\\s*", "");
|
String cleanDesc = form.description.replaceFirst("^\\d+\\.\\s*", "");
|
||||||
|
|
@ -429,14 +430,13 @@ public class FormsFragment extends Fragment {
|
||||||
btnAdd.setBackgroundColor(Color.parseColor("#53AFE9"));
|
btnAdd.setBackgroundColor(Color.parseColor("#53AFE9"));
|
||||||
btnAdd.setTextColor(Color.WHITE);
|
btnAdd.setTextColor(Color.WHITE);
|
||||||
btnAdd.setOnClickListener(v -> {
|
btnAdd.setOnClickListener(v -> {
|
||||||
expandFormModule(); // Trigger expand
|
expandFormModule();
|
||||||
int childFormId = 18;
|
int childFormId = 18;
|
||||||
if (field.gpnfForm != null) {
|
if (field.gpnfForm != null) {
|
||||||
try {
|
try {
|
||||||
childFormId = Integer.parseInt(field.gpnfForm);
|
childFormId = Integer.parseInt(field.gpnfForm);
|
||||||
} catch (NumberFormatException e) { e.printStackTrace(); }
|
} catch (NumberFormatException e) { e.printStackTrace(); }
|
||||||
}
|
}
|
||||||
// NYTT: Sender med felt-ID fra hovedskjemaet (f.eks "25")
|
|
||||||
openChildFormDialog(childFormId, field.id);
|
openChildFormDialog(childFormId, field.id);
|
||||||
});
|
});
|
||||||
container.addView(btnAdd);
|
container.addView(btnAdd);
|
||||||
|
|
@ -455,7 +455,6 @@ public class FormsFragment extends Fragment {
|
||||||
container.addView(totalAmountView);
|
container.addView(totalAmountView);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NY SIGNATUR: Tar imot parentFieldId
|
|
||||||
private void openChildFormDialog(int childFormId, String parentFieldId) {
|
private void openChildFormDialog(int childFormId, String parentFieldId) {
|
||||||
if (getActivity() == null) return;
|
if (getActivity() == null) return;
|
||||||
ProgressBar pBar = new ProgressBar(getContext());
|
ProgressBar pBar = new ProgressBar(getContext());
|
||||||
|
|
@ -483,7 +482,6 @@ public class FormsFragment extends Fragment {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// NY SIGNATUR: Tar imot parentFieldId
|
|
||||||
private void showChildFormDialog(GravityForm childForm, String parentFieldId) {
|
private void showChildFormDialog(GravityForm childForm, String parentFieldId) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
childInputViews.clear();
|
childInputViews.clear();
|
||||||
|
|
@ -533,7 +531,6 @@ public class FormsFragment extends Fragment {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// NY SIGNATUR: Tar imot parentFieldId og sender den som meta
|
|
||||||
private void submitChildForm(int childFormId, AlertDialog dialog, String parentFieldId) {
|
private void submitChildForm(int childFormId, AlertDialog dialog, String parentFieldId) {
|
||||||
JSONObject inputValues = new JSONObject();
|
JSONObject inputValues = new JSONObject();
|
||||||
for (Map.Entry<String, View> entry : childInputViews.entrySet()) {
|
for (Map.Entry<String, View> entry : childInputViews.entrySet()) {
|
||||||
|
|
@ -559,13 +556,9 @@ public class FormsFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- HER ER FIKSEN FOR BUGGEN ---
|
|
||||||
// Vi legger ved en ekstra parameter som forteller Gravity Forms at dette
|
|
||||||
// er en nested entry som hører til et bestemt felt (f.eks "25").
|
|
||||||
if (parentFieldId != null) {
|
if (parentFieldId != null) {
|
||||||
textParts.put("gpnf_entry_nested_form_field", RequestBody.create(MultipartBody.FORM, parentFieldId));
|
textParts.put("gpnf_entry_nested_form_field", RequestBody.create(MultipartBody.FORM, parentFieldId));
|
||||||
}
|
}
|
||||||
// ---------------------------------
|
|
||||||
|
|
||||||
for (Map.Entry<String, Uri> fileEntry : childFileUploads.entrySet()) {
|
for (Map.Entry<String, Uri> fileEntry : childFileUploads.entrySet()) {
|
||||||
String fieldId = fileEntry.getKey();
|
String fieldId = fileEntry.getKey();
|
||||||
|
|
@ -585,9 +578,6 @@ public class FormsFragment extends Fragment {
|
||||||
JsonObject json = response.body().getAsJsonObject();
|
JsonObject json = response.body().getAsJsonObject();
|
||||||
if (json.has("is_valid") && json.get("is_valid").getAsBoolean()) {
|
if (json.has("is_valid") && json.get("is_valid").getAsBoolean()) {
|
||||||
String entryId = json.has("entry_id") ? json.get("entry_id").getAsString() : "";
|
String entryId = json.has("entry_id") ? json.get("entry_id").getAsString() : "";
|
||||||
|
|
||||||
// NB: Tilpass ID-ene her hvis skjema 18 endres.
|
|
||||||
// ID 3 = Beskrivelse, ID 4 = Beløp
|
|
||||||
String desc = getInputValueGeneric(childInputViews.get("3"));
|
String desc = getInputValueGeneric(childInputViews.get("3"));
|
||||||
String price = getInputValueGeneric(childInputViews.get("4"));
|
String price = getInputValueGeneric(childInputViews.get("4"));
|
||||||
addNestedEntry(entryId, desc, price);
|
addNestedEntry(entryId, desc, price);
|
||||||
|
|
@ -661,10 +651,9 @@ public class FormsFragment extends Fragment {
|
||||||
Button btnUpload = new Button(getContext());
|
Button btnUpload = new Button(getContext());
|
||||||
btnUpload.setText("Velg fil / Ta bilde");
|
btnUpload.setText("Velg fil / Ta bilde");
|
||||||
btnUpload.setOnClickListener(v -> {
|
btnUpload.setOnClickListener(v -> {
|
||||||
// Setter state før vi viser dialog
|
|
||||||
pendingFileFieldId = field.id;
|
pendingFileFieldId = field.id;
|
||||||
isSelectingForChild = isChild;
|
isSelectingForChild = isChild;
|
||||||
expandFormModule(); // Trigger expand
|
expandFormModule();
|
||||||
showFileSourceDialog();
|
showFileSourceDialog();
|
||||||
});
|
});
|
||||||
TextView txtFileName = new TextView(getContext());
|
TextView txtFileName = new TextView(getContext());
|
||||||
|
|
@ -681,23 +670,19 @@ public class FormsFragment extends Fragment {
|
||||||
reqMap.put(field.id, field.isRequired);
|
reqMap.put(field.id, field.isRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hjelpemetode for å vise dialog
|
|
||||||
private void showFileSourceDialog() {
|
private void showFileSourceDialog() {
|
||||||
String[] options = {"Ta bilde", "Velg fil"};
|
String[] options = {"Ta bilde", "Velg fil"};
|
||||||
new AlertDialog.Builder(getContext())
|
new AlertDialog.Builder(getContext())
|
||||||
.setTitle("Last opp vedlegg")
|
.setTitle("Last opp vedlegg")
|
||||||
.setItems(options, (dialog, which) -> {
|
.setItems(options, (dialog, which) -> {
|
||||||
if (which == 0) {
|
if (which == 0) {
|
||||||
// Ta bilde - SJEKKER PERMISSION FØRST
|
|
||||||
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA)
|
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA)
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
openCamera();
|
openCamera();
|
||||||
} else {
|
} else {
|
||||||
// Spør om lov
|
|
||||||
requestPermissionLauncher.launch(Manifest.permission.CAMERA);
|
requestPermissionLauncher.launch(Manifest.permission.CAMERA);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Velg fil
|
|
||||||
if (filePickerLauncher != null) {
|
if (filePickerLauncher != null) {
|
||||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
intent.setType("*/*");
|
intent.setType("*/*");
|
||||||
|
|
@ -790,7 +775,7 @@ public class FormsFragment extends Fragment {
|
||||||
timeInput.setClickable(true);
|
timeInput.setClickable(true);
|
||||||
timeInput.setHint("00:00");
|
timeInput.setHint("00:00");
|
||||||
timeInput.setOnClickListener(v -> {
|
timeInput.setOnClickListener(v -> {
|
||||||
expandFormModule(); // Trigger expand
|
expandFormModule();
|
||||||
Calendar mcurrentTime = Calendar.getInstance();
|
Calendar mcurrentTime = Calendar.getInstance();
|
||||||
int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
|
int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
|
||||||
int minute = mcurrentTime.get(Calendar.MINUTE);
|
int minute = mcurrentTime.get(Calendar.MINUTE);
|
||||||
|
|
@ -831,7 +816,7 @@ public class FormsFragment extends Fragment {
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||||
public void afterTextChanged(Editable s) { evaluateAllConditionalLogic(); }
|
public void afterTextChanged(Editable s) { evaluateAllConditionalLogic(); }
|
||||||
});
|
});
|
||||||
attachInteractionListener(input); // Add listener
|
attachInteractionListener(input);
|
||||||
|
|
||||||
container.addView(input);
|
container.addView(input);
|
||||||
views.put(field.id, input);
|
views.put(field.id, input);
|
||||||
|
|
@ -845,7 +830,7 @@ public class FormsFragment extends Fragment {
|
||||||
input.setMinLines(3);
|
input.setMinLines(3);
|
||||||
input.setGravity(android.view.Gravity.TOP | android.view.Gravity.START);
|
input.setGravity(android.view.Gravity.TOP | android.view.Gravity.START);
|
||||||
|
|
||||||
attachInteractionListener(input); // Add listener
|
attachInteractionListener(input);
|
||||||
|
|
||||||
container.addView(input);
|
container.addView(input);
|
||||||
views.put(field.id, input);
|
views.put(field.id, input);
|
||||||
|
|
@ -859,7 +844,6 @@ public class FormsFragment extends Fragment {
|
||||||
RadioButton rb = new RadioButton(getContext());
|
RadioButton rb = new RadioButton(getContext());
|
||||||
rb.setText(choice.text);
|
rb.setText(choice.text);
|
||||||
rb.setTag(choice.value);
|
rb.setTag(choice.value);
|
||||||
// Also trigger expand on RadioButton click
|
|
||||||
rb.setOnClickListener(v -> {
|
rb.setOnClickListener(v -> {
|
||||||
expandFormModule();
|
expandFormModule();
|
||||||
evaluateAllConditionalLogic();
|
evaluateAllConditionalLogic();
|
||||||
|
|
@ -867,7 +851,6 @@ public class FormsFragment extends Fragment {
|
||||||
group.addView(rb);
|
group.addView(rb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fallback listener
|
|
||||||
group.setOnCheckedChangeListener((g, i) -> {
|
group.setOnCheckedChangeListener((g, i) -> {
|
||||||
expandFormModule();
|
expandFormModule();
|
||||||
evaluateAllConditionalLogic();
|
evaluateAllConditionalLogic();
|
||||||
|
|
@ -879,7 +862,6 @@ public class FormsFragment extends Fragment {
|
||||||
|
|
||||||
private void renderSelectField(LinearLayout container, GravityField field, Map<String, View> views, Map<String, Boolean> req) {
|
private void renderSelectField(LinearLayout container, GravityField field, Map<String, View> views, Map<String, Boolean> req) {
|
||||||
Spinner spinner = new Spinner(getContext());
|
Spinner spinner = new Spinner(getContext());
|
||||||
// Spinner touch listener is tricky, usually set onTouchListener works
|
|
||||||
spinner.setOnTouchListener((v, event) -> {
|
spinner.setOnTouchListener((v, event) -> {
|
||||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
expandFormModule();
|
expandFormModule();
|
||||||
|
|
@ -922,7 +904,6 @@ public class FormsFragment extends Fragment {
|
||||||
checkBox.setText(inputDef.label);
|
checkBox.setText(inputDef.label);
|
||||||
|
|
||||||
String value = "1";
|
String value = "1";
|
||||||
// Fallback
|
|
||||||
if (field.choices != null && i < field.choices.size()) {
|
if (field.choices != null && i < field.choices.size()) {
|
||||||
value = field.choices.get(i).value;
|
value = field.choices.get(i).value;
|
||||||
}
|
}
|
||||||
|
|
@ -940,24 +921,20 @@ public class FormsFragment extends Fragment {
|
||||||
|
|
||||||
private void renderDateField(LinearLayout container, GravityField field, Map<String, View> views, Map<String, Boolean> req) {
|
private void renderDateField(LinearLayout container, GravityField field, Map<String, View> views, Map<String, Boolean> req) {
|
||||||
EditText dateInput = new EditText(getContext());
|
EditText dateInput = new EditText(getContext());
|
||||||
// --- DATO LØSNING (Fix for Read Only / Dagens Dato) ---
|
|
||||||
if (field.readOnly || (formId == ID_REFUSJON_UTLEGG && "28".equals(field.id))) {
|
if (field.readOnly || (formId == ID_REFUSJON_UTLEGG && "28".equals(field.id))) {
|
||||||
// Sett dagens dato
|
|
||||||
SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault());
|
SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault());
|
||||||
dateInput.setText(df.format(new Date()));
|
dateInput.setText(df.format(new Date()));
|
||||||
|
|
||||||
// Gjør den "read-only" men synlig
|
|
||||||
dateInput.setFocusable(false);
|
dateInput.setFocusable(false);
|
||||||
dateInput.setClickable(false);
|
dateInput.setClickable(false);
|
||||||
dateInput.setEnabled(false);
|
dateInput.setEnabled(false);
|
||||||
dateInput.setTextColor(Color.BLACK);
|
dateInput.setTextColor(Color.BLACK);
|
||||||
} else {
|
} else {
|
||||||
// Vanlig dato-velger
|
|
||||||
dateInput.setFocusable(false);
|
dateInput.setFocusable(false);
|
||||||
dateInput.setClickable(true);
|
dateInput.setClickable(true);
|
||||||
dateInput.setHint("dd.mm.yyyy");
|
dateInput.setHint("dd.mm.yyyy");
|
||||||
dateInput.setOnClickListener(v -> {
|
dateInput.setOnClickListener(v -> {
|
||||||
expandFormModule(); // Trigger expand
|
expandFormModule();
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
new DatePickerDialog(getContext(), (view, year, month, dayOfMonth) -> {
|
new DatePickerDialog(getContext(), (view, year, month, dayOfMonth) -> {
|
||||||
dateInput.setText(String.format("%02d.%02d.%d", dayOfMonth, month + 1, year));
|
dateInput.setText(String.format("%02d.%02d.%d", dayOfMonth, month + 1, year));
|
||||||
|
|
@ -1361,20 +1338,17 @@ public class FormsFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Vis flere oppføringer siden vi nå har scrolle-mulighet øverst
|
|
||||||
int count = Math.min(entries.length(), 20);
|
int count = Math.min(entries.length(), 20);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
JSONObject entry = entries.getJSONObject(i);
|
JSONObject entry = entries.getJSONObject(i);
|
||||||
String date = entry.optString("date_created");
|
String date = entry.optString("date_created");
|
||||||
|
|
||||||
// Prøv å finne en bedre tittel enn bare dato (f.eks Prosjektnavn eller Sted)
|
|
||||||
String titleText = "Innsendt: " + date;
|
String titleText = "Innsendt: " + date;
|
||||||
TextView item = new TextView(getContext());
|
TextView item = new TextView(getContext());
|
||||||
item.setText(titleText);
|
item.setText(titleText);
|
||||||
item.setPadding(10, 20, 10, 20);
|
item.setPadding(10, 20, 10, 20);
|
||||||
item.setBackgroundResource(android.R.drawable.list_selector_background);
|
item.setBackgroundResource(android.R.drawable.list_selector_background);
|
||||||
item.setTextSize(14);
|
item.setTextSize(14);
|
||||||
// Add click listener to show details
|
|
||||||
item.setOnClickListener(v -> showEntryDetails(entry));
|
item.setOnClickListener(v -> showEntryDetails(entry));
|
||||||
View line = new View(getContext());
|
View line = new View(getContext());
|
||||||
line.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
|
line.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
|
||||||
|
|
@ -1387,20 +1361,16 @@ public class FormsFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NY METODE: Vis detaljer i dialog med delingsknapp
|
|
||||||
private void showEntryDetails(JSONObject entry) {
|
private void showEntryDetails(JSONObject entry) {
|
||||||
// HVIS dette er Form 16 (Refusjon), må vi først hente vedleggene (som ligger i Form 18)
|
|
||||||
if (formId == ID_REFUSJON_UTLEGG) {
|
if (formId == ID_REFUSJON_UTLEGG) {
|
||||||
Log.d(TAG, "Form 16 detected. Checking for child entries...");
|
Log.d(TAG, "Form 16 detected. Checking for child entries...");
|
||||||
String nestedIds = entry.optString("25"); // Felt 25 i Form 16 inneholder ID-ene til vedleggene
|
String nestedIds = entry.optString("25");
|
||||||
|
|
||||||
if (!nestedIds.isEmpty()) {
|
if (!nestedIds.isEmpty()) {
|
||||||
Log.d(TAG, "Nested IDs found: " + nestedIds);
|
Log.d(TAG, "Nested IDs found: " + nestedIds);
|
||||||
List<String> ids = new ArrayList<>();
|
List<String> ids = new ArrayList<>();
|
||||||
|
|
||||||
// ROBUST PARSING AV ID-LISTE
|
|
||||||
if (nestedIds.startsWith("[") && nestedIds.endsWith("]")) {
|
if (nestedIds.startsWith("[") && nestedIds.endsWith("]")) {
|
||||||
// Dette er en JSON-array streng (f.eks [101, 102])
|
|
||||||
try {
|
try {
|
||||||
JSONArray jsonArray = new JSONArray(nestedIds);
|
JSONArray jsonArray = new JSONArray(nestedIds);
|
||||||
for(int i=0; i<jsonArray.length(); i++) {
|
for(int i=0; i<jsonArray.length(); i++) {
|
||||||
|
|
@ -1410,42 +1380,34 @@ public class FormsFragment extends Fragment {
|
||||||
Log.e(TAG, "Failed to parse nested IDs as JSON array", e);
|
Log.e(TAG, "Failed to parse nested IDs as JSON array", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Dette er en komma-separert streng (f.eks "101, 102")
|
|
||||||
for (String id : nestedIds.split(",")) {
|
for (String id : nestedIds.split(",")) {
|
||||||
ids.add(id.trim());
|
ids.add(id.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ids.isEmpty()) {
|
if (!ids.isEmpty()) {
|
||||||
// Vis en "Laster..." dialog mens vi henter data
|
|
||||||
AlertDialog loadingDialog = new AlertDialog.Builder(getContext())
|
AlertDialog loadingDialog = new AlertDialog.Builder(getContext())
|
||||||
.setMessage("Henter vedleggsdetaljer...")
|
.setMessage("Henter vedleggsdetaljer...")
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.show();
|
.show();
|
||||||
|
|
||||||
// Start rekursiv henting
|
|
||||||
StringBuilder accumulatedHtml = new StringBuilder();
|
StringBuilder accumulatedHtml = new StringBuilder();
|
||||||
StringBuilder accumulatedText = new StringBuilder();
|
StringBuilder accumulatedText = new StringBuilder();
|
||||||
|
|
||||||
// Legg først til basis-info fra hovedskjemaet
|
|
||||||
appendBasicInfo(entry, accumulatedHtml, accumulatedText);
|
appendBasicInfo(entry, accumulatedHtml, accumulatedText);
|
||||||
|
|
||||||
fetchChildEntriesRecursive(ids, 0, accumulatedHtml, accumulatedText, loadingDialog);
|
fetchChildEntriesRecursive(ids, 0, accumulatedHtml, accumulatedText, loadingDialog);
|
||||||
return; // Stopp her, dialogen vises når data er hentet
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Log.d(TAG, "No nested IDs found in field 25.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- STANDARD VISNING (For alle andre skjemaer) ---
|
|
||||||
StringBuilder htmlBuilder = new StringBuilder();
|
StringBuilder htmlBuilder = new StringBuilder();
|
||||||
StringBuilder textBuilder = new StringBuilder();
|
StringBuilder textBuilder = new StringBuilder();
|
||||||
appendBasicInfo(entry, htmlBuilder, textBuilder);
|
appendBasicInfo(entry, htmlBuilder, textBuilder);
|
||||||
showFinalDialog(htmlBuilder, textBuilder);
|
showFinalDialog(htmlBuilder, textBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hjelpemetode for å legge til info fra hovedskjemaet
|
|
||||||
private void appendBasicInfo(JSONObject entry, StringBuilder html, StringBuilder text) {
|
private void appendBasicInfo(JSONObject entry, StringBuilder html, StringBuilder text) {
|
||||||
try {
|
try {
|
||||||
String date = entry.optString("date_created");
|
String date = entry.optString("date_created");
|
||||||
|
|
@ -1455,7 +1417,6 @@ public class FormsFragment extends Fragment {
|
||||||
if (currentForm != null && currentForm.fields != null) {
|
if (currentForm != null && currentForm.fields != null) {
|
||||||
for (GravityField field : currentForm.fields) {
|
for (GravityField field : currentForm.fields) {
|
||||||
if ("section".equals(field.type) || "html".equals(field.type) || "captcha".equals(field.type)) continue;
|
if ("section".equals(field.type) || "html".equals(field.type) || "captcha".equals(field.type)) continue;
|
||||||
// Hopp over felt 25 (Vedleggs-IDer) i Form 16, siden vi viser det bedre senere
|
|
||||||
if (formId == ID_REFUSJON_UTLEGG && "25".equals(field.id)) continue;
|
if (formId == ID_REFUSJON_UTLEGG && "25".equals(field.id)) continue;
|
||||||
|
|
||||||
String value = "";
|
String value = "";
|
||||||
|
|
@ -1470,8 +1431,6 @@ public class FormsFragment extends Fragment {
|
||||||
|
|
||||||
if (!value.trim().isEmpty()) {
|
if (!value.trim().isEmpty()) {
|
||||||
if ("fileupload".equals(field.type)) {
|
if ("fileupload".equals(field.type)) {
|
||||||
// Håndter filopplastinger (single/multiple)
|
|
||||||
// Her antar vi enkel URL, men for sikkerhets skyld bruker vi extractUrl
|
|
||||||
String cleanUrl = extractUrl(value);
|
String cleanUrl = extractUrl(value);
|
||||||
if (cleanUrl.startsWith("http")) {
|
if (cleanUrl.startsWith("http")) {
|
||||||
html.append("<b>").append(field.label).append(":</b><br>")
|
html.append("<b>").append(field.label).append(":</b><br>")
|
||||||
|
|
@ -1491,27 +1450,20 @@ public class FormsFragment extends Fragment {
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rekursiv metode for å hente barn-oppføringer (Vedlegg)
|
|
||||||
private void fetchChildEntriesRecursive(List<String> ids, int index, StringBuilder html, StringBuilder text, AlertDialog loader) {
|
private void fetchChildEntriesRecursive(List<String> ids, int index, StringBuilder html, StringBuilder text, AlertDialog loader) {
|
||||||
if (index >= ids.size()) {
|
if (index >= ids.size()) {
|
||||||
// Alle ferdige! Vis dialogen.
|
|
||||||
loader.dismiss();
|
loader.dismiss();
|
||||||
showFinalDialog(html, text);
|
showFinalDialog(html, text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String entryId = ids.get(index);
|
String entryId = ids.get(index);
|
||||||
Log.d(TAG, "Fetching child entry ID: " + entryId);
|
|
||||||
|
|
||||||
RetrofitClient.getApiService().getSingleEntry(entryId).enqueue(new retrofit2.Callback<JsonElement>() {
|
RetrofitClient.getApiService().getSingleEntry(entryId).enqueue(new retrofit2.Callback<JsonElement>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(retrofit2.Call<JsonElement> call, retrofit2.Response<JsonElement> response) {
|
public void onResponse(retrofit2.Call<JsonElement> call, retrofit2.Response<JsonElement> response) {
|
||||||
if (response.isSuccessful() && response.body() != null) {
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
try {
|
try {
|
||||||
JsonObject json = response.body().getAsJsonObject();
|
JsonObject json = response.body().getAsJsonObject();
|
||||||
// I Form 18: Felt 1 = Fil, Felt 3 = Beskrivelse, Felt 4 = Beløp
|
|
||||||
|
|
||||||
// Parse Description and Price
|
|
||||||
String desc = json.has("3") ? json.get("3").getAsString() : "Uten beskrivelse";
|
String desc = json.has("3") ? json.get("3").getAsString() : "Uten beskrivelse";
|
||||||
String price = json.has("4") ? json.get("4").getAsString() : "";
|
String price = json.has("4") ? json.get("4").getAsString() : "";
|
||||||
|
|
||||||
|
|
@ -1521,11 +1473,9 @@ public class FormsFragment extends Fragment {
|
||||||
html.append(desc).append(" (").append(price).append(")<br>");
|
html.append(desc).append(" (").append(price).append(")<br>");
|
||||||
text.append(desc).append(" (").append(price).append(")\n");
|
text.append(desc).append(" (").append(price).append(")\n");
|
||||||
|
|
||||||
// Parse File Field (ID 1) - Can be multiple files!
|
|
||||||
if (json.has("1")) {
|
if (json.has("1")) {
|
||||||
JsonElement fileEl = json.get("1");
|
JsonElement fileEl = json.get("1");
|
||||||
if (fileEl.isJsonArray()) {
|
if (fileEl.isJsonArray()) {
|
||||||
// It is a real JSON array
|
|
||||||
JsonArray arr = fileEl.getAsJsonArray();
|
JsonArray arr = fileEl.getAsJsonArray();
|
||||||
for (int i = 0; i < arr.size(); i++) {
|
for (int i = 0; i < arr.size(); i++) {
|
||||||
String url = arr.get(i).getAsString().replace("\\/", "/");
|
String url = arr.get(i).getAsString().replace("\\/", "/");
|
||||||
|
|
@ -1533,7 +1483,6 @@ public class FormsFragment extends Fragment {
|
||||||
text.append(url).append("\n");
|
text.append(url).append("\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// It is a string. Check if it's a JSON string array like "[\"http...\"]"
|
|
||||||
String rawString = fileEl.getAsString();
|
String rawString = fileEl.getAsString();
|
||||||
if (rawString.startsWith("[") && rawString.endsWith("]")) {
|
if (rawString.startsWith("[") && rawString.endsWith("]")) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -1544,13 +1493,11 @@ public class FormsFragment extends Fragment {
|
||||||
text.append(url).append("\n");
|
text.append(url).append("\n");
|
||||||
}
|
}
|
||||||
} catch (JSONException ex) {
|
} catch (JSONException ex) {
|
||||||
// Fallback: simple cleanup
|
|
||||||
String clean = extractUrl(rawString);
|
String clean = extractUrl(rawString);
|
||||||
html.append("<a href=\"").append(clean).append("\">Åpne fil</a><br>");
|
html.append("<a href=\"").append(clean).append("\">Åpne fil</a><br>");
|
||||||
text.append(clean).append("\n");
|
text.append(clean).append("\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Just a plain URL string
|
|
||||||
String clean = extractUrl(rawString);
|
String clean = extractUrl(rawString);
|
||||||
if(clean.startsWith("http")) {
|
if(clean.startsWith("http")) {
|
||||||
html.append("<a href=\"").append(clean).append("\">Åpne fil</a><br>");
|
html.append("<a href=\"").append(clean).append("\">Åpne fil</a><br>");
|
||||||
|
|
@ -1565,17 +1512,12 @@ public class FormsFragment extends Fragment {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Error parsing child entry", e);
|
Log.e(TAG, "Error parsing child entry", e);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Failed to fetch child entry: " + response.code());
|
|
||||||
}
|
}
|
||||||
// Gå til neste (uansett om denne feilet eller ei)
|
|
||||||
fetchChildEntriesRecursive(ids, index + 1, html, text, loader);
|
fetchChildEntriesRecursive(ids, index + 1, html, text, loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(retrofit2.Call<JsonElement> call, Throwable t) {
|
public void onFailure(retrofit2.Call<JsonElement> call, Throwable t) {
|
||||||
Log.e(TAG, "Network error fetching child entry", t);
|
|
||||||
// Hopp over ved feil
|
|
||||||
fetchChildEntriesRecursive(ids, index + 1, html, text, loader);
|
fetchChildEntriesRecursive(ids, index + 1, html, text, loader);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1598,7 +1540,6 @@ public class FormsFragment extends Fragment {
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hjelpemetode for å rydde opp i URLer fra JSON (f.eks ["http://..."] -> http://...)
|
|
||||||
private String extractUrl(String rawValue) {
|
private String extractUrl(String rawValue) {
|
||||||
if (rawValue == null) return "";
|
if (rawValue == null) return "";
|
||||||
String clean = rawValue.replace("[", "")
|
String clean = rawValue.replace("[", "")
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,25 @@
|
||||||
android:background="#F5F5F5"
|
android:background="#F5F5F5"
|
||||||
tools:context=".FormsFragment">
|
tools:context=".FormsFragment">
|
||||||
|
|
||||||
|
<!-- NYTT: Toolbar med tilbake-knapp -->
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.Light">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/forms_toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="@color/white"
|
||||||
|
app:navigationIcon="@android:drawable/ic_menu_revert"
|
||||||
|
app:titleTextColor="@color/black"
|
||||||
|
app:title="Laster..." />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<!-- Resten er likt, men nå under toolbaren -->
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/history_wrapper"
|
android:id="@+id/history_wrapper"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
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"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@android:color/white">
|
android:background="@android:color/white">
|
||||||
|
|
@ -91,12 +92,17 @@
|
||||||
android:text="Av: Forfatter"/>
|
android:text="Av: Forfatter"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- BYTTET FRA TextView TIL WebView -->
|
<!--
|
||||||
|
WebView for innhold.
|
||||||
|
tools:ignore="WebViewLayout" hindrer feilmeldingen om wrap_content,
|
||||||
|
da dette er ønsket oppførsel inne i en NestedScrollView.
|
||||||
|
-->
|
||||||
<WebView
|
<WebView
|
||||||
android:id="@+id/detail_webview"
|
android:id="@+id/detail_webview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:scrollbars="none" />
|
android:scrollbars="none"
|
||||||
|
tools:ignore="WebViewLayout" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue