From 76dbcda6ca1faac58b14b6f6084f066ee838a248 Mon Sep 17 00:00:00 2001 From: Amanpal Singh <87360222+aman-alfresco@users.noreply.github.com> Date: Tue, 5 Mar 2024 09:54:22 +0530 Subject: [PATCH] added default and custom outcomes --- auth/build.gradle | 1 + .../kotlin/com/alfresco/ui/SplashActivity.kt | 45 +---- capture/src/main/res/values-de/strings.xml | 64 +++---- capture/src/main/res/values-es/strings.xml | 64 +++---- capture/src/main/res/values-fr/strings.xml | 64 +++---- capture/src/main/res/values-it/strings.xml | 64 +++---- capture/src/main/res/values-nl/strings.xml | 64 +++---- .../content/common/SharedURLParser.kt | 56 ++++++ common/src/main/res/values-de/strings.xml | 66 +++---- common/src/main/res/values-es/strings.xml | 66 +++---- common/src/main/res/values-fr/strings.xml | 66 +++---- common/src/main/res/values-it/strings.xml | 66 +++---- common/src/main/res/values-nl/strings.xml | 66 +++---- .../content/component/ComponentData.kt | 28 ++- .../content/component/ComponentSheet.kt | 82 ++++++-- .../component/ComponentSheetExtension.kt | 15 ++ .../content/component/ComponentType.kt | 1 + .../content/component/ListViewActionsRow.kt | 36 ++++ .../res/layout/sheet_component_filter.xml | 11 ++ .../res/layout/view_actions_component.xml | 16 ++ .../main/res/layout/view_actions_list_row.xml | 18 ++ component/src/main/res/values-de/strings.xml | 66 +++---- component/src/main/res/values-es/strings.xml | 66 +++---- component/src/main/res/values-fr/strings.xml | 66 +++---- component/src/main/res/values-it/strings.xml | 66 +++---- component/src/main/res/values-nl/strings.xml | 66 +++---- process-app/build.gradle | 1 + .../alfresco/content/process/FormViewModel.kt | 8 +- .../content/process/ui/FormDetailScreen.kt | 176 ++++-------------- .../ui/components/FloatingActionButton.kt | 27 ++- .../process/ui/components/FormScreen.kt | 47 +++-- .../ui/components/FormScrollContent.kt | 135 ++++++++++++++ .../process/ui/components/HyperLinkField.kt | 42 ++++- .../content/process/ui/components/Outcomes.kt | 26 +++ search/src/main/res/values-es/strings.xml | 138 +++++++------- 35 files changed, 1116 insertions(+), 773 deletions(-) create mode 100644 common/src/main/kotlin/com/alfresco/content/common/SharedURLParser.kt create mode 100644 component/src/main/java/com/alfresco/content/component/ListViewActionsRow.kt create mode 100644 component/src/main/res/layout/view_actions_component.xml create mode 100644 component/src/main/res/layout/view_actions_list_row.xml create mode 100644 process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FormScrollContent.kt create mode 100644 process-app/src/main/kotlin/com/alfresco/content/process/ui/components/Outcomes.kt diff --git a/auth/build.gradle b/auth/build.gradle index 462f45c73..b500d5a40 100644 --- a/auth/build.gradle +++ b/auth/build.gradle @@ -16,6 +16,7 @@ dependencies { implementation project(':base-ui') implementation project(':theme') implementation project(':data') + implementation project(':common') implementation libs.kotlin.stdlib diff --git a/auth/src/main/kotlin/com/alfresco/ui/SplashActivity.kt b/auth/src/main/kotlin/com/alfresco/ui/SplashActivity.kt index 90687b4e1..c7afb2f5e 100644 --- a/auth/src/main/kotlin/com/alfresco/ui/SplashActivity.kt +++ b/auth/src/main/kotlin/com/alfresco/ui/SplashActivity.kt @@ -6,10 +6,15 @@ import android.os.Handler import android.os.Looper import androidx.appcompat.app.AppCompatActivity import com.alfresco.android.aims.R +import com.alfresco.content.common.SharedURLParser +import com.alfresco.content.common.SharedURLParser.Companion.ID_KEY +import com.alfresco.content.common.SharedURLParser.Companion.KEY_FOLDER +import com.alfresco.content.common.SharedURLParser.Companion.MODE_KEY +import com.alfresco.content.common.SharedURLParser.Companion.VALUE_REMOTE +import com.alfresco.content.common.SharedURLParser.Companion.VALUE_SHARE import com.alfresco.content.data.rooted.CheckForRootWorker import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import java.net.URLDecoder abstract class SplashActivity : AppCompatActivity() { @@ -22,7 +27,10 @@ abstract class SplashActivity : AppCompatActivity() { super.onCreate(savedInstanceState) if (intent.data != null && intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0) { // Handle the url passed through the intent - entryId = getEntryIdFromShareURL() + val urlData = SharedURLParser().getEntryIdFromShareURL(intent.data.toString()) + isRemoteFolder = urlData.third + entryId = urlData.second + isPreview = urlData.first } setContentView(R.layout.activity_alfresco_splash) } @@ -34,28 +42,6 @@ abstract class SplashActivity : AppCompatActivity() { handler.removeCallbacksAndMessages(null) } - private fun getEntryIdFromShareURL(): String { - isPreview = false - isRemoteFolder = false - val extData = URLDecoder.decode(intent.data.toString(), "UTF-8") - - if (!extData.contains(SCHEME)) return "" - - if (extData.contains(IDENTIFIER_PREVIEW)) { - isPreview = true - return extData.substringAfter(SCHEME) - } - - if (!extData.contains(IDENTIFIER_PERSONAL_FILES)) return "" - - return if (extData.contains(IDENTIFIER_VIEWER)) { - extData.substringAfter(IDENTIFIER_VIEWER).substringBefore(DELIMITER_BRACKET) - } else { - isRemoteFolder = true - extData.substringAfter(IDENTIFIER_PERSONAL_FILES).substringBefore(DELIMITER_FORWARD_SLASH) - } - } - override fun onResume() { super.onResume() @@ -90,16 +76,5 @@ abstract class SplashActivity : AppCompatActivity() { companion object { private const val DISPLAY_TIMEOUT = 100L - private const val ID_KEY = "id" - private const val MODE_KEY = "mode" - private const val VALUE_REMOTE = "remote" - private const val VALUE_SHARE = "share" - const val KEY_FOLDER = "folder" - const val SCHEME = "androidamw:///" - const val IDENTIFIER_PREVIEW = "/preview" - const val IDENTIFIER_VIEWER = "viewer:view/" - const val IDENTIFIER_PERSONAL_FILES = "/personal-files/" - const val DELIMITER_BRACKET = ")" - const val DELIMITER_FORWARD_SLASH = "/" } } diff --git a/capture/src/main/res/values-de/strings.xml b/capture/src/main/res/values-de/strings.xml index 64cb645ef..21ccd2dec 100644 --- a/capture/src/main/res/values-de/strings.xml +++ b/capture/src/main/res/values-de/strings.xml @@ -1,32 +1,32 @@ - - - Schließen - Aufnehmen - Kamera wechseln - Gallerie - Blitzlicht-Modus - - Foto - Video - - Fotovorschau - Dateiname - Beschreibung - Foto löschen - Speichern - Der Dateiname darf keines der folgenden Zeichen enthalten: ?:\"*|/\<> - Der Dateiname darf nicht leer sein. - - Vorschau - - Audio - An - Aus - - @string/capture_failure_permissions - Für Medienaufnahmen müssen die Berechtigungen zur Nutzung von Kamera und Mikrofon erteilt werden. - %02d:%02d:%02d - %02d:%02d - Die ausgewählte Dateigröße darf beim Hochladen 100 MB nicht überschreiten. - - + + + Schließen + Aufnehmen + Kamera wechseln + Gallerie + Blitzlicht-Modus + + Foto + Video + + Fotovorschau + Dateiname + Beschreibung + Foto löschen + Speichern + Der Dateiname darf keines der folgenden Zeichen enthalten: ?:\"*|/\<> + Der Dateiname darf nicht leer sein. + + Vorschau + + Audio + An + Aus + + @string/capture_failure_permissions + Für Medienaufnahmen müssen die Berechtigungen zur Nutzung von Kamera und Mikrofon erteilt werden. + %02d:%02d:%02d + %02d:%02d + Die ausgewählte Dateigröße darf beim Hochladen 100 MB nicht überschreiten. + + diff --git a/capture/src/main/res/values-es/strings.xml b/capture/src/main/res/values-es/strings.xml index fccfd95ed..1141147c6 100644 --- a/capture/src/main/res/values-es/strings.xml +++ b/capture/src/main/res/values-es/strings.xml @@ -1,32 +1,32 @@ - - - Cerrar - Tomar foto - Cambiar de cámara - Galería - Modo con flash - - Foto - Vídeo - - Vista previa de foto - Nombre de fichero - Añadir descripción - Eliminar foto - Guardar - El nombre del fichero no puede contener ninguno de los siguientes caracteres: ?: \"*|/\<> - El nombre del fichero no puede estar vacío. - - Vista previa - - Automático - Encendido - Apagado - - @string/capture_failure_permissions - Para tomar fotos o grabar vídeos, active los permisos de Cámara y Micrófono. - %02d:%02d:%02d - %02d:%02d - El tamaño del fichero seleccionado no puede superar los 100 MB para cargarlo. - - + + + Cerrar + Tomar foto + Cambiar de cámara + Galería + Modo con flash + + Foto + Vídeo + + Vista previa de foto + Nombre de fichero + Añadir descripción + Eliminar foto + Guardar + El nombre del fichero no puede contener ninguno de los siguientes caracteres: ?: \"*|/\<> + El nombre del fichero no puede estar vacío. + + Vista previa + + Automático + Encendido + Apagado + + @string/capture_failure_permissions + Para tomar fotos o grabar vídeos, active los permisos de Cámara y Micrófono. + %02d:%02d:%02d + %02d:%02d + El tamaño del fichero seleccionado no puede superar los 100 MB para cargarlo. + + diff --git a/capture/src/main/res/values-fr/strings.xml b/capture/src/main/res/values-fr/strings.xml index 82d8f8f38..656a4cd29 100644 --- a/capture/src/main/res/values-fr/strings.xml +++ b/capture/src/main/res/values-fr/strings.xml @@ -1,32 +1,32 @@ - - - Fermer - Capture - Changer de caméra - Galerie - Modèle de flash - - Photo - Vidéo - - Aperçu de la photo - Nom de fichier - Ajouter une description - Supprimer la photo - Enregistrer - Le nom de fichier ne peut pas contenir les caractères suivants : ?:\"*|/\<> - Le nom du fichier ne peut pas être vide. - - Aperçu - - Auto - Activé - Désactivé - - @string/capture_failure_permissions - Pour capturer des médias, activez les autorisations de l\'appareil photo et du microphone. - %02d:%02d:%02d - %02d:%02d - La taille du fichier sélectionné pour importation ne peut pas dépasser 100 Mo. - - + + + Fermer + Capture + Changer de caméra + Galerie + Modèle de flash + + Photo + Vidéo + + Aperçu de la photo + Nom de fichier + Ajouter une description + Supprimer la photo + Enregistrer + Le nom de fichier ne peut pas contenir les caractères suivants : ?:\"*|/\<> + Le nom du fichier ne peut pas être vide. + + Aperçu + + Auto + Activé + Désactivé + + @string/capture_failure_permissions + Pour capturer des médias, activez les autorisations de l\'appareil photo et du microphone. + %02d:%02d:%02d + %02d:%02d + La taille du fichier sélectionné pour importation ne peut pas dépasser 100 Mo. + + diff --git a/capture/src/main/res/values-it/strings.xml b/capture/src/main/res/values-it/strings.xml index 7d28a6699..b73e03b92 100644 --- a/capture/src/main/res/values-it/strings.xml +++ b/capture/src/main/res/values-it/strings.xml @@ -1,32 +1,32 @@ - - - Chiudi - Acquisisci - Passa dalla fotocamera anteriore a quella posteriore - Galleria - Modalità flash - - Foto - Video - - Anteprima foto - Nome file - Aggiungi descrizione - Elimina foto - Salva - Il nome del file non può contenere i caratteri seguenti: ?:\"*|/\<> - Il nome file non può essere vuoto. - - Anteprima - - Automatico - Attiva - Disattiva - - @string/capture_failure_permissions - Per acquisire i contenuti multimediali, abilitare le autorizzazioni per la fotocamera e il microfono. - %02d:%02d:%02d - %02d:%02d - Le dimensioni del file selezionato per il caricamento non possono superare 100 MB. - - + + + Chiudi + Acquisisci + Passa dalla fotocamera anteriore a quella posteriore + Galleria + Modalità flash + + Foto + Video + + Anteprima foto + Nome file + Aggiungi descrizione + Elimina foto + Salva + Il nome del file non può contenere i caratteri seguenti: ?:\"*|/\<> + Il nome file non può essere vuoto. + + Anteprima + + Automatico + Attiva + Disattiva + + @string/capture_failure_permissions + Per acquisire i contenuti multimediali, abilitare le autorizzazioni per la fotocamera e il microfono. + %02d:%02d:%02d + %02d:%02d + Le dimensioni del file selezionato per il caricamento non possono superare 100 MB. + + diff --git a/capture/src/main/res/values-nl/strings.xml b/capture/src/main/res/values-nl/strings.xml index 4746d2716..086d1c709 100644 --- a/capture/src/main/res/values-nl/strings.xml +++ b/capture/src/main/res/values-nl/strings.xml @@ -1,32 +1,32 @@ - - - Sluiten - Vastleggen - Van camera wisselen - Galerie - Flitsmodus - - Foto - Video - - Fotopreview - Bestandsnaam - Beschrijving toevoegen - Foto verwijderen - Opslaan - Bestandsnaam mag geen van de volgende tekens bevatten: ?:\"*|/\<> - Bestandsnaam mag niet leeg zijn. - - Preview - - Auto - Aan - Uit - - @string/capture_failure_permissions - Om media vast te leggen, schakelt u camera- en microfoonrechten in. - %02d:%02d:%02d - %02d:%02d - Het geselecteerde bestand mag niet groter zijn dan 100 MB om te kunnen worden geüpload. - - + + + Sluiten + Vastleggen + Van camera wisselen + Galerie + Flitsmodus + + Foto + Video + + Fotopreview + Bestandsnaam + Beschrijving toevoegen + Foto verwijderen + Opslaan + Bestandsnaam mag geen van de volgende tekens bevatten: ?:\"*|/\<> + Bestandsnaam mag niet leeg zijn. + + Preview + + Auto + Aan + Uit + + @string/capture_failure_permissions + Om media vast te leggen, schakelt u camera- en microfoonrechten in. + %02d:%02d:%02d + %02d:%02d + Het geselecteerde bestand mag niet groter zijn dan 100 MB om te kunnen worden geüpload. + + diff --git a/common/src/main/kotlin/com/alfresco/content/common/SharedURLParser.kt b/common/src/main/kotlin/com/alfresco/content/common/SharedURLParser.kt new file mode 100644 index 000000000..6c5ef2e4a --- /dev/null +++ b/common/src/main/kotlin/com/alfresco/content/common/SharedURLParser.kt @@ -0,0 +1,56 @@ +package com.alfresco.content.common + +import java.net.URLDecoder + +class SharedURLParser { + + /** + * isPreview (Boolean) + * String + * isRemoteFolder (Boolean) + */ + fun getEntryIdFromShareURL(url: String, isHyperLink: Boolean = false): Triple { + val extData = URLDecoder.decode(url, "UTF-8") + + if (!isHyperLink && !extData.contains(SCHEME)) return Triple(false, "", false) + + if (extData.contains(IDENTIFIER_PREVIEW)) { + return Triple( + true, + extData.substringAfter(SCHEME), + false, + ) + } + + if (!extData.contains(IDENTIFIER_PERSONAL_FILES)) return Triple(false, "", false) + + return if (extData.contains(IDENTIFIER_VIEWER)) { + Triple( + false, + extData.substringAfter(IDENTIFIER_VIEWER).substringBefore(DELIMITER_BRACKET), + false, + ) + } else { + Triple( + false, + extData.substringAfter(IDENTIFIER_PERSONAL_FILES) + .substringBefore(DELIMITER_FORWARD_SLASH), + true, + ) + } + } + + companion object { + const val ID_KEY = "id" + const val MODE_KEY = "mode" + const val VALUE_REMOTE = "remote" + const val VALUE_SHARE = "share" + const val KEY_FOLDER = "folder" + const val SCHEME = "androidamw:///" + const val IDENTIFIER_PREVIEW = "/preview" + const val IDENTIFIER_VIEWER = "viewer:view/" + const val IDENTIFIER_PERSONAL_FILES = "/personal-files/" + const val DELIMITER_BRACKET = ")" + const val DELIMITER_FORWARD_SLASH = "/" + } +} diff --git a/common/src/main/res/values-de/strings.xml b/common/src/main/res/values-de/strings.xml index eb63866b8..7eb4c7b51 100755 --- a/common/src/main/res/values-de/strings.xml +++ b/common/src/main/res/values-de/strings.xml @@ -1,33 +1,33 @@ - - - Berechtigungen erforderlich - OK - Abbrechen - Zurück - Niedrig - Mittel - Hoch - NV - Mich - M - Titel: %s Zugewiesener Benutzer: %s Priorität %s - Titel: %s Pfad: %s - Titel: %s - Ordner: %s - Titel: %s Typ: %s - Kopfzeile: %s - Mehr - Herunterladen - Favorit hinzufügen - Favorit entfernen - Erstellen - Es gibt bereits einen Ordner mit diesem Namen. Versuchen Sie es mit einem anderen Namen. - Titel: %s Zugewiesener Benutzer: %s - Einzelperson - Gruppe - Der Hochladevorgang wird gerade durchgeführt. Möchten Sie ohne Upload fortfahren? - Keine - %d Ausgewählt - Bitte überprüfen Sie Ihre Internetverbindung und starten anschließend den Vorgang erneut. - ...Alle anzeigen - + + + Berechtigungen erforderlich + OK + Abbrechen + Zurück + Niedrig + Mittel + Hoch + NV + Mich + M + Titel: %s Zugewiesener Benutzer: %s Priorität %s + Titel: %s Pfad: %s + Titel: %s + Ordner: %s + Titel: %s Typ: %s + Kopfzeile: %s + Mehr + Herunterladen + Favorit hinzufügen + Favorit entfernen + Erstellen + Es gibt bereits einen Ordner mit diesem Namen. Versuchen Sie es mit einem anderen Namen. + Titel: %s Zugewiesener Benutzer: %s + Einzelperson + Gruppe + Der Hochladevorgang wird gerade durchgeführt. Möchten Sie ohne Upload fortfahren? + Keine + %d Ausgewählt + Bitte überprüfen Sie Ihre Internetverbindung und starten anschließend den Vorgang erneut. + ...Alle anzeigen + diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index 47a692a7b..f9b91786b 100755 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -1,33 +1,33 @@ - - - Se necesitan permisos - Aceptar - Cancelar - Volver - Baja - Mediano - Alta - NA - Yo - Y - Título: %s Asignado: %s Prioridad %s - Título: %s Ruta: %s - Título: %s - Carpeta: %s - Título: %s Tipo: %s - Encabezado: %s - Más - Descargar - Añadir Favorito - Eliminar Favorito - Crear - Ya existe una carpeta con este nombre. Pruebe un nombre diferente. - Título: %s Usuario asignado: %s - Individual - Grupo - La carga ya está en curso. ¿Desea continuar sin cargar? - Ninguno - %d Seleccionado - Verifique su conexión a Internet y vuelva a intentarlo. - ...Ver todo - + + + Se necesitan permisos + Aceptar + Cancelar + Volver + Baja + Mediano + Alta + NA + Yo + Y + Título: %s Asignado: %s Prioridad %s + Título: %s Ruta: %s + Título: %s + Carpeta: %s + Título: %s Tipo: %s + Encabezado: %s + Más + Descargar + Añadir Favorito + Eliminar Favorito + Crear + Ya existe una carpeta con este nombre. Pruebe un nombre diferente. + Título: %s Usuario asignado: %s + Individual + Grupo + La carga ya está en curso. ¿Desea continuar sin cargar? + Ninguno + %d Seleccionado + Verifique su conexión a Internet y vuelva a intentarlo. + ...Ver todo + diff --git a/common/src/main/res/values-fr/strings.xml b/common/src/main/res/values-fr/strings.xml index b16022c11..843b09a56 100755 --- a/common/src/main/res/values-fr/strings.xml +++ b/common/src/main/res/values-fr/strings.xml @@ -1,33 +1,33 @@ - - - Permissions nécessaires - Ok - Annuler - Retour - Basse - Moyenne - Élevée - NA - Moi - M - Titre : %s Personne assignée : %s Priorité %s - Titre : %s Chemin : %s - Titre : %s - Dossier : %s - Titre : %s Type : %s - En-tête : %s - Plus - Télécharger - Ajouter aux favoris - Supprimer des favoris - Créer - Un dossier du même nom existe déjà. Essayez avec un nom différent. - Titre : %s Assigné : %s - Individuel - Groupe - L\'importation est actuellement en cours. Voulez-vous continuer sans importer ? - Aucun - %d Sélectionné - Veuillez vérifier votre connexion Internet et réessayer. - …Afficher tout - + + + Permissions nécessaires + Ok + Annuler + Retour + Basse + Moyenne + Élevée + NA + Moi + M + Titre : %s Personne assignée : %s Priorité %s + Titre : %s Chemin : %s + Titre : %s + Dossier : %s + Titre : %s Type : %s + En-tête : %s + Plus + Télécharger + Ajouter aux favoris + Supprimer des favoris + Créer + Un dossier du même nom existe déjà. Essayez avec un nom différent. + Titre : %s Assigné : %s + Individuel + Groupe + L\'importation est actuellement en cours. Voulez-vous continuer sans importer ? + Aucun + %d Sélectionné + Veuillez vérifier votre connexion Internet et réessayer. + …Afficher tout + diff --git a/common/src/main/res/values-it/strings.xml b/common/src/main/res/values-it/strings.xml index e8a40f0b1..f4f4c7881 100755 --- a/common/src/main/res/values-it/strings.xml +++ b/common/src/main/res/values-it/strings.xml @@ -1,33 +1,33 @@ - - - Autorizzazioni necessarie - OK - Annulla - Indietro - Bassa - Media - Alta - N/D - Me stesso - M - Titolo: %s Assegnatario: %s Priorità %s - Titolo: %s Percorso: %s - Titolo: %s - Cartella: %s - Titolo: %s Tipo: %s - Intestazione: %s - Altro - Scarica - Aggiungi a Preferiti - Rimuovi da Preferiti - Crea - Esiste già una cartella con questo nome. Provare un nome diverso. - Titolo: %s Assegnatario: %s - Singolo - Gruppo - Il caricamento è attualmente in corso. Continuare senza eseguire il caricamento? - Nessuno - %d Selezionato - Controlla la connessione Internet e riprova. - ...Visualizza tutto - + + + Autorizzazioni necessarie + OK + Annulla + Indietro + Bassa + Media + Alta + N/D + Me stesso + M + Titolo: %s Assegnatario: %s Priorità %s + Titolo: %s Percorso: %s + Titolo: %s + Cartella: %s + Titolo: %s Tipo: %s + Intestazione: %s + Altro + Scarica + Aggiungi a Preferiti + Rimuovi da Preferiti + Crea + Esiste già una cartella con questo nome. Provare un nome diverso. + Titolo: %s Assegnatario: %s + Singolo + Gruppo + Il caricamento è attualmente in corso. Continuare senza eseguire il caricamento? + Nessuno + %d Selezionato + Controlla la connessione Internet e riprova. + ...Visualizza tutto + diff --git a/common/src/main/res/values-nl/strings.xml b/common/src/main/res/values-nl/strings.xml index 778bbebe0..b1120ac49 100755 --- a/common/src/main/res/values-nl/strings.xml +++ b/common/src/main/res/values-nl/strings.xml @@ -1,33 +1,33 @@ - - - Rechten vereist - OK - Annuleren - Terug - Laag - Gemiddeld - Hoog - N.v.t. - Ik - I - Titel: %s Toegewezen persoon: %s Prioriteit %s - Titel: %s Pad: %s - Titel: %s - Map: %s - Titel: %s Type: %s - Kop: %s - Meer - Downloaden - Favoriet toevoegen - Favoriet verwijderen - Maken - Er bestaat al een map met deze naam. Probeer een andere naam. - Titel: %s Toegewezen persoon: %s - Individueel - Groep - De upload is momenteel bezig. Wilt u doorgaan zonder uploaden? - Geen - %d Geselecteerd - Controleer uw internetverbinding en probeer het opnieuw. - ...Alle weergeven - + + + Rechten vereist + OK + Annuleren + Terug + Laag + Gemiddeld + Hoog + N.v.t. + Ik + I + Titel: %s Toegewezen persoon: %s Prioriteit %s + Titel: %s Pad: %s + Titel: %s + Map: %s + Titel: %s Type: %s + Kop: %s + Meer + Downloaden + Favoriet toevoegen + Favoriet verwijderen + Maken + Er bestaat al een map met deze naam. Probeer een andere naam. + Titel: %s Toegewezen persoon: %s + Individueel + Groep + De upload is momenteel bezig. Wilt u doorgaan zonder uploaden? + Geen + %d Geselecteerd + Controleer uw internetverbinding en probeer het opnieuw. + ...Alle weergeven + diff --git a/component/src/main/java/com/alfresco/content/component/ComponentData.kt b/component/src/main/java/com/alfresco/content/component/ComponentData.kt index 439e9174a..11e132f3b 100644 --- a/component/src/main/java/com/alfresco/content/component/ComponentData.kt +++ b/component/src/main/java/com/alfresco/content/component/ComponentData.kt @@ -2,6 +2,7 @@ package com.alfresco.content.component import android.os.Parcelable import com.alfresco.content.data.Facets +import com.alfresco.content.data.OptionsModel import com.alfresco.content.data.TaskEntry import com.alfresco.content.data.TaskFilterData import com.alfresco.content.data.payloads.FieldsData @@ -55,7 +56,23 @@ data class ComponentData( id = fieldsData.id, name = fieldsData.name, selector = ComponentType.DROPDOWN_RADIO.value, - options = fieldsData.options.filter { it.id != "empty" }.map { ComponentOptions.withProcess(it) }, + options = fieldsData.options.filter { it.id != "empty" } + .map { ComponentOptions.withProcess(it) }, + selectedName = name, + selectedQuery = query, + ) + } + + /** + * update the ComponentData obj after getting the result (name and id) from field options + * @param outcomes + * @param name + * @param query + */ + fun with(outcomes: List, name: String, query: String): ComponentData { + return ComponentData( + selector = ComponentType.PROCESS_ACTION.value, + options = outcomes.map { ComponentOptions.withProcess(it) }, selectedName = name, selectedQuery = query, ) @@ -123,7 +140,11 @@ data class ComponentData( * @param selectedName * @param selectedQueryMap */ - fun with(obj: ComponentData?, selectedName: String, selectedQueryMap: Map): ComponentData { + fun with( + obj: ComponentData?, + selectedName: String, + selectedQueryMap: Map, + ): ComponentData { return ComponentData( id = obj?.id, name = obj?.name, @@ -144,7 +165,8 @@ data class ComponentData( return ComponentData( name = "title_status", selector = ComponentType.RADIO.value, - options = taskEntry.statusOption.filter { it.id != "empty" }.map { ComponentOptions.withTaskStatus(it) }, + options = taskEntry.statusOption.filter { it.id != "empty" } + .map { ComponentOptions.withTaskStatus(it) }, selectedName = taskEntry.taskFormStatus ?: "", selectedQuery = taskEntry.taskFormStatus ?: "", ) diff --git a/component/src/main/java/com/alfresco/content/component/ComponentSheet.kt b/component/src/main/java/com/alfresco/content/component/ComponentSheet.kt index 8412a6fd5..2138a7e6f 100644 --- a/component/src/main/java/com/alfresco/content/component/ComponentSheet.kt +++ b/component/src/main/java/com/alfresco/content/component/ComponentSheet.kt @@ -38,6 +38,7 @@ class ComponentSheet : BottomSheetDialogFragment(), MavericksView { val epoxyCheckListController: AsyncEpoxyController by lazy { epoxyCheckListController() } val epoxyRadioListController: AsyncEpoxyController by lazy { epoxyRadioListController() } val epoxyCheckFacetListController: AsyncEpoxyController by lazy { epoxyCheckFacetListController() } + val epoxyActionListController: AsyncEpoxyController by lazy { epoxyActionListController() } private var executedPicker = false val minVisibleItem = 10 @@ -194,16 +195,26 @@ class ComponentSheet : BottomSheetDialogFragment(), MavericksView { private fun setupComponents() = withState(viewModel) { state -> binding.parentView.removeAllViews() - binding.parentView.addView(binding.topView) - binding.parentView.addView(binding.separator) - if (state.parent?.selector != ComponentType.DROPDOWN_RADIO.value) { - binding.bottomSeparator.visibility = View.VISIBLE - binding.bottomView.visibility = View.VISIBLE + if (state.parent?.selector != ComponentType.PROCESS_ACTION.value) { + binding.parentView.addView(binding.topView) + binding.parentView.addView(binding.separator) + } + + when { + (state.parent?.selector == ComponentType.DROPDOWN_RADIO.value) || + (state.parent?.selector == ComponentType.PROCESS_ACTION.value) -> { + } + + else -> { + binding.bottomSeparator.visibility = View.VISIBLE + binding.bottomView.visibility = View.VISIBLE + } } val replacedString = state.parent?.name?.replace(" ", ".") ?: "" val localizedName = requireContext().getLocalizedName(replacedString) + if (localizedName == replacedString) { binding.title.text = state.parent?.name ?: "" } else if (state.parent?.name?.lowercase().equals(textFileSize)) { @@ -240,6 +251,7 @@ class ComponentSheet : BottomSheetDialogFragment(), MavericksView { } ComponentType.FACETS.value -> setupFacetComponent(state, viewModel) + ComponentType.PROCESS_ACTION.value -> setupProcessActionsComponent(state, viewModel) } } @@ -249,26 +261,41 @@ class ComponentSheet : BottomSheetDialogFragment(), MavericksView { when (state.parent?.selector) { ComponentType.DATE_RANGE.value -> { if (viewModel.fromDate.isEmpty()) { - binding.dateRangeComponent.fromInputLayout.error = getString(R.string.component_number_range_empty) + binding.dateRangeComponent.fromInputLayout.error = + getString(R.string.component_number_range_empty) } else if (viewModel.toDate.isEmpty()) { - binding.dateRangeComponent.toInputLayout.error = getString(R.string.component_number_range_empty) + binding.dateRangeComponent.toInputLayout.error = + getString(R.string.component_number_range_empty) } else { - onApply?.invoke(state.parent.selectedName, state.parent.selectedQuery, state.parent.selectedQueryMap) + onApply?.invoke( + state.parent.selectedName, + state.parent.selectedQuery, + state.parent.selectedQueryMap, + ) dismiss() } } ComponentType.DATE_RANGE_FUTURE.value -> { if (viewModel.fromDate.isEmpty() && viewModel.toDate.isEmpty()) { - binding.dateRangeComponent.fromInputLayout.error = getString(R.string.component_number_range_empty) + binding.dateRangeComponent.fromInputLayout.error = + getString(R.string.component_number_range_empty) } else { - onApply?.invoke(state.parent.selectedName, state.parent.selectedQuery, state.parent.selectedQueryMap) + onApply?.invoke( + state.parent.selectedName, + state.parent.selectedQuery, + state.parent.selectedQueryMap, + ) dismiss() } } else -> { - onApply?.invoke(state.parent?.selectedName ?: "", state.parent?.selectedQuery ?: "", state.parent?.selectedQueryMap ?: mapOf()) + onApply?.invoke( + state.parent?.selectedName ?: "", + state.parent?.selectedQuery ?: "", + state.parent?.selectedQueryMap ?: mapOf(), + ) dismiss() } } @@ -301,6 +328,10 @@ class ComponentSheet : BottomSheetDialogFragment(), MavericksView { ComponentType.FACETS.value -> { epoxyCheckFacetListController.requestModelBuild() } + + ComponentType.PROCESS_ACTION.value -> { + epoxyActionListController.requestModelBuild() + } } } @@ -312,7 +343,10 @@ class ComponentSheet : BottomSheetDialogFragment(), MavericksView { data(option) optionSelected(viewModel.isOptionSelected(state, option)) clickListener { model, _, _, _ -> - viewModel.updateMultipleComponentData(model.data().label, model.data().value) + viewModel.updateMultipleComponentData( + model.data().label, + model.data().value, + ) } } } @@ -328,7 +362,11 @@ class ComponentSheet : BottomSheetDialogFragment(), MavericksView { optionSelected(viewModel.isOptionSelected(state, option)) clickListener { model, _, _, _ -> if (state.parent.selector == ComponentType.DROPDOWN_RADIO.value) { - onApply?.invoke(requireContext().getLocalizedName(model.data().label), model.data().query, mapOf()) + onApply?.invoke( + requireContext().getLocalizedName(model.data().label), + model.data().query, + mapOf(), + ) dismiss() } else { viewModel.updateSingleComponentData( @@ -369,6 +407,24 @@ class ComponentSheet : BottomSheetDialogFragment(), MavericksView { } } + private fun epoxyActionListController() = simpleController(viewModel) { state -> + + if (state.parent?.options?.isNotEmpty() == true) { + state.parent.options.forEach { bucket -> + listViewActionsRow { + id(bucket.hashCode()) + data(bucket) + clickListener { model, _, _, _ -> +// viewModel.updateMultipleComponentData( +// requireContext().getLocalizedName(model.data().label), +// model.data().query, +// ) + } + } + } + } + } + private fun showCalendar(isFrom: Boolean, isFutureDate: Boolean) { viewLifecycleOwner.lifecycleScope.launch { val result = suspendCoroutine { diff --git a/component/src/main/java/com/alfresco/content/component/ComponentSheetExtension.kt b/component/src/main/java/com/alfresco/content/component/ComponentSheetExtension.kt index 118b24ab6..4d625a060 100644 --- a/component/src/main/java/com/alfresco/content/component/ComponentSheetExtension.kt +++ b/component/src/main/java/com/alfresco/content/component/ComponentSheetExtension.kt @@ -183,6 +183,21 @@ fun ComponentSheet.setupFacetComponent(state: ComponentState, viewModel: Compone binding.facetCheckListComponent.searchInputLayout.editText?.addTextChangedListener(searchInputTextWatcher) } +/** + * setup the Process Actions Component + * @param state + * @param viewModel + */ +@SuppressLint("ClickableViewAccessibility") +fun ComponentSheet.setupProcessActionsComponent(state: ComponentState, viewModel: ComponentViewModel) { + viewModel.buildCheckListModel() + binding.parentView.addView(binding.frameActions) + + binding.processActions.componentParent.visibility = View.VISIBLE + + binding.processActions.recyclerView.setController(epoxyActionListController) +} + /** * setup the Title Description Component * @param state diff --git a/component/src/main/java/com/alfresco/content/component/ComponentType.kt b/component/src/main/java/com/alfresco/content/component/ComponentType.kt index 8c31ea5ac..dcceec73c 100644 --- a/component/src/main/java/com/alfresco/content/component/ComponentType.kt +++ b/component/src/main/java/com/alfresco/content/component/ComponentType.kt @@ -16,5 +16,6 @@ enum class ComponentType(val value: String) { DROPDOWN_RADIO("dropdown_radio"), FACETS("facets"), TASK_PROCESS_PRIORITY("task-process-priority"), + PROCESS_ACTION("process-actions"), None("none"), } diff --git a/component/src/main/java/com/alfresco/content/component/ListViewActionsRow.kt b/component/src/main/java/com/alfresco/content/component/ListViewActionsRow.kt new file mode 100644 index 000000000..095afd035 --- /dev/null +++ b/component/src/main/java/com/alfresco/content/component/ListViewActionsRow.kt @@ -0,0 +1,36 @@ +package com.alfresco.content.component + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.FrameLayout +import com.airbnb.epoxy.CallbackProp +import com.airbnb.epoxy.ModelProp +import com.airbnb.epoxy.ModelView +import com.alfresco.content.component.databinding.ViewActionsListRowBinding +import com.alfresco.content.getLocalizedName + +@ModelView(autoLayout = ModelView.Size.MATCH_WIDTH_WRAP_HEIGHT) +internal class ListViewActionsRow @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : FrameLayout(context, attrs, defStyleAttr) { + private val binding = + ViewActionsListRowBinding.inflate(LayoutInflater.from(context), this, true) + + @ModelProp + fun setData(options: ComponentOptions) { + binding.actionButton.text = context.getLocalizedName(options.label ?: "") + } + + @ModelProp + fun setOptionSelected(isSelected: Boolean) { +// binding.checkBox.isChecked = isSelected + } + + @CallbackProp + fun setClickListener(listener: OnClickListener?) { +// binding.parentListRow.setOnClickListener(listener) + } +} diff --git a/component/src/main/res/layout/sheet_component_filter.xml b/component/src/main/res/layout/sheet_component_filter.xml index 0e36e3da5..6896575f7 100644 --- a/component/src/main/res/layout/sheet_component_filter.xml +++ b/component/src/main/res/layout/sheet_component_filter.xml @@ -152,6 +152,17 @@ layout="@layout/view_task_priority_component" /> + + + + + diff --git a/component/src/main/res/layout/view_actions_component.xml b/component/src/main/res/layout/view_actions_component.xml new file mode 100644 index 000000000..a6c1f1740 --- /dev/null +++ b/component/src/main/res/layout/view_actions_component.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/component/src/main/res/layout/view_actions_list_row.xml b/component/src/main/res/layout/view_actions_list_row.xml new file mode 100644 index 000000000..7a36fe391 --- /dev/null +++ b/component/src/main/res/layout/view_actions_list_row.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/component/src/main/res/values-de/strings.xml b/component/src/main/res/values-de/strings.xml index cb037f221..b01a7cca9 100644 --- a/component/src/main/res/values-de/strings.xml +++ b/component/src/main/res/values-de/strings.xml @@ -1,33 +1,33 @@ - - -2 - Suchen - Erweiterte Suche - Von - Bis - Startdatum - Enddatum - Der \„Von\“ Wert muss kleiner als der \„Bis\“ Wert sein - Zurücksetzen - Anwenden - Abbrechen - Erforderlicher Wert - %1$s (KB) - %1$s-%2$s-%3$s - %1$s (%2$d) - %1$s-%2$s-%3$s - Fälligkeitsdatum - Status - Aufgabenname - Aktiv - Abgeschlossen - Fällig vor - Fällig nach - Nach Name - Nach E-Mail - Schaltfläche \„Zurück\“ - Alle - Benutzer suchen - Gruppe durchsuchen - In Warteschlange - + + +2 + Suchen + Erweiterte Suche + Von + Bis + Startdatum + Enddatum + Der \„Von\“ Wert muss kleiner als der \„Bis\“ Wert sein + Zurücksetzen + Anwenden + Abbrechen + Erforderlicher Wert + %1$s (KB) + %1$s-%2$s-%3$s + %1$s (%2$d) + %1$s-%2$s-%3$s + Fälligkeitsdatum + Status + Aufgabenname + Aktiv + Abgeschlossen + Fällig vor + Fällig nach + Nach Name + Nach E-Mail + Schaltfläche \„Zurück\“ + Alle + Benutzer suchen + Gruppe durchsuchen + In Warteschlange + diff --git a/component/src/main/res/values-es/strings.xml b/component/src/main/res/values-es/strings.xml index 8818c5c1f..ba9f08536 100644 --- a/component/src/main/res/values-es/strings.xml +++ b/component/src/main/res/values-es/strings.xml @@ -1,33 +1,33 @@ - - -2 - Buscar - Búsqueda avanzada - De - A - Desde la fecha - Hasta la fecha - El valor \'De\' debe ser menor que el valor \'A\' - Reiniciar - Aplicar - Cancelar - Valor requerido - %1$s (KB) - %1$s-%2$s-%3$s - %1$s (%2$d) - %1$s-%2$s-%3$s - Fecha de vencimiento - Estado - Nombre de la tarea - Activo - Completada - Vencimiento antes de - Vencimiento después de - Por nombre - Por correo electrónico - Botón Atrás - Todos - Buscar usuario - Buscar grupo - En cola - + + +2 + Buscar + Búsqueda avanzada + De + A + Desde la fecha + Hasta la fecha + El valor \'De\' debe ser menor que el valor \'A\' + Reiniciar + Aplicar + Cancelar + Valor requerido + %1$s (KB) + %1$s-%2$s-%3$s + %1$s (%2$d) + %1$s-%2$s-%3$s + Fecha de vencimiento + Estado + Nombre de la tarea + Activo + Completada + Vencimiento antes de + Vencimiento después de + Por nombre + Por correo electrónico + Botón Atrás + Todos + Buscar usuario + Buscar grupo + En cola + diff --git a/component/src/main/res/values-fr/strings.xml b/component/src/main/res/values-fr/strings.xml index 4ef900fee..2c08edd62 100644 --- a/component/src/main/res/values-fr/strings.xml +++ b/component/src/main/res/values-fr/strings.xml @@ -1,33 +1,33 @@ - - -2 - Rechercher - Recherche avancée - De - A - Date de début - Date de fin - La valeur \'De\' doit être inférieure à la valeur \'A\' - Réinitialiser - Appliquer - Annuler - Valeur requise - %1$s (KB) - %1$s-%2$s-%3$s - %1$s (%2$d) - %1$s-%2$s-%3$s - Date d\'échéance - Statut - Nom de la tâche - Actif - Terminé - Dû avant - Dû après - Par nom - Par e-mail - Bouton Retour - Tout - Rechercher des utilisateurs - Groupe de recherche - En file d\'attente - + + +2 + Rechercher + Recherche avancée + De + A + Date de début + Date de fin + La valeur \'De\' doit être inférieure à la valeur \'A\' + Réinitialiser + Appliquer + Annuler + Valeur requise + %1$s (KB) + %1$s-%2$s-%3$s + %1$s (%2$d) + %1$s-%2$s-%3$s + Date d\'échéance + Statut + Nom de la tâche + Actif + Terminé + Dû avant + Dû après + Par nom + Par e-mail + Bouton Retour + Tout + Rechercher des utilisateurs + Groupe de recherche + En file d\'attente + diff --git a/component/src/main/res/values-it/strings.xml b/component/src/main/res/values-it/strings.xml index 9fbad91f6..9a60c2f36 100644 --- a/component/src/main/res/values-it/strings.xml +++ b/component/src/main/res/values-it/strings.xml @@ -1,33 +1,33 @@ - - -2 - Ricerca - Ricerca avanzata - Da - A - Data di inizio - Data di fine - Il valore \'Da\' deve essere inferiore al valore \'A\' - Reimposta - Applica - Annulla - Valore obbligatorio - %1$s (KB) - %1$s-%2$s-%3$s - %1$s (%2$d) - %1$s-%2$s-%3$s - Scadenza - Stato - Nome compito - Attivo - Completato - Scadenza antecedente a - Scadenza successiva a - Per nome - Per e-mail - Pulsante Indietro - Tutti - Cerca utente - Cerca gruppo - In coda - + + +2 + Ricerca + Ricerca avanzata + Da + A + Data di inizio + Data di fine + Il valore \'Da\' deve essere inferiore al valore \'A\' + Reimposta + Applica + Annulla + Valore obbligatorio + %1$s (KB) + %1$s-%2$s-%3$s + %1$s (%2$d) + %1$s-%2$s-%3$s + Scadenza + Stato + Nome compito + Attivo + Completato + Scadenza antecedente a + Scadenza successiva a + Per nome + Per e-mail + Pulsante Indietro + Tutti + Cerca utente + Cerca gruppo + In coda + diff --git a/component/src/main/res/values-nl/strings.xml b/component/src/main/res/values-nl/strings.xml index d66d95824..18c62e8e3 100644 --- a/component/src/main/res/values-nl/strings.xml +++ b/component/src/main/res/values-nl/strings.xml @@ -1,33 +1,33 @@ - - -2 - Zoeken - Geavanceerd zoeken - Van - Tot - Begindatum - Einddatum - Van-waarde moet kleiner zijn dan Tot-waarde - Opnieuw instellen - Toepassen - Annuleren - Vereiste waarde - %1$s (KB) - %1$s-%2$s-%3$s - %1$s (%2$d) - %1$s-%2$s-%3$s - Vervaldatum - Status - Taaknaam - Actief - Voltooid - Vervallen Voor - Vervallen Na - Op naam - Op e-mail - Knop Terug - Alle - Gebruiker zoeken - Groep zoeken - In wachtrij - + + +2 + Zoeken + Geavanceerd zoeken + Van + Tot + Begindatum + Einddatum + Van-waarde moet kleiner zijn dan Tot-waarde + Opnieuw instellen + Toepassen + Annuleren + Vereiste waarde + %1$s (KB) + %1$s-%2$s-%3$s + %1$s (%2$d) + %1$s-%2$s-%3$s + Vervaldatum + Status + Taaknaam + Actief + Voltooid + Vervallen Voor + Vervallen Na + Op naam + Op e-mail + Knop Terug + Alle + Gebruiker zoeken + Groep zoeken + In wachtrij + diff --git a/process-app/build.gradle b/process-app/build.gradle index 5330cba46..e376b6bf8 100644 --- a/process-app/build.gradle +++ b/process-app/build.gradle @@ -49,6 +49,7 @@ dependencies { implementation project(':actions') implementation project(':data') implementation project(':component') + implementation project(':viewer') implementation libs.androidx.core implementation libs.androidx.appcompat diff --git a/process-app/src/main/kotlin/com/alfresco/content/process/FormViewModel.kt b/process-app/src/main/kotlin/com/alfresco/content/process/FormViewModel.kt index e9129131d..7a43c8294 100644 --- a/process-app/src/main/kotlin/com/alfresco/content/process/FormViewModel.kt +++ b/process-app/src/main/kotlin/com/alfresco/content/process/FormViewModel.kt @@ -10,6 +10,7 @@ import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.ViewModelContext +import com.alfresco.content.data.OptionsModel import com.alfresco.content.data.ProcessEntry import com.alfresco.content.data.ResponseListForm import com.alfresco.content.data.ResponseListProcessDefinition @@ -23,6 +24,7 @@ data class FormViewState( val requestStartForm: Async = Uninitialized, val requestProcessDefinition: Async = Uninitialized, val formFields: List = emptyList(), + val processOutcomes: List = emptyList(), ) : MavericksState { constructor(target: ProcessEntry) : this(parent = target) @@ -80,7 +82,11 @@ class FormViewModel( } is Success -> { - copy(formFields = it().fields.flatMap { listData -> listData.fields }, requestStartForm = Success(it())) + copy( + formFields = it().fields.flatMap { listData -> listData.fields }, + processOutcomes = it().outcomes, + requestStartForm = Success(it()), + ) } else -> { diff --git a/process-app/src/main/kotlin/com/alfresco/content/process/ui/FormDetailScreen.kt b/process-app/src/main/kotlin/com/alfresco/content/process/ui/FormDetailScreen.kt index 0abb0c5ab..89c29761f 100644 --- a/process-app/src/main/kotlin/com/alfresco/content/process/ui/FormDetailScreen.kt +++ b/process-app/src/main/kotlin/com/alfresco/content/process/ui/FormDetailScreen.kt @@ -4,42 +4,30 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import com.alfresco.content.data.ProcessEntry +import com.alfresco.content.data.OptionsModel import com.alfresco.content.data.TaskRepository -import com.alfresco.content.data.UserGroupDetails -import com.alfresco.content.data.payloads.FieldType import com.alfresco.content.process.FormViewModel import com.alfresco.content.process.FormViewState -import com.alfresco.content.process.R -import com.alfresco.content.process.ui.components.AmountInputField -import com.alfresco.content.process.ui.components.CheckBoxField -import com.alfresco.content.process.ui.components.DateTimeField -import com.alfresco.content.process.ui.components.DropdownField -import com.alfresco.content.process.ui.components.HyperLinkField -import com.alfresco.content.process.ui.components.IntegerInputField -import com.alfresco.content.process.ui.components.MultiLineInputField -import com.alfresco.content.process.ui.components.PeopleField -import com.alfresco.content.process.ui.components.ReadOnlyField -import com.alfresco.content.process.ui.components.SingleLineInputField +import com.alfresco.content.process.ui.components.FormScrollContent +import com.alfresco.content.process.ui.components.Outcomes @OptIn(ExperimentalComposeUiApi::class) @Composable -fun FormDetailScreen(state: FormViewState, viewModel: FormViewModel) { +fun FormDetailScreen(state: FormViewState, viewModel: FormViewModel, outcomes: List) { val keyboardController = LocalSoftwareKeyboardController.current val focusManager = LocalFocusManager.current @@ -48,136 +36,32 @@ fun FormDetailScreen(state: FormViewState, viewModel: FormViewModel) { } Column( - modifier = Modifier - .fillMaxSize() - .clickable { - // Hide the keyboard on click outside of input fields - keyboardController?.hide() - focusManager.clearFocus() - }, - verticalArrangement = Arrangement.Top, - horizontalAlignment = Alignment.CenterHorizontally, - + modifier = Modifier.fillMaxWidth(), ) { LazyColumn( modifier = Modifier - .fillMaxSize(), + .fillMaxSize() + .weight(1f, false) + .clickable { + // Hide the keyboard on click outside of input fields + keyboardController?.hide() + focusManager.clearFocus() + }, + verticalArrangement = Arrangement.Top, + horizontalAlignment = Alignment.CenterHorizontally, ) { items(items = formList) { field -> - when (field.type) { - FieldType.TEXT.value() -> { - var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } - SingleLineInputField( - textFieldValue = textFieldValue, - onValueChanged = { newText -> - textFieldValue = newText - viewModel.updateFieldValue(field.id, newText, state) - }, - field, - ) - } - - FieldType.MULTI_LINE_TEXT.value() -> { - var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } - MultiLineInputField( - textFieldValue = textFieldValue, - onValueChanged = { newText -> - textFieldValue = newText - viewModel.updateFieldValue(field.id, newText, state) - }, - field, - ) - } - - FieldType.INTEGER.value() -> { - var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } - IntegerInputField( - textFieldValue = textFieldValue, - onValueChanged = { newText -> - textFieldValue = newText - viewModel.updateFieldValue(field.id, newText, state) - }, - field, - ) - } - - FieldType.AMOUNT.value() -> { - var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } - AmountInputField( - textFieldValue = textFieldValue, - onValueChanged = { newText -> - textFieldValue = newText - viewModel.updateFieldValue(field.id, newText, state) - }, - field, - ) - } - - FieldType.BOOLEAN.value() -> { - var checkedValue by remember { mutableStateOf(field.value as? Boolean ?: false) } - CheckBoxField( - title = stringResource(id = R.string.title_workflow), - checkedValue = checkedValue, - onCheckChanged = { newChecked -> - checkedValue = newChecked - viewModel.updateFieldValue(field.id, newChecked, state) - }, - field, - ) - } - - FieldType.DATETIME.value(), FieldType.DATE.value() -> { - var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } - DateTimeField( - dateTimeValue = textFieldValue, - onValueChanged = { newText -> - textFieldValue = newText - viewModel.updateFieldValue(field.id, newText, state) - }, - field, - ) - } - - FieldType.DROPDOWN.value(), FieldType.RADIO_BUTTONS.value() -> { - var textFieldValue by remember { mutableStateOf(field.placeHolder ?: "") } - var textFieldQuery by remember { mutableStateOf("") } - DropdownField( - nameText = textFieldValue, - queryText = textFieldQuery, - onValueChanged = { (newText, newQuery) -> - textFieldValue = newText - textFieldQuery = newQuery - viewModel.updateFieldValue(field.id, newText, state) - }, - fieldsData = field, - ) - } - - FieldType.READONLY_TEXT.value(), FieldType.READONLY.value() -> { - val textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } - ReadOnlyField( - textFieldValue = textFieldValue, - fieldsData = field, - ) - } - - FieldType.PEOPLE.value(), FieldType.FUNCTIONAL_GROUP.value() -> { - var userDetailValue by remember { mutableStateOf(field.value as? UserGroupDetails) } - PeopleField( - userDetail = userDetailValue, - onAssigneeSelected = { userDetails -> - userDetailValue = userDetails - viewModel.updateFieldValue(field.id, userDetails, state) - }, - fieldsData = field, - processEntry = ProcessEntry.withProcess(state.parent, field.type), - ) - } + FormScrollContent(field, viewModel, state) + } + } - FieldType.HYPERLINK.value() -> { - HyperLinkField(field) - } - } + if (outcomes.isNotEmpty()) { + Column( + modifier = Modifier + .fillMaxWidth() + .align(alignment = Alignment.CenterHorizontally), + ) { + Outcomes(outcomes = outcomes) } } } @@ -187,5 +71,13 @@ fun FormDetailScreen(state: FormViewState, viewModel: FormViewModel) { @Composable fun PreviewProcessDetailScreen() { val state = FormViewState() - FormDetailScreen(state, FormViewModel(state, LocalContext.current, TaskRepository())) + FormDetailScreen( + state, + FormViewModel( + state, + LocalContext.current, + TaskRepository(), + ), + emptyList(), + ) } diff --git a/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FloatingActionButton.kt b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FloatingActionButton.kt index 096fa15cd..c47dd5583 100644 --- a/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FloatingActionButton.kt +++ b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FloatingActionButton.kt @@ -9,17 +9,34 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import com.alfresco.content.component.ComponentBuilder +import com.alfresco.content.component.ComponentData +import com.alfresco.content.data.OptionsModel @Composable -fun FloatingActionButton() { +fun FloatingActionButton(outcomes: List) { + val context = LocalContext.current + ExtendedFloatingActionButton( onClick = { - + val componentData = ComponentData.with( + outcomes, + "", + "", + ) + ComponentBuilder(context, componentData) + .onApply { name, query, _ -> + } + .onReset { name, query, _ -> + } + .onCancel { + } + .show() }, containerColor = MaterialTheme.colorScheme.primary, icon = { Icon(Icons.Filled.PlaylistAdd, "Extended floating action button.") }, text = { Text(text = "Actions") }, - modifier = Modifier.navigationBarsPadding() + modifier = Modifier.navigationBarsPadding(), ) - -} \ No newline at end of file +} diff --git a/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FormScreen.kt b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FormScreen.kt index 734175652..e02fb9672 100644 --- a/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FormScreen.kt +++ b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FormScreen.kt @@ -9,11 +9,11 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier import androidx.navigation.NavController import com.airbnb.mvrx.Loading import com.airbnb.mvrx.compose.collectAsState import com.airbnb.mvrx.compose.mavericksActivityViewModel +import com.alfresco.content.data.OptionsModel import com.alfresco.content.process.FormViewModel import com.alfresco.content.process.ui.FormDetailScreen @@ -22,16 +22,41 @@ fun FormScreen(navController: NavController) { // This will get or create a ViewModel scoped to the Activity. val viewModel: FormViewModel = mavericksActivityViewModel() val state by viewModel.collectAsState() - val has2Coutcomes = state.formFields - - Scaffold( - topBar = { ComposeTopBar() }, - content = { padding -> + val customOutcomes = state.processOutcomes.ifEmpty { + listOf( + OptionsModel(name = "Start workflow"), + ) + } + if (customOutcomes.size < 3) { + Scaffold( + topBar = { ComposeTopBar() }, + ) { padding -> + val colorScheme = MaterialTheme.colorScheme + // Wrap the content in a Column with verticalScroll + Surface( + modifier = androidx.compose.ui.Modifier + .padding(padding) + .statusBarsPadding(), + color = colorScheme.background, + contentColor = colorScheme.onBackground, + ) { + if (state.requestStartForm is Loading) { + CustomLinearProgressIndicator(padding) + } + FormDetailScreen(state, viewModel, customOutcomes) + } + } + } else { + Scaffold( + topBar = { ComposeTopBar() }, + floatingActionButton = { FloatingActionButton(customOutcomes) }, + floatingActionButtonPosition = FabPosition.End, + ) { padding -> val colorScheme = MaterialTheme.colorScheme // Wrap the content in a Column with verticalScroll Surface( - modifier = Modifier + modifier = androidx.compose.ui.Modifier .padding(padding) .statusBarsPadding(), color = colorScheme.background, @@ -40,10 +65,8 @@ fun FormScreen(navController: NavController) { if (state.requestStartForm is Loading) { CustomLinearProgressIndicator(padding) } - FormDetailScreen(state, viewModel) + FormDetailScreen(state, viewModel, customOutcomes) } - }, - floatingActionButton = { FloatingActionButton() }, - floatingActionButtonPosition = FabPosition.End - ) + } + } } diff --git a/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FormScrollContent.kt b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FormScrollContent.kt new file mode 100644 index 000000000..e8bb74690 --- /dev/null +++ b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/FormScrollContent.kt @@ -0,0 +1,135 @@ +package com.alfresco.content.process.ui.components + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.res.stringResource +import com.alfresco.content.data.ProcessEntry +import com.alfresco.content.data.UserGroupDetails +import com.alfresco.content.data.payloads.FieldType +import com.alfresco.content.data.payloads.FieldsData +import com.alfresco.content.process.FormViewModel +import com.alfresco.content.process.FormViewState +import com.alfresco.content.process.R + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun FormScrollContent(field: FieldsData, viewModel: FormViewModel, state: FormViewState) { + when (field.type) { + FieldType.TEXT.value() -> { + var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } + SingleLineInputField( + textFieldValue = textFieldValue, + onValueChanged = { newText -> + textFieldValue = newText + viewModel.updateFieldValue(field.id, newText, state) + }, + field, + ) + } + + FieldType.MULTI_LINE_TEXT.value() -> { + var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } + MultiLineInputField( + textFieldValue = textFieldValue, + onValueChanged = { newText -> + textFieldValue = newText + viewModel.updateFieldValue(field.id, newText, state) + }, + field, + ) + } + + FieldType.INTEGER.value() -> { + var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } + IntegerInputField( + textFieldValue = textFieldValue, + onValueChanged = { newText -> + textFieldValue = newText + viewModel.updateFieldValue(field.id, newText, state) + }, + field, + ) + } + + FieldType.AMOUNT.value() -> { + var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } + AmountInputField( + textFieldValue = textFieldValue, + onValueChanged = { newText -> + textFieldValue = newText + viewModel.updateFieldValue(field.id, newText, state) + }, + field, + ) + } + + FieldType.BOOLEAN.value() -> { + var checkedValue by remember { mutableStateOf(field.value as? Boolean ?: false) } + CheckBoxField( + title = stringResource(id = R.string.title_workflow), + checkedValue = checkedValue, + onCheckChanged = { newChecked -> + checkedValue = newChecked + viewModel.updateFieldValue(field.id, newChecked, state) + }, + field, + ) + } + + FieldType.DATETIME.value(), FieldType.DATE.value() -> { + var textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } + DateTimeField( + dateTimeValue = textFieldValue, + onValueChanged = { newText -> + textFieldValue = newText + viewModel.updateFieldValue(field.id, newText, state) + }, + field, + ) + } + + FieldType.DROPDOWN.value(), FieldType.RADIO_BUTTONS.value() -> { + var textFieldValue by remember { mutableStateOf(field.placeHolder ?: "") } + var textFieldQuery by remember { mutableStateOf("") } + DropdownField( + nameText = textFieldValue, + queryText = textFieldQuery, + onValueChanged = { (newText, newQuery) -> + textFieldValue = newText + textFieldQuery = newQuery + viewModel.updateFieldValue(field.id, newText, state) + }, + fieldsData = field, + ) + } + + FieldType.READONLY_TEXT.value(), FieldType.READONLY.value() -> { + val textFieldValue by remember { mutableStateOf(field.value as? String ?: "") } + ReadOnlyField( + textFieldValue = textFieldValue, + fieldsData = field, + ) + } + + FieldType.PEOPLE.value(), FieldType.FUNCTIONAL_GROUP.value() -> { + var userDetailValue by remember { mutableStateOf(field.value as? UserGroupDetails) } + PeopleField( + userDetail = userDetailValue, + onAssigneeSelected = { userDetails -> + userDetailValue = userDetails + viewModel.updateFieldValue(field.id, userDetails, state) + }, + fieldsData = field, + processEntry = ProcessEntry.withProcess(state.parent, field.type), + ) + } + + FieldType.HYPERLINK.value() -> { + HyperLinkField(field) + } + } +} diff --git a/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/HyperLinkField.kt b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/HyperLinkField.kt index bca9be2e4..3fd27fed4 100644 --- a/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/HyperLinkField.kt +++ b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/HyperLinkField.kt @@ -1,31 +1,42 @@ package com.alfresco.content.process.ui.components +import android.content.Intent +import android.provider.MediaStore.Audio.AudioColumns.TITLE_KEY import androidx.compose.foundation.clickable import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Link import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.Preview +import androidx.core.content.ContextCompat.startActivity +import com.alfresco.content.common.SharedURLParser +import com.alfresco.content.common.SharedURLParser.Companion.ID_KEY +import com.alfresco.content.common.SharedURLParser.Companion.MODE_KEY import com.alfresco.content.data.payloads.FieldsData import com.alfresco.content.process.R +import com.alfresco.content.viewer.ViewerActivity @Composable fun HyperLinkField( fieldsData: FieldsData = FieldsData(), ) { val uriHandler = LocalUriHandler.current + val context = LocalContext.current val keyboardOptions = KeyboardOptions.Default.copy( imeAction = ImeAction.Next, keyboardType = KeyboardType.Text, ) - val leadingIcon: @Composable () -> Unit = { Icon( imageVector = Icons.Default.Link, @@ -34,13 +45,33 @@ fun HyperLinkField( ) } - InputFieldWithLeading( modifier = Modifier .inputField() .clickable { - uriHandler.openUri(fieldsData.hyperlinkUrl ?: "") + val urlData = + SharedURLParser().getEntryIdFromShareURL(fieldsData.hyperlinkUrl ?: "", true) + + if (urlData.second.isNotEmpty()) { + context.startActivity( + Intent(context, ViewerActivity::class.java) + .putExtra(ID_KEY, urlData.second) + .putExtra( + MODE_KEY, + if (urlData.first) SharedURLParser.VALUE_SHARE else SharedURLParser.VALUE_REMOTE, + ) + .putExtra(TITLE_KEY, "Preview"), + ) + } else { + uriHandler.openUri(fieldsData.hyperlinkUrl ?: "") + } }, + colors = OutlinedTextFieldDefaults.colors( + disabledLabelColor = MaterialTheme.colorScheme.onSurface, + disabledBorderColor = MaterialTheme.colorScheme.onSurface, + disabledTextColor = MaterialTheme.colorScheme.onSurface, + disabledPlaceholderColor = MaterialTheme.colorScheme.onSurface, + ), maxLines = 1, textFieldValue = fieldsData.displayText, fieldsData = fieldsData, @@ -48,5 +79,10 @@ fun HyperLinkField( leadingIcon = leadingIcon, isEnabled = false, ) +} +@Preview +@Composable +fun HyperLinkFieldPreview() { + HyperLinkField() } diff --git a/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/Outcomes.kt b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/Outcomes.kt new file mode 100644 index 000000000..8beedd321 --- /dev/null +++ b/process-app/src/main/kotlin/com/alfresco/content/process/ui/components/Outcomes.kt @@ -0,0 +1,26 @@ +package com.alfresco.content.process.ui.components + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.alfresco.content.data.OptionsModel + +@Composable +fun Outcomes(outcomes: List) { + outcomes.forEach { + Button( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 4.dp), + onClick = { }, + shape = RoundedCornerShape(4.dp), + ) { + Text(it.name) + } + } +} diff --git a/search/src/main/res/values-es/strings.xml b/search/src/main/res/values-es/strings.xml index 6080b54af..d8465985a 100755 --- a/search/src/main/res/values-es/strings.xml +++ b/search/src/main/res/values-es/strings.xml @@ -1,69 +1,69 @@ - - - - Buscar - - Búsquedas recientes - - Buscando\u2026 - - en: %s - Ficheros - Carpetas - Bibliotecas - - ¡Vaya! - No encontramos el fichero\nque busca. - - Predeterminado - Ninguno - Todos - Carpeta - Documento - %1$s-%2$s-%3$s - %1$s... - %1$s (%2$d) - %1$s (%2$s) - - Tamaño de fichero - Fecha de creación - Tipo de fichero - Modificador - Creador - %1$s ... %2$s - %1$s + %2$d - - - Consultas con filtros por tamaño - Mediano - Grande - Pequeño - Extra pequeño - Extra grande - Supergrande - Anterior - Último año - Año actual - Este año - Tipo MIME - Año de creación - Año de modificación - Tamaño - Fecha de creación - Creador - Modificador - Mis consultas por filtros - - - Fecha de creación (rango) - Tamaño de contenido - Tipo - Nombre del fichero - Introduzca el nombre - Predeterminado - Carpeta - Consultas con filtros por tipo - no puede mover a su propia carpeta y subcarpetas. - Reiniciar - Sin conexión - + + + + Buscar + + Búsquedas recientes + + Buscando\u2026 + + en: %s + Ficheros + Carpetas + Bibliotecas + + ¡Vaya! + No encontramos el fichero\nque busca. + + Predeterminado + Ninguno + Todos + Carpeta + Documento + %1$s-%2$s-%3$s + %1$s... + %1$s (%2$d) + %1$s (%2$s) + + Tamaño de fichero + Fecha de creación + Tipo de fichero + Modificador + Creador + %1$s ... %2$s + %1$s + %2$d + + + Consultas con filtros por tamaño + Mediano + Grande + Pequeño + Extra pequeño + Extra grande + Supergrande + Anterior + Último año + Año actual + Este año + Tipo MIME + Año de creación + Año de modificación + Tamaño + Fecha de creación + Creador + Modificador + Mis consultas por filtros + + + Fecha de creación (rango) + Tamaño de contenido + Tipo + Nombre del fichero + Introduzca el nombre + Predeterminado + Carpeta + Consultas con filtros por tipo + no puede mover a su propia carpeta y subcarpetas. + Reiniciar + Sin conexión +