@plusscommunities/pluss-maintenance-web-forms 1.1.35 → 1.1.37-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,166 +1,320 @@
1
- import React, { useState, useEffect } from 'react';
2
- import moment from 'moment';
3
- import { faCircleCheck, faComment, faWrench } from '@fortawesome/free-solid-svg-icons';
4
- import { connect } from 'react-redux';
5
- import { analyticsActions } from '../apis';
6
- import { PlussCore } from '../feature.config';
7
- import { values } from '../values.config';
1
+ import React, { useState, useEffect } from "react";
2
+ import moment from "moment";
3
+ import {
4
+ faCircleCheck,
5
+ faComment,
6
+ faWrench,
7
+ } from "@fortawesome/free-solid-svg-icons";
8
+ import { connect } from "react-redux";
9
+ import { analyticsActions } from "../apis";
10
+ import { PlussCore } from "../feature.config";
11
+ import { values } from "../values.config";
8
12
 
9
- const { Analytics, Session, Components } = PlussCore;
13
+ const { Analytics, Session, Components, Helper } = PlussCore;
10
14
 
11
15
  const getInitialState = () => ({
12
- requests: 0,
13
- prevRequests: 0,
14
- completedRequests: 0,
15
- prevCompletedRequests: 0,
16
- comments: 0,
17
- prevComments: 0,
18
- isLoading: true,
16
+ requests: 0,
17
+ prevRequests: 0,
18
+ completedRequests: 0,
19
+ prevCompletedRequests: 0,
20
+ comments: 0,
21
+ prevComments: 0,
22
+ isLoading: true,
19
23
  });
20
24
 
21
25
  // AnalyticsHub Component
22
- const AnalyticsHub = ({ startTime, endTime, auth, prevText, dayCount, strings }) => {
23
- const [analyticsData, setAnalyticsData] = useState(getInitialState());
24
- const [isExportOpen, setIsExportOpen] = useState(false);
25
-
26
- const hasAccess = Session.validateAccess(auth.site, values.permissionMaintenanceTracking, auth);
27
- if (!hasAccess) {
28
- return null;
29
- }
30
-
31
- const featureTitle = ((key) => {
32
- if (!strings || !strings.sideNav || !strings.sideNav[key]) {
33
- return values.textMenuTitle;
34
- }
35
- return strings.sideNav[key];
36
- })();
37
-
38
- const exportColumns = [
39
- { label: 'Select All', key: '' },
40
- { label: 'Start Date', key: 'startDate' },
41
- { label: 'End Date', key: 'endDate' },
42
- { label: `${values.textSingularName}s`, key: 'requests' },
43
- { label: `Completed ${values.textSingularName}s`, key: 'completedRequests' },
44
- { label: 'Comments', key: 'comments' },
45
- ];
46
-
47
- useEffect(() => {
48
- getData();
49
- }, [startTime, endTime]);
50
-
51
- const getData = async () => {
52
- setAnalyticsData(getInitialState());
53
- // Load analytics data here using startTime and endTime
54
- const timeDifference = endTime - startTime;
55
- const [currentStatsResponse, prevStatsResponse] = await Promise.all([
56
- analyticsActions.getAggregateEntityStats(auth.site, values.analyticsKey, startTime, endTime, true),
57
- analyticsActions.getAggregateEntityStats(auth.site, values.analyticsKey, startTime - timeDifference, startTime, true),
58
- ]);
59
-
60
- const data = {
61
- requests: Analytics.countActivities(currentStatsResponse.data, 'Request', 'total'),
62
- prevRequests: Analytics.countActivities(prevStatsResponse.data, 'Request', 'total'),
63
- completedRequests: Analytics.countActivities(currentStatsResponse.data, 'RequestCompleted', 'unique'),
64
- prevCompletedRequests: Analytics.countActivities(prevStatsResponse.data, 'RequestCompleted', 'unique'),
65
- comments: Analytics.countActivities(currentStatsResponse.data, 'Comment', 'total'),
66
- prevComments: Analytics.countActivities(prevStatsResponse.data, 'Comment', 'total'),
67
- isLoading: false,
68
- };
69
- setAnalyticsData(data);
70
- };
71
-
72
- const isReadyToOpenCSV = () => {
73
- return !analyticsData.isLoading;
74
- };
75
-
76
- const getExportSource = () => {
77
- return [
78
- {
79
- startDate: moment(startTime + 1).format('D-MM-YYYY'),
80
- endDate: moment(endTime).format('D-MM-YYYY'),
81
- requests: analyticsData.requests,
82
- completedRequests: analyticsData.completedRequests,
83
- comments: analyticsData.comments,
84
- },
85
- ];
86
- };
87
-
88
- const csvPopup = () => {
89
- if (!isExportOpen) {
90
- return null;
91
- }
92
- const source = getExportSource();
93
- return (
94
- <Components.ExportCsvPopup
95
- onClose={() => {
96
- setIsExportOpen(false);
97
- }}
98
- columns={exportColumns}
99
- source={source}
100
- filename={`${values.analyticsKey}analytics_${source[0].startDate}_${source[0].endDate}.csv`}
101
- />
102
- );
103
- };
104
-
105
- return (
106
- <div className="dashboardSection">
107
- {csvPopup()}
108
- <div>
109
- <Components.Text type="h4" className="inlineBlock marginRight-40">
110
- {featureTitle}
111
- </Components.Text>
112
- <Components.Button
113
- inline
114
- buttonType="primaryAction"
115
- onClick={() => {
116
- if (!isReadyToOpenCSV()) return;
117
- setIsExportOpen(true);
118
- }}
119
- isActive={isReadyToOpenCSV()}
120
- leftIcon="file-code-o"
121
- >
122
- Export CSV
123
- </Components.Button>
124
- </div>
125
- <div className="analyticsSection dashboardSection_content">
126
- <Components.StatBox
127
- title={`${featureTitle} Requests`}
128
- icon={faWrench}
129
- value={analyticsData.requests}
130
- previousValue={analyticsData.prevRequests}
131
- prevText={prevText}
132
- viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=Request&countType=total&dayCount=${dayCount}`}
133
- isLoading={analyticsData.isLoading}
134
- />
135
- <Components.StatBox
136
- title={`Completed ${featureTitle} Requests`}
137
- icon={faCircleCheck}
138
- value={analyticsData.completedRequests}
139
- previousValue={analyticsData.prevCompletedRequests}
140
- prevText={prevText}
141
- viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=RequestCompleted&countType=unique&dayCount=${dayCount}`}
142
- isLoading={analyticsData.isLoading}
143
- />
144
- <Components.StatBox
145
- title={`${featureTitle} Comments`}
146
- icon={faComment}
147
- value={analyticsData.comments}
148
- previousValue={analyticsData.prevComments}
149
- prevText={prevText}
150
- viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=Comment&countType=total&dayCount=${dayCount}`}
151
- isLoading={analyticsData.isLoading}
152
- />
153
- </div>
154
- </div>
155
- );
26
+ const AnalyticsHub = ({
27
+ startTime,
28
+ endTime,
29
+ auth,
30
+ prevText,
31
+ dayCount,
32
+ strings,
33
+ userType,
34
+ userCategory,
35
+ selectedSites,
36
+ }) => {
37
+ const [analyticsData, setAnalyticsData] = useState(getInitialState());
38
+ const [isExportOpen, setIsExportOpen] = useState(false);
39
+ const [comparisonData, setComparisonData] = useState({
40
+ requests: [],
41
+ completedRequests: [],
42
+ comments: [],
43
+ isLoading: true,
44
+ });
45
+
46
+ const comparisonMode = selectedSites && selectedSites.length > 1;
47
+
48
+ const hasAccess = Session.validateAccess(
49
+ auth.site,
50
+ values.permissionMaintenanceTracking,
51
+ auth,
52
+ );
53
+ if (!hasAccess) {
54
+ return null;
55
+ }
56
+
57
+ const featureTitle = ((key) => {
58
+ if (!strings || !strings.sideNav || !strings.sideNav[key]) {
59
+ return values.textMenuTitle;
60
+ }
61
+ return strings.sideNav[key];
62
+ })();
63
+
64
+ const exportColumns = [
65
+ { label: "Select All", key: "" },
66
+ { label: "Start Date", key: "startDate" },
67
+ { label: "End Date", key: "endDate" },
68
+ { label: `${values.textSingularName}s`, key: "requests" },
69
+ {
70
+ label: `Completed ${values.textSingularName}s`,
71
+ key: "completedRequests",
72
+ },
73
+ { label: "Comments", key: "comments" },
74
+ ];
75
+
76
+ useEffect(() => {
77
+ getData();
78
+ }, [startTime, endTime, userType, userCategory, selectedSites]);
79
+
80
+ const getData = async () => {
81
+ if (comparisonMode) {
82
+ setComparisonData({
83
+ requests: [],
84
+ completedRequests: [],
85
+ comments: [],
86
+ isLoading: true,
87
+ });
88
+ const multiSiteResultsObj = await Analytics.fetchMultiSiteData(
89
+ selectedSites,
90
+ async (site) => {
91
+ const { data } = await analyticsActions.getAggregateEntityStats(
92
+ site,
93
+ values.analyticsKey,
94
+ startTime,
95
+ endTime,
96
+ true,
97
+ { userType, userCategory },
98
+ );
99
+ return data;
100
+ },
101
+ );
102
+ const multiSiteResults = Object.entries(multiSiteResultsObj).map(
103
+ ([site, data]) => ({ site, data }),
104
+ );
105
+ const roles = auth.user.Roles;
106
+ const buildComparison = (activityKey, countType) =>
107
+ multiSiteResults.map((result) => ({
108
+ name: Helper.getSiteNameFromRoles(result.site, roles),
109
+ value: Analytics.countActivities(result.data, activityKey, countType),
110
+ }));
111
+ setComparisonData({
112
+ requests: buildComparison("Request", "total"),
113
+ completedRequests: buildComparison("RequestCompleted", "unique"),
114
+ comments: buildComparison("Comment", "total"),
115
+ isLoading: false,
116
+ });
117
+ } else {
118
+ setAnalyticsData(getInitialState());
119
+ const site =
120
+ selectedSites && selectedSites.length === 1
121
+ ? selectedSites[0]
122
+ : auth.site;
123
+ const timeDifference = endTime - startTime;
124
+ const [currentStatsResponse, prevStatsResponse] = await Promise.all([
125
+ analyticsActions.getAggregateEntityStats(
126
+ site,
127
+ values.analyticsKey,
128
+ startTime,
129
+ endTime,
130
+ true,
131
+ { userType, userCategory },
132
+ ),
133
+ analyticsActions.getAggregateEntityStats(
134
+ site,
135
+ values.analyticsKey,
136
+ startTime - timeDifference,
137
+ startTime,
138
+ true,
139
+ { userType, userCategory },
140
+ ),
141
+ ]);
142
+
143
+ const data = {
144
+ requests: Analytics.countActivities(
145
+ currentStatsResponse.data,
146
+ "Request",
147
+ "total",
148
+ ),
149
+ prevRequests: Analytics.countActivities(
150
+ prevStatsResponse.data,
151
+ "Request",
152
+ "total",
153
+ ),
154
+ completedRequests: Analytics.countActivities(
155
+ currentStatsResponse.data,
156
+ "RequestCompleted",
157
+ "unique",
158
+ ),
159
+ prevCompletedRequests: Analytics.countActivities(
160
+ prevStatsResponse.data,
161
+ "RequestCompleted",
162
+ "unique",
163
+ ),
164
+ comments: Analytics.countActivities(
165
+ currentStatsResponse.data,
166
+ "Comment",
167
+ "total",
168
+ ),
169
+ prevComments: Analytics.countActivities(
170
+ prevStatsResponse.data,
171
+ "Comment",
172
+ "total",
173
+ ),
174
+ isLoading: false,
175
+ };
176
+ setAnalyticsData(data);
177
+ }
178
+ };
179
+
180
+ const isReadyToOpenCSV = () => {
181
+ return comparisonMode
182
+ ? !comparisonData.isLoading
183
+ : !analyticsData.isLoading;
184
+ };
185
+
186
+ const getExportSource = () => {
187
+ return [
188
+ {
189
+ startDate: moment(startTime + 1).format("D-MM-YYYY"),
190
+ endDate: moment(endTime).format("D-MM-YYYY"),
191
+ requests: analyticsData.requests,
192
+ completedRequests: analyticsData.completedRequests,
193
+ comments: analyticsData.comments,
194
+ },
195
+ ];
196
+ };
197
+
198
+ const csvPopup = () => {
199
+ if (!isExportOpen) {
200
+ return null;
201
+ }
202
+ const source = getExportSource();
203
+ return (
204
+ <Components.ExportCsvPopup
205
+ onClose={() => {
206
+ setIsExportOpen(false);
207
+ }}
208
+ columns={exportColumns}
209
+ source={source}
210
+ filename={`${values.analyticsKey}analytics_${source[0].startDate}_${source[0].endDate}.csv`}
211
+ />
212
+ );
213
+ };
214
+
215
+ return (
216
+ <div className="dashboardSection">
217
+ {csvPopup()}
218
+ <div>
219
+ <Components.Text type="h4" className="inlineBlock marginRight-40">
220
+ {featureTitle}
221
+ </Components.Text>
222
+ <Components.Button
223
+ inline
224
+ buttonType="primaryAction"
225
+ onClick={() => {
226
+ if (!isReadyToOpenCSV()) return;
227
+ setIsExportOpen(true);
228
+ }}
229
+ isActive={isReadyToOpenCSV()}
230
+ leftIcon="file-code-o"
231
+ >
232
+ Export CSV
233
+ </Components.Button>
234
+ </div>
235
+ <div className="analyticsSection dashboardSection_content">
236
+ {(() => {
237
+ const chartSuffix = [
238
+ selectedSites && selectedSites.length > 0
239
+ ? `&sites=${selectedSites.join(",")}`
240
+ : "",
241
+ userType ? `&userType=${encodeURIComponent(userType)}` : "",
242
+ userCategory
243
+ ? `&userCategory=${encodeURIComponent(userCategory)}`
244
+ : "",
245
+ ].join("");
246
+ if (comparisonMode) {
247
+ return (
248
+ <div
249
+ style={{ display: "flex", flexDirection: "column", gap: 16 }}
250
+ >
251
+ <Components.ComparisonStatBox
252
+ title={`${featureTitle} Requests`}
253
+ data={comparisonData.requests}
254
+ prevText={prevText}
255
+ viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=Request&countType=total&dayCount=${dayCount}${chartSuffix}`}
256
+ isLoading={comparisonData.isLoading}
257
+ />
258
+ <Components.ComparisonStatBox
259
+ title={`Completed ${featureTitle} Requests`}
260
+ data={comparisonData.completedRequests}
261
+ prevText={prevText}
262
+ viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=RequestCompleted&countType=unique&dayCount=${dayCount}${chartSuffix}`}
263
+ isLoading={comparisonData.isLoading}
264
+ />
265
+ <Components.ComparisonStatBox
266
+ title={`${featureTitle} Comments`}
267
+ data={comparisonData.comments}
268
+ prevText={prevText}
269
+ viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=Comment&countType=total&dayCount=${dayCount}${chartSuffix}`}
270
+ isLoading={comparisonData.isLoading}
271
+ />
272
+ </div>
273
+ );
274
+ }
275
+ return (
276
+ <>
277
+ <Components.StatBox
278
+ title={`${featureTitle} Requests`}
279
+ icon={faWrench}
280
+ value={analyticsData.requests}
281
+ previousValue={analyticsData.prevRequests}
282
+ prevText={prevText}
283
+ viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=Request&countType=total&dayCount=${dayCount}${chartSuffix}`}
284
+ isLoading={analyticsData.isLoading}
285
+ />
286
+ <Components.StatBox
287
+ title={`Completed ${featureTitle} Requests`}
288
+ icon={faCircleCheck}
289
+ value={analyticsData.completedRequests}
290
+ previousValue={analyticsData.prevCompletedRequests}
291
+ prevText={prevText}
292
+ viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=RequestCompleted&countType=unique&dayCount=${dayCount}${chartSuffix}`}
293
+ isLoading={analyticsData.isLoading}
294
+ />
295
+ <Components.StatBox
296
+ title={`${featureTitle} Comments`}
297
+ icon={faComment}
298
+ value={analyticsData.comments}
299
+ previousValue={analyticsData.prevComments}
300
+ prevText={prevText}
301
+ viewGraphLink={`/chart?entity=${values.analyticsKey}&startTime=${startTime}&endTime=${endTime}&key=Comment&countType=total&dayCount=${dayCount}${chartSuffix}`}
302
+ isLoading={analyticsData.isLoading}
303
+ />
304
+ </>
305
+ );
306
+ })()}
307
+ </div>
308
+ </div>
309
+ );
156
310
  };
157
311
 
158
312
  const mapStateToProps = (state) => {
159
- const { auth } = state;
160
- return {
161
- auth,
162
- strings: (state.strings && state.strings.config) || {},
163
- };
313
+ const { auth } = state;
314
+ return {
315
+ auth,
316
+ strings: (state.strings && state.strings.config) || {},
317
+ };
164
318
  };
165
319
 
166
320
  const toExport = connect(mapStateToProps, {})(AnalyticsHub);