Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
Entrambe le parti precedenti la revisione Revisione precedente Prossima revisione | Revisione precedente | ||
gwusermanual:interface:widget [2025/02/06 11:02] giorgio.scali [LABEL_VALUE_JSON_WIDGET] |
gwusermanual:interface:widget [2025/04/07 10:52] (versione attuale) giorgio.scali [LABEL_VALUE_JSON_WIDGET] |
||
---|---|---|---|
Linea 593: | Linea 593: | ||
^ Parametro ^ Descrizione ^ | ^ Parametro ^ Descrizione ^ | ||
| textHtml| String. Codice html che verrà formattato e visualizzato | | | textHtml| String. Codice html che verrà formattato e visualizzato | | ||
- | | behaviorType | Integer. Se impostato a 0 permette di valutare il valore gli attributi della classe con la notazione ${nome_attributo} | | + | | behaviorType | Integer. Default 1. Possibili valori [1,0]. Di norma vengono sostituite dinamicamente tutte le espressioni del tipo //${field_name}// e del tipo //${session_var_name}// in base al contesto. Per la lista vengono passati i valori dei soli widget aggiunti in lista. Analogamente per il dettaglio di classe. Se behaviorType è impostato a 0 vengono valutati i valori di tutti gli attributi anche quelli non presenti nella lista o nel dettaglio. Questo comporta una query sul dettaglio aggiuntiva, che può causare dei rallentamenti. **Nota: behaviorType a 0 è tassativamente da evitare se il widget va in lista.** Come best practise vanno nel caso messi tutti i field di riferimento in lista, al limite nascondendoli agendo nell'**xml del widget**, cosi: **<listCellStyleRules>display:none;</listCellStyleRules><listCellHeaderStyleRules>display:none;</listCellHeaderStyleRules>**. Sul dettaglio di classe, invece, si può valutare l'utilizzo di behaviorType a 0 nel caso in cui nell'htmlTemplate si richiamino molti attributi attualmente non presenti nel dettaglio, e non si voglia aggiungerli manualmente per poi nasconderli| |
---- | ---- | ||
Linea 950: | Linea 950: | ||
Rappresenta il corrispettivo del labelValuesXmlWidget, che invece lavora con tipo di dato testuale in formato xml. | Rappresenta il corrispettivo del labelValuesXmlWidget, che invece lavora con tipo di dato testuale in formato xml. | ||
Caratteristiche: | Caratteristiche: | ||
- | * In particolare vengono presentate le coppie chiave valore esclusivamente del primo livello. | + | * In particolare vengono presentate le coppie chiave valore esclusivamente del primo livello. |
+ | * Eventuali valori con JSON annidati vengono trasformati in String JSON e visualizzati come tali | ||
* Le coppie chiave valore sono rese tramite una elenco di coppie label-widget. | * Le coppie chiave valore sono rese tramite una elenco di coppie label-widget. | ||
* Le coppie label-widget possono essere raggruppati in sezioni. | * Le coppie label-widget possono essere raggruppati in sezioni. | ||
- | * Se dall'elaborazione dei dati dovesse risultare un solo raggruppamento, la relativa intestazione non verrà visualizzata | + | * Se dall'elaborazione dei dati dovesse risultare un solo raggruppamento (configurato o automatico), la relativa intestazione non verrà visualizzata |
* I widget senza raggruppamento, vengono raccolti in un gruppo creato automaticamente //'Altri'// (localizzato) | * I widget senza raggruppamento, vengono raccolti in un gruppo creato automaticamente //'Altri'// (localizzato) | ||
* Di base i widget vengono resi mediante un semplice campo di testo in sola lettura. | * Di base i widget vengono resi mediante un semplice campo di testo in sola lettura. | ||
Linea 975: | Linea 976: | ||
<code json> | <code json> | ||
{ | { | ||
- | "label 1": "valore 1", | + | "Label 1": "uno", |
- | "label 2": 2, | + | "Label 2": 2, |
- | "label 3": true | + | "Label 3": true |
} | } | ||
</code> | </code> | ||
- | A sinistra il JSON di origine in un widget codeEditor, e a destra la relativa rappresentazione LabelValueJsonWidget. | + | A sinistra il JSON di origine in un widget //codeEditor//, e a destra la relativa rappresentazione //labelValueJsonWidget//. |
{{:gwusermanual:interface:labelvaluejsonwidget_simple.jpg?600|}} | {{:gwusermanual:interface:labelvaluejsonwidget_simple.jpg?600|}} | ||
Linea 991: | Linea 992: | ||
* **order** integer, usato per l'ordinamento (gli elementi senza ordine hanno precedenza, in base all'ordine di comparsa nel JSON) | * **order** integer, usato per l'ordinamento (gli elementi senza ordine hanno precedenza, in base all'ordine di comparsa nel JSON) | ||
* **parameters**, contiene i metadati relativi alle singole coppie chiave valore, organizzate per chiave. **Ogni key è in rapporto 1:1 con le key di primo livello del JSON**, e nel relativo oggetto //value// sono presenti: | * **parameters**, contiene i metadati relativi alle singole coppie chiave valore, organizzate per chiave. **Ogni key è in rapporto 1:1 con le key di primo livello del JSON**, e nel relativo oggetto //value// sono presenti: | ||
- | * **type** string, optional, default "string", valori possibili **string**, **numeric**, **date**, **image**, **html** | + | * **type** string, optional, default "string", valori possibili **string**, **numeric**, **date**, **boolean**, **image**, **html** |
* **label** string, optional, label da usare per la rappresentazione. In sua assenza viene usata la medesima //key// di primo livello del JSON | * **label** string, optional, label da usare per la rappresentazione. In sua assenza viene usata la medesima //key// di primo livello del JSON | ||
* **order**, integer, optional, determina l'ordine all'interno del gruppo (gli elementi senza ordine hanno precedenza, in base all'ordine di comparsa nel JSON) | * **order**, integer, optional, determina l'ordine all'interno del gruppo (gli elementi senza ordine hanno precedenza, in base all'ordine di comparsa nel JSON) | ||
Linea 1005: | Linea 1006: | ||
* **pattern** string, optional, default null. Stesso funzionamento del //widget NumberBox//. Esempi: "#.", "#.00", "#.## %", "#.00 €", "#. €" | * **pattern** string, optional, default null. Stesso funzionamento del //widget NumberBox//. Esempi: "#.", "#.00", "#.## %", "#.00 €", "#. €" | ||
* //type date// (nel //value// del primo livello del JSON ammessi valori nel formato stringa e intero (data in millisecondi)) | * //type date// (nel //value// del primo livello del JSON ammessi valori nel formato stringa e intero (data in millisecondi)) | ||
- | * **format**, string, optional default "dd/MM/yyyy". Formati ammessi: //"dd-MM-yyyy", "yyyy-MM-dd", "yyyy/MM/dd", "dd/MM/yyyy", "dd MMMM yyyy", "yyyy MMMM dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "dd-MM-yyyy HH:mm:ss", "dd-MM-yyyy HH:mm", "dd/MM/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm", "HH:mm:ss": "HH:mm:ss", "EEEE, dd MMMM yyyy"// | + | * **constraints**, object, optional, default null. Con dentro: |
+ | * **datePattern** string, optional, default "dd/MM/yyyy". Formati ammessi: //"dd-MM-yyyy", "yyyy-MM-dd", "yyyy/MM/dd", "dd/MM/yyyy", "dd MMMM yyyy", "yyyy MMMM dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "dd-MM-yyyy HH:mm:ss", "dd-MM-yyyy HH:mm", "dd/MM/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm", "HH:mm:ss": "HH:mm:ss", "EEEE, dd MMMM yyyy"// | ||
+ | * **format** @Deprecated from 4.7.4 (usare constraints.datePattern), string, optional default "dd/MM/yyyy". Formati ammessi: //"dd-MM-yyyy", "yyyy-MM-dd", "yyyy/MM/dd", "dd/MM/yyyy", "dd MMMM yyyy", "yyyy MMMM dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "dd-MM-yyyy HH:mm:ss", "dd-MM-yyyy HH:mm", "dd/MM/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm", "HH:mm:ss": "HH:mm:ss", "EEEE, dd MMMM yyyy"// | ||
* //type image// (nel //value// del primo livello del JSON ammessi solo valori stringa (nome del file, con estenzione, con eventuale path relativo)) | * //type image// (nel //value// del primo livello del JSON ammessi solo valori stringa (nome del file, con estenzione, con eventuale path relativo)) | ||
* **height**, string (HTML height), optional, default "100px". Quando usato imposta un'altezza specifica per l'immagine | * **height**, string (HTML height), optional, default "100px". Quando usato imposta un'altezza specifica per l'immagine | ||
+ | * //type boolean// (nel //value// del primo livello del JSON ammessi valori nel formato boolean true/false) | ||
* //type html// (nel //value// del primo livello del JSON ammessi solo valori stringa, contenenti codice html) | * //type html// (nel //value// del primo livello del JSON ammessi solo valori stringa, contenenti codice html) | ||
- | Esempio semplificato: | + | === Esempi === |
+ | |||
+ | **Esempio semplificato** | ||
+ | Configurazione con metadati minimale per un tipo di dato stringa. | ||
<code json> | <code json> | ||
Linea 1038: | Linea 1045: | ||
- | Esempio esteso: | + | **Esempio esteso** |
In questo esempio sono presenti tutte le tipologie di dato, predisposte con molte varianti di presentazione. | In questo esempio sono presenti tutte le tipologie di dato, predisposte con molte varianti di presentazione. | ||
A sinistra del gwClassDetail è presente il dato JSON in un widget codeEditor. A destra il relativo risultato finale. | A sinistra del gwClassDetail è presente il dato JSON in un widget codeEditor. A destra il relativo risultato finale. | ||
{{:gwusermanual:interface:labelvaluejsonwidget.jpg?1000|}} | {{:gwusermanual:interface:labelvaluejsonwidget.jpg?1000|}} | ||
+ | |||
+ | Relativo dato JSON comprensivo di metadati | ||
<code json> | <code json> | ||
Linea 1111: | Linea 1120: | ||
"order": 3, | "order": 3, | ||
"params": { | "params": { | ||
- | "format": "yyyy-MM-dd HH:mm:ss" | + | "constraints": {"datePattern": "yyyy-MM-dd HH:mm:ss"} |
}, | }, | ||
"group_code": "group_3" | "group_code": "group_3" | ||
Linea 1120: | Linea 1129: | ||
"order": 4, | "order": 4, | ||
"params": { | "params": { | ||
- | "format": "dd-MM-yyyy HH:mm:ss" | + | "constraints": {"datePattern": "dd-MM-yyyy HH:mm:ss"} |
}, | }, | ||
"group_code": "group_3" | "group_code": "group_3" | ||
Linea 1129: | Linea 1138: | ||
"order": 5, | "order": 5, | ||
"params": { | "params": { | ||
- | "format": "HH:mm:ss" | + | "constraints": {"datePattern": "HH:mm:ss"} |
}, | }, | ||
"group_code": "group_3" | "group_code": "group_3" | ||
Linea 1278: | Linea 1287: | ||
</code> | </code> | ||
+ | === Popolamento JSON tramite groovy === | ||
+ | |||
+ | Il widget nasce con finalità di presentazione del dato. Nelle varie piattaforme il dato tipicamente deriva da attributi variabili, ospitati in classi/tabelle differenti dalla classe padre dove tipicamente dov'à essere usato questo widget. | ||
+ | |||
+ | Nella classe padre si avrà quindi un campo JSON, che verrà popolato con solo una sintesi di tutta la mole di dati presente negli attributi variabili. | ||
+ | |||
+ | Il popolamento del dato avviene tipicamente tramite groovy. | ||
+ | |||
+ | Sotto un groovy di esempio per la creazione del JSON con relativi metadati. | ||
+ | |||
+ | Si tenga presente che quando nel GwAdmin è impostato il tipo di dato JSON per un attributo, nella mappa destinata all'insert/update, si può usare indistintamente sia una string in formato JSON, che una mappa, con coppie chiave valore. | ||
+ | Per praticità conviene sempre usare una mappa. | ||
+ | Questo anche perchè nei anche nei vari metodi di seleizone il valoredi un field json viene restituito come mappa. | ||
+ | |||
+ | <code java> | ||
+ | |||
+ | String gwClassName = "gw_class_name"; | ||
+ | |||
+ | def map = [:]; | ||
+ | |||
+ | def jsonMap = [:]; | ||
+ | |||
+ | |||
+ | //popolamento key-value primo livello json | ||
+ | //TODO rinominare le key e recuperare i valori da altre classi/tabelle | ||
+ | jsonMap.key_date_1 = 1738573528392; | ||
+ | jsonMap.key_date_2 = "2025-02-03T09:16:00.565Z"; | ||
+ | jsonMap.key_date_3 = 1738573528392; | ||
+ | jsonMap.key_date_4 = "2025-02-03T09:16:00.565Z"; | ||
+ | jsonMap.key_date_5 = "2025-02-03T09:16:00.565Z"; | ||
+ | jsonMap.key_html_1 = "<span style='height: 40px; display: flex; align-items: center;'><i class='fa-solid fa-circle-check gwMainColor icon32x32'></i><span style='margin-left: 15px; font-weight: bold;' >Approved<span/><span/>"; | ||
+ | jsonMap.key_image_1 = "TEST/Galleria/12023.jpg"; | ||
+ | jsonMap.key_image_2 = "TEST/Galleria/download.jpg"; | ||
+ | jsonMap.key_string_1 = "Yes"; | ||
+ | jsonMap.key_string_2 = "Questa è una nota estesa. Questa è una nota estesa."; | ||
+ | jsonMap.key_string_3 = "Questa è una nota estesa. Questa è una nota estesa. Questa è una nota estesa. Questa è una nota estesa. Questa è una nota estesa."; | ||
+ | jsonMap.key_numeric_1 = 12345; | ||
+ | jsonMap.key_numeric_2 = 12.345; | ||
+ | jsonMap.key_numeric_3 = 1; | ||
+ | jsonMap.key_numeric_4 = 1; | ||
+ | jsonMap.key_numeric_5 = 0.569; | ||
+ | jsonMap.key_numeric_7 = 600000; | ||
+ | jsonMap.key_numeric_8 = 10.57; | ||
+ | |||
+ | //popolamento key-value primo livello json senza _metadata (e con key complessa che viene usata come label) | ||
+ | jsonMap["Image senza _metadata"] = "TEST/Galleria/download.jpg"; | ||
+ | jsonMap["String senza _metadata"] = "generic string"; | ||
+ | jsonMap["Date senza _metadata ms"] = 1738573528392; | ||
+ | jsonMap["Numeric senza _metadata"] = 999; | ||
+ | jsonMap["Date senza _metadata string ISO-8601"] = "2025-02-03T09:16:00.565Z"; | ||
+ | |||
+ | |||
+ | |||
+ | //popolamento key _metadata | ||
+ | |||
+ | //definizione dei gruppi | ||
+ | def groupsMap = [ | ||
+ | group_1: [ | ||
+ | label: "Testo (\"type\": \"string\")", | ||
+ | order: 1 | ||
+ | ], | ||
+ | group_2: [ | ||
+ | label: "Testo (\"type\": \"numeric\")", | ||
+ | order: 2 | ||
+ | ], | ||
+ | group_3: [ | ||
+ | label: "Testo (\"type\": \"date\")", | ||
+ | order: 3 | ||
+ | ], | ||
+ | group_4: [ | ||
+ | label: "Testo (\"type\": \"image\")", | ||
+ | order: 4 | ||
+ | ], | ||
+ | group_5: [ | ||
+ | label: "Testo (\"type\": \"html\")", | ||
+ | order: 5 | ||
+ | ] | ||
+ | ]; | ||
+ | |||
+ | //definizione dei parametri dei metadata | ||
+ | def parametersMap = [ | ||
+ | key_string_1: [ | ||
+ | type: "string", | ||
+ | label: "Confermi?", | ||
+ | order: 1, | ||
+ | group_code: "group_1" | ||
+ | ], | ||
+ | key_string_2: [ | ||
+ | type: "string", | ||
+ | label: "Testo (useTextArea true)", | ||
+ | order: 2, | ||
+ | params: [ | ||
+ | useTextArea: true | ||
+ | ], | ||
+ | group_code: "group_1" | ||
+ | ], | ||
+ | key_string_3: [ | ||
+ | type: "string", | ||
+ | label: "Testo (useTextArea true, height 100px, maxHeight:300px)", | ||
+ | order: 3, | ||
+ | params: [ | ||
+ | useTextArea: true, | ||
+ | height: "100px", | ||
+ | maxHeight: "300px" | ||
+ | ], | ||
+ | group_code: "group_1" | ||
+ | ], | ||
+ | |||
+ | key_numeric_1: [ | ||
+ | type: "numeric", | ||
+ | label: "Numero intero", | ||
+ | order: 1, | ||
+ | params: [ | ||
+ | constraints: [ | ||
+ | places: 0, | ||
+ | pattern: "#." | ||
+ | ] | ||
+ | ], | ||
+ | group_code: "group_2" | ||
+ | ], | ||
+ | key_numeric_2: [ | ||
+ | type: "numeric", | ||
+ | label: "Numero decimale", | ||
+ | order: 2, | ||
+ | params: [ | ||
+ | constraints: [ | ||
+ | places: 2, | ||
+ | pattern: "00#." | ||
+ | ] | ||
+ | ], | ||
+ | group_code: "group_2" | ||
+ | ], | ||
+ | key_numeric_3: [ | ||
+ | type: "numeric", | ||
+ | label: "Numero decimale places 4", | ||
+ | order: 3, | ||
+ | params: [ | ||
+ | constraints: [ | ||
+ | places: 4, | ||
+ | pattern: "#." | ||
+ | ] | ||
+ | ], | ||
+ | group_code: "group_2" | ||
+ | ], | ||
+ | key_numeric_4: [ | ||
+ | type: "numeric", | ||
+ | label: "Numero intero 0 leading", | ||
+ | order: 4, | ||
+ | params: [ | ||
+ | constraints: [ | ||
+ | places: 0, | ||
+ | pattern: "000#." | ||
+ | ] | ||
+ | ], | ||
+ | group_code: "group_2" | ||
+ | ], | ||
+ | key_numeric_5: [ | ||
+ | type: "numeric", | ||
+ | label: "% completamento", | ||
+ | order: 5, | ||
+ | params: [ | ||
+ | constraints: [ | ||
+ | places: 2, | ||
+ | pattern: "#.## %" | ||
+ | ] | ||
+ | ], | ||
+ | group_code: "group_2" | ||
+ | ], | ||
+ | key_numeric_6: [ | ||
+ | type: "numeric", | ||
+ | label: "% completamento places 2", | ||
+ | order: 6, | ||
+ | params: [ | ||
+ | constraints: [ | ||
+ | pattern: "#. %" | ||
+ | ] | ||
+ | ], | ||
+ | group_code: "group_2" | ||
+ | ], | ||
+ | key_numeric_7: [ | ||
+ | type: "numeric", | ||
+ | label: "Importo", | ||
+ | order: 7, | ||
+ | params: [ | ||
+ | constraints: [ | ||
+ | pattern: "#.00 €" | ||
+ | ] | ||
+ | ], | ||
+ | group_code: "group_2" | ||
+ | ], | ||
+ | key_numeric_8: [ | ||
+ | type: "numeric", | ||
+ | label: "Importo no decimals", | ||
+ | order: 8, | ||
+ | params: [ | ||
+ | constraints: [ | ||
+ | pattern: "#. €" | ||
+ | ] | ||
+ | ] | ||
+ | ], | ||
+ | |||
+ | key_date_1: [ | ||
+ | type: "date", | ||
+ | label: "Data ms default", | ||
+ | order: 1, | ||
+ | group_code: "group_3" | ||
+ | ], | ||
+ | key_date_2: [ | ||
+ | type: "date", | ||
+ | label: "Data string ISO-8601 default", | ||
+ | order: 2, | ||
+ | group_code: "group_3" | ||
+ | ], | ||
+ | key_date_3: [ | ||
+ | type: "date", | ||
+ | label: "Data ms params.format 'yyyy-MM-dd HH:mm:ss'", | ||
+ | order: 3, | ||
+ | params: [ | ||
+ | format: "yyyy-MM-dd HH:mm:ss" | ||
+ | ], | ||
+ | group_code: "group_3" | ||
+ | ], | ||
+ | key_date_4: [ | ||
+ | type: "date", | ||
+ | label: "Data string ISO-8601 params.format 'dd-MM-yyyy HH:mm:ss'", | ||
+ | order: 4, | ||
+ | params: [ | ||
+ | format: "dd-MM-yyyy HH:mm:ss" | ||
+ | ], | ||
+ | group_code: "group_3" | ||
+ | ], | ||
+ | key_date_5: [ | ||
+ | type: "date", | ||
+ | label: "Data string ISO-8601 params.format 'HH:mm:ss'", | ||
+ | order: 5, | ||
+ | params: [ | ||
+ | format: "HH:mm:ss" | ||
+ | ], | ||
+ | group_code: "group_3" | ||
+ | ], | ||
+ | |||
+ | key_image_1: [ | ||
+ | type: "image", | ||
+ | label: "Immagine da CMS (default)", | ||
+ | order: 1, | ||
+ | group_code: "group_4" | ||
+ | ], | ||
+ | key_image_2: [ | ||
+ | type: "image", | ||
+ | label: "Immagine da CMS (height 50px)", | ||
+ | order: 2, | ||
+ | params: [ | ||
+ | height: "50px" | ||
+ | ], | ||
+ | group_code: "group_4" | ||
+ | ], | ||
+ | |||
+ | key_html_1: [ | ||
+ | type: "html", | ||
+ | label: "custom html", | ||
+ | order: 1, | ||
+ | params: [], | ||
+ | group_code: "group_5" | ||
+ | ] | ||
+ | ]; | ||
+ | |||
+ | |||
+ | jsonMap._metadata = [ | ||
+ | groups: groupsMap, | ||
+ | parameters: parametersMap | ||
+ | ]; | ||
+ | |||
+ | map.id_field = 123; | ||
+ | //... | ||
+ | map.jsonb_field = jsonMap; | ||
+ | |||
+ | services.classService.updateClassRecord(gwClassName, map); | ||
+ | |||
+ | </code> | ||
+ | |||
+ | === Note implementative per le date === | ||
+ | |||
+ | Sebbene il visualizzatore JSON supporto formalmente una grande varietà di formati supportati per il type 'date', nelle implementazioni va usato la versione stringa nel formato **'dd-MM-yyyy HH:mm:ss'** (uguale al //timestamp// del database). Quindi NON la versione ISO-8601, con o senza TIMEZONE. | ||
+ | |||
+ | Questo per le logiche dei filtri del queryBuilder di geoweb. | ||
| |