diff --git a/app/release/app-release.apk b/app/release/app-release.apk new file mode 100644 index 0000000..ee88b35 Binary files /dev/null and b/app/release/app-release.apk differ diff --git a/app/release/baselineProfiles/0/app-release.dm b/app/release/baselineProfiles/0/app-release.dm new file mode 100644 index 0000000..2a563fe Binary files /dev/null and b/app/release/baselineProfiles/0/app-release.dm differ diff --git a/app/release/baselineProfiles/1/app-release.dm b/app/release/baselineProfiles/1/app-release.dm new file mode 100644 index 0000000..15fdf75 Binary files /dev/null and b/app/release/baselineProfiles/1/app-release.dm differ diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json new file mode 100644 index 0000000..f49adf9 --- /dev/null +++ b/app/release/output-metadata.json @@ -0,0 +1,37 @@ +{ + "version": 3, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.kbs.kbsintranett", + "variantName": "release", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "attributes": [], + "versionCode": 1, + "versionName": "1.0", + "outputFile": "app-release.apk" + } + ], + "elementType": "File", + "baselineProfiles": [ + { + "minApi": 28, + "maxApi": 30, + "baselineProfiles": [ + "baselineProfiles/1/app-release.dm" + ] + }, + { + "minApi": 31, + "maxApi": 2147483647, + "baselineProfiles": [ + "baselineProfiles/0/app-release.dm" + ] + } + ], + "minSdkVersionForDexing": 28 +} \ No newline at end of file diff --git a/hele_prosjektet.txt b/hele_prosjektet.txt index fbec233..9018bbd 100644 --- a/hele_prosjektet.txt +++ b/hele_prosjektet.txt @@ -3193,24 +3193,32 @@ public class HandbookAdapter extends RecyclerView.Adapter" + + "body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; color: #333333; line-height: 1.6; padding: 16px; margin: 0; }" + + + "h1 { color: #0069B3; font-size: 24px; border-bottom: 2px solid #0069B3; padding-bottom: 10px; margin-top: 0; }" + + "p, ul, li { margin-bottom: 12px; }" + + "a { color: #0069B3; font-weight: bold; text-decoration: none; }" + + + // --- BOKSEN --- + ".trekkspill { " + + " background-color: #fff; " + + " border: 1px solid #ddd; " + + " border-radius: 4px; " + + " max-height: 58px; " + // LUKKET + " overflow: hidden; " + + " transition: max-height 0.4s ease; " + + + // LUFT OG AVSTAND + " margin-top: 32px; " + + " margin-bottom: 16px; " + + "}" + + + // --- KNAPPEN --- + ".trekkspill > a[id^='fl-accordion--label-'] { " + + " display: flex; " + + " justify-content: space-between; " + + " align-items: center; " + + " background-color: #f2f2f2; " + + " color: #0069B3; " + + " padding: 15px; " + + " font-weight: bold; " + + " cursor: pointer; " + + " width: 100%; " + + " height: 58px; " + + " box-sizing: border-box; " + + " pointer-events: auto; " + + "}" + + + // --- PLUSS-TEGN --- + ".trekkspill > a[id^='fl-accordion--label-']::after { " + + " content: '+'; " + + " font-size: 24px; " + + " font-weight: bold; " + + " color: #0069B3; " + + "}" + + + // --- ÅPEN TILSTAND --- + ".trekkspill.open { " + + " max-height: 4000px; " + // ÅPEN + " overflow: visible; " + + " border-color: #0069B3; " + + "}" + + + ".trekkspill.open > a[id^='fl-accordion--label-'] { " + + " background-color: #0069B3; " + + " color: #ffffff; " + + "}" + + + ".trekkspill.open > a[id^='fl-accordion--label-']::after { " + + " content: '-'; " + + " color: #ffffff; " + + "}" + + + // --- RYDDEJOBB --- + ".trekkspill > a[id^='fl-accordion--icon-'] { display: none !important; }" + + ".trekkspill > h2 { display: none; }" + + ".trekkspill > p, .trekkspill > ul, .trekkspill > div { padding: 10px 15px; }" + + + ""; + + // --- JAVASCRIPT: AUTOSCROLL --- + private static final String JS_SCRIPT = + ""; + @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -3233,28 +3346,187 @@ public class HandbookDetailFragment extends Fragment { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - // Hent argumenter fra navigasjon if (getArguments() != null) { pageId = getArguments().getInt("page_id"); pageTitle = getArguments().getString("page_title"); } Toolbar toolbar = view.findViewById(R.id.detail_toolbar); - toolbar.setTitle("Håndbok"); + toolbar.setTitle(pageTitle != null ? pageTitle : "Håndbok"); toolbar.setNavigationOnClickListener(v -> Navigation.findNavController(view).navigateUp()); - titleView = view.findViewById(R.id.detail_title); - contentView = view.findViewById(R.id.detail_content); + webView = view.findViewById(R.id.detail_webview); progressBar = view.findViewById(R.id.detail_loading); - titleView.setText(pageTitle); // Sett midlertidig tittel - + setupWebView(); fetchContent(); } + private void setupWebView() { + WebSettings settings = webView.getSettings(); + settings.setJavaScriptEnabled(true); + settings.setDomStorageEnabled(true); + settings.setCacheMode(WebSettings.LOAD_NO_CACHE); + + webView.setWebViewClient(new WebViewClient() { + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + return handleLinkClick(request.getUrl().toString()); + } + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + return handleLinkClick(url); + } + }); + } + + private boolean handleLinkClick(String url) { + // Ignorer klikk på accordion-lenker + if (url.endsWith("#")) return true; + + String lowerUrl = url.toLowerCase(); + int formIdToOpen = 0; + + // --- SPESIALHÅNDTERING: Link til Skjemaer basert på URL-nøkkelord --- + + // ID 1: Ansatteopplysninger + if (lowerUrl.contains("ansatteopplysninger")) { + formIdToOpen = 1; + } + // ID 2: Vernerunde + else if (lowerUrl.contains("vernerunde")) { + formIdToOpen = 2; + } + // ID 4: RUH (Rapport om uønsket hendelse) + else if (lowerUrl.contains("uonsket-hendelse") || lowerUrl.contains("/ruh")) { + formIdToOpen = 4; + } + // ID 5: Lån av verktøy/henger + else if (lowerUrl.contains("lan-av") || lowerUrl.contains("verktoy")) { + formIdToOpen = 5; + } + // ID 6: Avviksmelding + else if (lowerUrl.contains("avviksmelding") || lowerUrl.contains("/avvik")) { + formIdToOpen = 6; + } + // ID 9: Sikkerhetskurs / Kompetansebevis + else if (lowerUrl.contains("sikkerhetskurs") || lowerUrl.contains("kompetansebevis")) { + formIdToOpen = 9; + } + // ID 10: HMS Bekreftelse + else if (lowerUrl.contains("hms-bekreftelse") || lowerUrl.contains("hms-policy")) { + formIdToOpen = 10; + } + // ID 11: Egenmelding + else if (lowerUrl.contains("egenmelding")) { + formIdToOpen = 11; + } + // ID 12: Sjekkliste firmabil + else if (lowerUrl.contains("sjekkliste") && (lowerUrl.contains("bil") || lowerUrl.contains("kjoretoy"))) { + formIdToOpen = 12; + } + // ID 14: SJA (Sikker Jobbanalyse) + else if (lowerUrl.contains("sja") || lowerUrl.contains("jobbanalyse")) { + formIdToOpen = 14; + } + // ID 15: Fraværsvarsel + else if (lowerUrl.contains("fravaersvarsel") || lowerUrl.contains("fravarsvarsel")) { + formIdToOpen = 15; + } + // ID 16: Refusjon utlegg + else if (lowerUrl.contains("refusjon") || lowerUrl.contains("utlegg")) { + formIdToOpen = 16; + } + // ID 21: Medarbeidersamtale + else if (lowerUrl.contains("medarbeidersamtale")) { + formIdToOpen = 21; + } + // ID 22: Medarbeiderundersøkelse + else if (lowerUrl.contains("medarbeiderundersokelse")) { + formIdToOpen = 22; + } + + // Hvis vi fant et skjema, naviger dit internt + if (formIdToOpen > 0) { + Bundle bundle = new Bundle(); + bundle.putInt("formId", formIdToOpen); + Navigation.findNavController(getView()).navigate(R.id.action_handbook_to_form, bundle); + return true; + } + + // --- STANDARD INTERN NAVIGASJON --- + if (url.contains("intranet.kbs.no") || url.startsWith("/")) { + int targetId = extractIdFromUrl(url); + if (targetId > 0) { + navigateToPage(targetId, "Laster..."); + return true; + } + + progressBar.setVisibility(View.VISIBLE); + RetrofitClient.getApiService().lookupPageId(url).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (!isAdded()) return; + progressBar.setVisibility(View.GONE); + + if (response.isSuccessful() && response.body() != null) { + int id = response.body().get("id").getAsInt(); + if (id > 0) { + navigateToPage(id, "Laster..."); + } else { + openExternal(url); + } + } else { + openExternal(url); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + if (!isAdded()) return; + progressBar.setVisibility(View.GONE); + openExternal(url); + } + }); + return true; + } else { + // Ekstern lenke + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(browserIntent); + return true; + } + } + + private void navigateToPage(int id, String title) { + Bundle bundle = new Bundle(); + bundle.putInt("page_id", id); + bundle.putString("page_title", title); + Navigation.findNavController(getView()).navigate(R.id.action_handbook_to_detail, bundle); + } + + private void openExternal(String url) { + Intent intent = new Intent(getContext(), WebViewActivity.class); + intent.putExtra(WebViewActivity.EXTRA_URL, url); + intent.putExtra(WebViewActivity.EXTRA_TITLE, "KBS Intranett"); + startActivity(intent); + } + + private int extractIdFromUrl(String url) { + Pattern p = Pattern.compile("[?&](p|page_id|post)=([0-9]+)"); + Matcher m = p.matcher(url); + if (m.find()) { + try { + return Integer.parseInt(m.group(2)); + } catch (NumberFormatException e) { + return 0; + } + } + return 0; + } + private void fetchContent() { progressBar.setVisibility(View.VISIBLE); - RetrofitClient.getApiService().getHandbookPage(pageId).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { @@ -3263,17 +3535,29 @@ public class HandbookDetailFragment extends Fragment { if (response.isSuccessful() && response.body() != null) { HandbookPage page = response.body(); - titleView.setText(page.title); - // RENDERING AV HTML - // HtmlCompat.FROM_HTML_MODE_COMPACT håndterer grunnleggende tags (p, br, b, i, h1-h6, ul, li) - // Det støtter dessverre ikke tabeller eller bilder optimalt rett i TextView. - if (page.content != null) { - contentView.setText(HtmlCompat.fromHtml(page.content, HtmlCompat.FROM_HTML_MODE_COMPACT)); - contentView.setMovementMethod(LinkMovementMethod.getInstance()); // Gjør linker klikkbare - } else { - contentView.setText("Ingen innhold funnet."); + if (getView() != null) { + Toolbar toolbar = getView().findViewById(R.id.detail_toolbar); + if (toolbar != null) toolbar.setTitle(page.title); } + + String htmlContent = "" + + "" + + CSS_STYLE + + JS_SCRIPT + + ""; + + htmlContent += "

" + page.title + "

"; + + if (page.content != null) { + htmlContent += page.content; + } else { + htmlContent += "

Ingen innhold funnet.

"; + } + htmlContent += ""; + + webView.loadDataWithBaseURL("https://intranet.kbs.no", htmlContent, "text/html", "UTF-8", null); + } else { Toast.makeText(getContext(), "Kunne ikke laste innhold.", Toast.LENGTH_SHORT).show(); } @@ -4619,6 +4903,7 @@ public class ProfileFragment extends Fragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_profile, container, false); + // 1. Finn Views ImageView closeBtn = view.findViewById(R.id.btn_close_profile); ImageView profileImage = view.findViewById(R.id.profile_image); @@ -4626,6 +4911,7 @@ public class ProfileFragment extends Fragment { TextView emailText = view.findViewById(R.id.profile_email); TextView roleText = view.findViewById(R.id.profile_role); Button logoutBtn = view.findViewById(R.id.btn_logout); + Button updateInfoBtn = view.findViewById(R.id.btn_update_info); // NY // 2. Hent data fra UserManager UserManager user = UserManager.getInstance(); @@ -4646,7 +4932,14 @@ public class ProfileFragment extends Fragment { Navigation.findNavController(view).navigateUp(); }); - // 5. Håndter utlogging + // 5. Håndter "Oppdater opplysninger" (Skjema ID 1) + updateInfoBtn.setOnClickListener(v -> { + Bundle bundle = new Bundle(); + bundle.putInt("formId", 1); // ID 1 er Ansatteopplysninger + Navigation.findNavController(view).navigate(R.id.action_profile_to_form, bundle); + }); + + // 6. Håndter utlogging logoutBtn.setOnClickListener(v -> performLogout()); return view; @@ -5707,6 +6000,15 @@ FILSTI: app\src\main\res\layout\fragment_handbook.xml android:textColor="#333333" android:layout_marginBottom="12dp"/> + + - - + + + android:layout_centerInParent="true" + android:visibility="gone"/> - + - - - - - - ============================================================ @@ -6135,44 +6418,50 @@ FILSTI: app\src\main\res\layout\fragment_profile.xml android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp" - android:background="@color/kbs_very_light_blue"> + android:background="@color/kbs_very_light_blue"> - - + android:layout_marginBottom="32dp" + android:paddingHorizontal="10dp" + android:background="@color/kbs_logo_blue" > + + + + + + android:paddingTop="32dp"> + + + android:layout_marginBottom="32dp"/> + +