1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.kibana.modules.forms.service;
35
36 import java.util.List;
37 import fr.paris.lutece.plugins.elasticdata.business.DataSource;
38 import fr.paris.lutece.plugins.elasticdata.modules.forms.business.OptionalQuestionIndexation;
39 import fr.paris.lutece.plugins.elasticdata.modules.forms.business.OptionalQuestionIndexationHome;
40 import fr.paris.lutece.plugins.forms.business.Form;
41 import fr.paris.lutece.plugins.forms.business.FormHome;
42 import fr.paris.lutece.plugins.forms.business.Question;
43 import fr.paris.lutece.plugins.forms.business.QuestionHome;
44 import fr.paris.lutece.plugins.kibana.business.DashboardReference;
45 import fr.paris.lutece.plugins.kibana.business.GirdLayout;
46 import fr.paris.lutece.plugins.kibana.service.IDataVisualizerService;
47 import fr.paris.lutece.plugins.kibana.service.SavedObjectService;
48 import fr.paris.lutece.plugins.kibana.service.VisualizationService;
49 import fr.paris.lutece.portal.business.event.ResourceEvent;
50 import net.sf.json.JSONArray;
51 import net.sf.json.JSONObject;
52
53
54
55
56
57
58 public class DataVisualizerService implements IDataVisualizerService
59 {
60 public static final String DATA_SOURCE_ID = "FormsDataSource";
61
62 @Override
63 public void createOrUpdate( ResourceEvent event, DataSource dataSource )
64 {
65 List<Form> listForms = FormHome.getFormList( );
66 String strIdIndexPattern = dataSource.getTargetIndexName( );
67 for ( Form form : listForms )
68 {
69 JSONArray jsonArrayReference = new JSONArray( );
70 JSONArray jsonArraypanelsJSON = new JSONArray( );
71 String strIdDashboard = event.getIdResource( ) + "_" + form.getId( );
72 GirdLayout girdLayout = new GirdLayout( );
73 String strQueryFilterFormResponse = "documentTypeName.keyword : formResponse and formId : " + form.getId( );
74 initDashboard( jsonArrayReference, jsonArraypanelsJSON, strIdDashboard, strIdIndexPattern, girdLayout, form.getId( ) );
75 SavedObjectService.deleteDashboard( strIdDashboard );
76 List<OptionalQuestionIndexation> optionalQuestionIndexations = OptionalQuestionIndexationHome
77 .getOptionalQuestionIndexationListByFormId( form.getId( ) );
78 if ( optionalQuestionIndexations != null )
79 {
80 for ( OptionalQuestionIndexation optionalQuestionIndexation : optionalQuestionIndexations )
81 {
82 int idQuestion = optionalQuestionIndexation.getIdQuestion( );
83 Question question = QuestionHome.findByPrimaryKey( idQuestion );
84 String strType = question.getEntry( ).getEntryType( ).getBeanName( );
85 String fieldName = getFieldName( strType, question.getId( ), question.getTitle( ) );
86 if ( strType.contains( "entryTypeSelect" ) || strType.contains( "entryTypeCheckBox" ) || strType.contains( "entryTypeRadioButton" ) )
87 {
88 DashboardReference dashboardReferenceLens = new DashboardReference( "lens" );
89 jsonArrayReference.add( dashboardReferenceLens );
90 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReferenceLens.getName( ), girdLayout.getPos( 12, 10 ) ) );
91 VisualizationService.createDonutLensVisualization( question.getTitle( ), fieldName, dashboardReferenceLens.getId( ), strIdIndexPattern,
92 strQueryFilterFormResponse );
93 DashboardReference dashboardReferenceTable = new DashboardReference( );
94 jsonArrayReference.add( dashboardReferenceTable );
95 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReferenceTable.getName( ), girdLayout.getPos( 12, 10 ) ) );
96 VisualizationService.createDataTableTopValueVisualization( question.getTitle( ), fieldName, dashboardReferenceTable.getId( ),
97 strIdIndexPattern, strQueryFilterFormResponse );
98 }
99 if ( strType.contains( "entryTypeGeolocation" ) )
100 {
101 DashboardReference dashboardReferenceMap = new DashboardReference( "map" );
102 jsonArrayReference.add( dashboardReferenceMap );
103 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReferenceMap.getName( ), girdLayout.getPos( 24, 10 ) ) );
104 VisualizationService.createMapVisualization( question.getTitle( ), fieldName, dashboardReferenceMap.getId( ), strIdIndexPattern,
105 strQueryFilterFormResponse );
106 DashboardReference dashboardReferenceTable = new DashboardReference( );
107 jsonArrayReference.add( dashboardReferenceTable );
108 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReferenceTable.getName( ), girdLayout.getPos( 24, 10 ) ) );
109 VisualizationService.createDataTableTopValueVisualization( question.getTitle( ),
110 fieldName.replace( "elastic.geopoint", "address.keyword" ), dashboardReferenceTable.getId( ), strIdIndexPattern,
111 strQueryFilterFormResponse );
112 }
113 if ( strType.contains( "entryTypeText" ) || strType.contains( "entryTypeTextArea" ) )
114 {
115 DashboardReference dashboardReferenceTable = new DashboardReference( );
116 jsonArrayReference.add( dashboardReferenceTable );
117 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReferenceTable.getName( ), girdLayout.getPos( 24, 10 ) ) );
118 VisualizationService.createDataTableTopValueVisualization( question.getTitle( ), fieldName, dashboardReferenceTable.getId( ),
119 strIdIndexPattern, strQueryFilterFormResponse );
120 }
121 }
122 }
123 SavedObjectService.createDashboard( strIdDashboard, form.getTitle( ), strIdIndexPattern, jsonArrayReference, jsonArraypanelsJSON, dataSource );
124 }
125 }
126
127 @Override
128 public Boolean isExistDataSourceDataVisualizer( DataSource datasource )
129 {
130 if ( datasource.getId( ).equals( DATA_SOURCE_ID ) )
131 {
132 return true;
133 }
134 return false;
135 }
136
137 private static void initDashboard( JSONArray jsonArrayReference, JSONArray jsonArraypanelsJSON, String strIdDashboard, String strIdIndexPattern,
138 GirdLayout girdLayout, int formId )
139 {
140 DashboardReference dashboardReference = new DashboardReference( );
141 jsonArrayReference.add( dashboardReference );
142 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReference.getName( ), girdLayout.getPos( 36, 10 ) ) );
143 createHistoResponseVisualization( "Histogramme des demandes", dashboardReference.getId( ), strIdIndexPattern, formId );
144 dashboardReference = new DashboardReference( );
145 jsonArrayReference.add( dashboardReference );
146 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReference.getName( ), girdLayout.getPos( 12, 10 ) ) );
147 createResponseByMonthVisualization( "Répartition par mois", dashboardReference.getId( ), strIdIndexPattern, formId );
148 dashboardReference = new DashboardReference( );
149 jsonArrayReference.add( dashboardReference );
150 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReference.getName( ), girdLayout.getPos( 24, 10 ) ) );
151 createWorkflowDurationVisualization( "Répartition par état des demandes", dashboardReference.getId( ), strIdIndexPattern, formId );
152 dashboardReference = new DashboardReference( );
153 jsonArrayReference.add( dashboardReference );
154 jsonArraypanelsJSON.add( SavedObjectService.createPanelJson( dashboardReference.getName( ), girdLayout.getPos( 24, 10 ) ) );
155 createWorkflowHistoryDurationVisualization( "Répartition de l'historique des workflows par état", dashboardReference.getId( ), strIdIndexPattern,
156 formId );
157 }
158
159 private static String getFieldName( String strEntryType, int strIdQuestion, String strQuestionTitle )
160 {
161 String strFieldName = "userResponses." + strIdQuestion + "." + strQuestionTitle;
162 if ( strEntryType.contains( "entryTypeSelect" ) || strEntryType.contains( "entryTypeRadioButton" ) )
163 {
164 strFieldName += ".answer_choice.keyword";
165 }
166 if ( strEntryType.contains( "entryTypeCheckBox" ) )
167 {
168 strFieldName = "userResponsesMultiValued." + strIdQuestion + "." + strQuestionTitle + ".keyword";
169 }
170 if ( strEntryType.contains( "entryTypeText" ) || strEntryType.contains( "entryTypeTextArea" ) )
171 {
172 strFieldName += ".keyword";
173 }
174 if ( strEntryType.contains( "entryTypeGeolocation" ) )
175 {
176 strFieldName += ".elastic.geopoint";
177 }
178 return strFieldName;
179 }
180
181
182
183
184
185
186
187 private static void createHistoResponseVisualization( String strTitle, String strIdVisualization, String strIdIndexPattern, int nFormId )
188 {
189 JSONObject bar = VisualizationService.getVisualizationObject( strTitle, strIdVisualization, strIdIndexPattern,
190 "documentTypeName.keyword : formResponse and formId : " + nFormId );
191 String visState = "{\\\"title\\\":\\\"Histogramme des demandes\\\",\\\"type\\\":\\\"histogram\\\",\\\"aggs\\\":[{\\\"id\\\":\\\"1\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"count\\\",\\\"params\\\":{\\\"customLabel\\\":\\\"Nombre de demandes\\\"},\\\"schema\\\":\\\"metric\\\"},{\\\"id\\\":\\\"2\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"date_histogram\\\",\\\"params\\\":{\\\"field\\\":\\\"timestamp\\\",\\\"timeRange\\\":{\\\"from\\\":\\\"now-1y\\\",\\\"to\\\":\\\"now\\\"},\\\"useNormalizedEsInterval\\\":true,\\\"scaleMetricValues\\\":false,\\\"interval\\\":\\\"auto\\\",\\\"drop_partials\\\":false,\\\"min_doc_count\\\":1,\\\"extended_bounds\\\":{},\\\"customLabel\\\":\\\" \\\"},\\\"schema\\\":\\\"segment\\\"},{\\\"id\\\":\\\"3\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"terms\\\",\\\"params\\\":{\\\"field\\\":\\\"workflowState.keyword\\\",\\\"orderBy\\\":\\\"1\\\",\\\"order\\\":\\\"desc\\\",\\\"size\\\":150,\\\"otherBucket\\\":false,\\\"otherBucketLabel\\\":\\\"Other\\\",\\\"missingBucket\\\":true,\\\"missingBucketLabel\\\":\\\"Sans workflow\\\",\\\"customLabel\\\":\\\"Statut\\\"},\\\"schema\\\":\\\"group\\\"}],\\\"params\\\":{\\\"type\\\":\\\"histogram\\\",\\\"grid\\\":{\\\"categoryLines\\\":false},\\\"categoryAxes\\\":[{\\\"id\\\":\\\"CategoryAxis-1\\\",\\\"type\\\":\\\"category\\\",\\\"position\\\":\\\"bottom\\\",\\\"show\\\":true,\\\"style\\\":{},\\\"scale\\\":{\\\"type\\\":\\\"linear\\\"},\\\"labels\\\":{\\\"show\\\":true,\\\"filter\\\":true,\\\"truncate\\\":100},\\\"title\\\":{}}],\\\"valueAxes\\\":[{\\\"id\\\":\\\"ValueAxis-1\\\",\\\"name\\\":\\\"LeftAxis-1\\\",\\\"type\\\":\\\"value\\\",\\\"position\\\":\\\"left\\\",\\\"show\\\":true,\\\"style\\\":{},\\\"scale\\\":{\\\"type\\\":\\\"linear\\\",\\\"mode\\\":\\\"normal\\\"},\\\"labels\\\":{\\\"show\\\":true,\\\"rotate\\\":0,\\\"filter\\\":false,\\\"truncate\\\":100},\\\"title\\\":{\\\"text\\\":\\\"Nombre de demandes\\\"}}],\\\"seriesParams\\\":[{\\\"show\\\":true,\\\"type\\\":\\\"histogram\\\",\\\"mode\\\":\\\"stacked\\\",\\\"data\\\":{\\\"label\\\":\\\"Nombre de demandes\\\",\\\"id\\\":\\\"1\\\"},\\\"valueAxis\\\":\\\"ValueAxis-1\\\",\\\"drawLinesBetweenPoints\\\":true,\\\"lineWidth\\\":2,\\\"showCircles\\\":true}],\\\"addTooltip\\\":true,\\\"addLegend\\\":true,\\\"legendPosition\\\":\\\"right\\\",\\\"times\\\":[],\\\"addTimeMarker\\\":true,\\\"labels\\\":{\\\"show\\\":true},\\\"thresholdLine\\\":{\\\"show\\\":false,\\\"value\\\":10,\\\"width\\\":1,\\\"style\\\":\\\"full\\\",\\\"color\\\":\\\"#E7664C\\\"}}}";
192 ( (JSONObject) bar.get( "attributes" ) ).put( "visState", visState );
193 SavedObjectService.create( bar );
194 }
195
196
197
198
199
200
201
202 private static void createWorkflowDurationVisualization( String strTitle, String strIdVisualization, String strIdIndexPattern, int nFormId )
203 {
204 JSONObject bar = VisualizationService.getVisualizationObject( strTitle, strIdVisualization, strIdIndexPattern,
205 "documentTypeName.keyword : formResponse and formId : " + nFormId );
206 String visState = "{\\\"title\\\":\\\"" + strTitle
207 + "\\\",\\\"type\\\":\\\"table\\\",\\\"aggs\\\":[{\\\"id\\\":\\\"1\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"count\\\",\\\"params\\\":{\\\"customLabel\\\":\\\"Nombre de demandes\\\"},\\\"schema\\\":\\\"metric\\\"},{\\\"id\\\":\\\"2\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"terms\\\",\\\"params\\\":{\\\"field\\\":\\\"workflowState.keyword\\\",\\\"orderBy\\\":\\\"1\\\",\\\"order\\\":\\\"desc\\\",\\\"size\\\":150,\\\"otherBucket\\\":false,\\\"otherBucketLabel\\\":\\\"Other\\\",\\\"missingBucket\\\":false,\\\"missingBucketLabel\\\":\\\"Missing\\\",\\\"customLabel\\\":\\\"Etat du workflow\\\"},\\\"schema\\\":\\\"bucket\\\"},{\\\"id\\\":\\\"3\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"avg\\\",\\\"params\\\":{\\\"field\\\":\\\"completeDuration\\\",\\\"customLabel\\\":\\\"Durée moyenne avant l'état\\\"},\\\"schema\\\":\\\"metric\\\"}],\\\"params\\\":{\\\"perPage\\\":150,\\\"showPartialRows\\\":false,\\\"showMetricsAtAllLevels\\\":false,\\\"sort\\\":{\\\"columnIndex\\\":null,\\\"direction\\\":null},\\\"showTotal\\\":false,\\\"totalFunc\\\":\\\"sum\\\",\\\"percentageCol\\\":\\\"Nombre de demandes\\\"}}";
208 ( (JSONObject) bar.get( "attributes" ) ).put( "visState", visState );
209 SavedObjectService.create( bar );
210 }
211
212
213
214
215
216
217
218 private static void createWorkflowHistoryDurationVisualization( String strTitle, String strIdVisualization, String strIdIndexPattern, int nFormId )
219 {
220 JSONObject bar = VisualizationService.getVisualizationObject( strTitle, strIdVisualization, strIdIndexPattern,
221 "documentTypeName.keyword : formResponseHistory and formId : " + nFormId );
222 String visState = "{\\\"title\\\":\\\"" + strTitle
223 + "\\\",\\\"type\\\":\\\"table\\\",\\\"aggs\\\":[{\\\"id\\\":\\\"1\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"count\\\",\\\"params\\\":{\\\"customLabel\\\":\\\"Nombre d'historique\\\"},\\\"schema\\\":\\\"metric\\\"},{\\\"id\\\":\\\"2\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"terms\\\",\\\"params\\\":{\\\"field\\\":\\\"workflowState.keyword\\\",\\\"orderBy\\\":\\\"1\\\",\\\"order\\\":\\\"desc\\\",\\\"size\\\":150,\\\"otherBucket\\\":false,\\\"otherBucketLabel\\\":\\\"Other\\\",\\\"missingBucket\\\":false,\\\"missingBucketLabel\\\":\\\"Missing\\\",\\\"customLabel\\\":\\\"Etat du workflow\\\"},\\\"schema\\\":\\\"bucket\\\"},{\\\"id\\\":\\\"3\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"avg\\\",\\\"params\\\":{\\\"field\\\":\\\"completeDuration\\\",\\\"customLabel\\\":\\\"Durée moyenne avant l'état\\\"},\\\"schema\\\":\\\"metric\\\"},{\\\"id\\\":\\\"4\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"avg\\\",\\\"params\\\":{\\\"field\\\":\\\"taskDuration\\\",\\\"customLabel\\\":\\\"Durée moyenne état à état\\\"},\\\"schema\\\":\\\"metric\\\"}],\\\"params\\\":{\\\"perPage\\\":150,\\\"showPartialRows\\\":false,\\\"showMetricsAtAllLevels\\\":false,\\\"sort\\\":{\\\"columnIndex\\\":null,\\\"direction\\\":null},\\\"showTotal\\\":false,\\\"totalFunc\\\":\\\"sum\\\",\\\"percentageCol\\\":\\\"\\\"}}";
224 ( (JSONObject) bar.get( "attributes" ) ).put( "visState", visState );
225 SavedObjectService.create( bar );
226 }
227
228
229
230
231
232
233
234 private static void createResponseByMonthVisualization( String strTitle, String strIdVisualization, String strIdIndexPattern, int nFormId )
235 {
236 JSONObject bar = VisualizationService.getVisualizationObject( strTitle, strIdVisualization, strIdIndexPattern,
237 "documentTypeName.keyword : formResponse and formId : " + nFormId );
238 String visState = "{\\\"title\\\":\\\"" + strTitle
239 + "\\\",\\\"type\\\":\\\"table\\\",\\\"aggs\\\":[{\\\"id\\\":\\\"1\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"count\\\",\\\"params\\\":{\\\"customLabel\\\":\\\"Nombre de réponses\\\"},\\\"schema\\\":\\\"metric\\\"},{\\\"id\\\":\\\"2\\\",\\\"enabled\\\":true,\\\"type\\\":\\\"date_histogram\\\",\\\"params\\\":{\\\"field\\\":\\\"timestamp\\\",\\\"timeRange\\\":{\\\"from\\\":\\\"now-90d\\\",\\\"to\\\":\\\"now\\\"},\\\"useNormalizedEsInterval\\\":true,\\\"scaleMetricValues\\\":false,\\\"interval\\\":\\\"M\\\",\\\"drop_partials\\\":false,\\\"min_doc_count\\\":1,\\\"extended_bounds\\\":{},\\\"customLabel\\\":\\\"Mois\\\"},\\\"schema\\\":\\\"bucket\\\"}],\\\"params\\\":{\\\"perPage\\\":10,\\\"showPartialRows\\\":false,\\\"showMetricsAtAllLevels\\\":false,\\\"sort\\\":{\\\"columnIndex\\\":null,\\\"direction\\\":null},\\\"showTotal\\\":false,\\\"totalFunc\\\":\\\"sum\\\",\\\"percentageCol\\\":\\\"\\\",\\\"row\\\":false}}";
240 ( (JSONObject) bar.get( "attributes" ) ).put( "visState", visState );
241 SavedObjectService.create( bar );
242 }
243 }