@buerokratt-ria/common-gui-components 0.0.51 → 0.0.53
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.
- package/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/templates/history-page/src/History.scss +8 -4
- package/templates/history-page/src/index.tsx +141 -112
- package/translations/en/common.json +4 -2
- package/translations/et/common.json +4 -2
- package/ui-components/Card/index.tsx +3 -1
- package/ui-components/ClearFiltersButton/index.tsx +24 -0
- package/ui-components/FormElements/FormSelect/FormMultiselect.tsx +4 -1
- package/ui-components/index.tsx +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ All changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## Template [MajorVersion.MediterraneanVersion.MinorVersion] - DD-MM-YYYY
|
|
6
6
|
|
|
7
|
+
## [0.0.53] - 06.05.2026
|
|
8
|
+
|
|
9
|
+
- Removed the Chosen CSA filter from chat history.
|
|
10
|
+
- Added Clear filters action for chat history filters.
|
|
11
|
+
- Added Choose all / Vali kõik option to the chosen columns filter.
|
|
12
|
+
- Persisted selected chat history columns in user preferences.
|
|
13
|
+
|
|
14
|
+
## [0.0.52] - 05.05.2026
|
|
15
|
+
|
|
16
|
+
- Updated loading logic
|
|
17
|
+
|
|
7
18
|
## [0.0.51] - 05.05.2026
|
|
8
19
|
|
|
9
20
|
- History page header alignment
|
package/package.json
CHANGED
|
@@ -3,10 +3,6 @@
|
|
|
3
3
|
@import 'src/styles/settings/variables/other';
|
|
4
4
|
@import 'src/styles/settings/variables/typography';
|
|
5
5
|
|
|
6
|
-
.input-wrapper {
|
|
7
|
-
width: 40%;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
6
|
.header-container {
|
|
11
7
|
align-items: center;
|
|
12
8
|
display: flex;
|
|
@@ -89,3 +85,11 @@
|
|
|
89
85
|
.spinner {
|
|
90
86
|
height: 24px;
|
|
91
87
|
}
|
|
88
|
+
|
|
89
|
+
.history-content {
|
|
90
|
+
&--loading {
|
|
91
|
+
opacity: 0.5;
|
|
92
|
+
pointer-events: none;
|
|
93
|
+
user-select: none;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {FC, PropsWithChildren, useEffect, useMemo, useRef, useState} from 'react';
|
|
2
2
|
import {useTranslation} from 'react-i18next';
|
|
3
3
|
import {useMutation} from '@tanstack/react-query';
|
|
4
4
|
import {ColumnPinningState, createColumnHelper, PaginationState, SortingState,} from '@tanstack/react-table';
|
|
5
5
|
import {endOfDay, format, formatISO, startOfDay} from "date-fns";
|
|
6
6
|
import {AxiosError} from 'axios';
|
|
7
7
|
import './History.scss';
|
|
8
|
-
import {MdOutlineRemoveRedEye} from 'react-icons/md';
|
|
8
|
+
import {MdOutlineRemoveRedEye } from 'react-icons/md';
|
|
9
9
|
import {CgSpinner} from 'react-icons/cg';
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
12
|
Button,
|
|
13
13
|
Card,
|
|
14
|
+
ClearFiltersButton,
|
|
14
15
|
DataTable,
|
|
15
16
|
Dialog,
|
|
16
17
|
Drawer,
|
|
@@ -61,6 +62,8 @@ type ExportResult = {
|
|
|
61
62
|
chatIds: string[];
|
|
62
63
|
};
|
|
63
64
|
|
|
65
|
+
const ALL_COLUMNS_VALUE = '__all__';
|
|
66
|
+
|
|
64
67
|
const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
65
68
|
user,
|
|
66
69
|
userDomains,
|
|
@@ -86,8 +89,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
86
89
|
const passedStartDate = delegatedStartDate ?? params.get("start");
|
|
87
90
|
const passedEndDate = delegatedEndDate ?? params.get("end");
|
|
88
91
|
const skipNextSelectedColumnsEffect = useRef(false);
|
|
89
|
-
const passedCustomerSupportIds = params.getAll('customerSupportIds');
|
|
90
|
-
const [search, setSearch] = useState('');
|
|
91
92
|
const [selectedChat, setSelectedChat] = useState<ChatType | null>(null);
|
|
92
93
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
93
94
|
const [statusChangeModal, setStatusChangeModal] = useState<string | null>(
|
|
@@ -114,7 +115,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
114
115
|
|
|
115
116
|
const [messagesTrigger, setMessagesTrigger] = useState(false);
|
|
116
117
|
const [selectedColumns, setSelectedColumns] = useState<string[]>([]);
|
|
117
|
-
const [customerSupportAgents, setCustomerSupportAgents] = useState<any[]>([]);
|
|
118
118
|
const [counterKey, setCounterKey] = useState<number>(0)
|
|
119
119
|
|
|
120
120
|
const useStore = userDomains;
|
|
@@ -126,6 +126,8 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
126
126
|
const showTest = envVal === undefined ? true : envVal.toLowerCase() === 'true';
|
|
127
127
|
const [loading, setLoading] = useState(false);
|
|
128
128
|
const abortRef = useRef<AbortController | null>(null);
|
|
129
|
+
const loadingTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
130
|
+
const timeoutAbortRef = useRef(false);
|
|
129
131
|
|
|
130
132
|
const parseDateParam = (dateString: string | null) => {
|
|
131
133
|
if (!dateString) return new Date();
|
|
@@ -135,13 +137,16 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
135
137
|
const { control, setValue, watch } = useForm<{
|
|
136
138
|
startDate: Date | string;
|
|
137
139
|
endDate: Date | string;
|
|
140
|
+
search: string;
|
|
138
141
|
}>({
|
|
139
142
|
defaultValues: {
|
|
140
143
|
startDate: passedStartDate ? parseDateParam(passedStartDate) : startOfDay(new Date()),
|
|
141
144
|
endDate: passedEndDate ? parseDateParam(passedEndDate) : endOfDay(new Date()),
|
|
145
|
+
search: '',
|
|
142
146
|
},
|
|
143
147
|
});
|
|
144
148
|
|
|
149
|
+
const search = watch('search');
|
|
145
150
|
const startDate = watch('startDate');
|
|
146
151
|
const endDate = watch('endDate');
|
|
147
152
|
|
|
@@ -149,7 +154,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
149
154
|
getAllEndedChats.mutate({
|
|
150
155
|
startDate: formatISO(startOfDay(new Date(startDate))),
|
|
151
156
|
endDate: formatISO(endOfDay(new Date(endDate))),
|
|
152
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
153
157
|
pagination,
|
|
154
158
|
sorting,
|
|
155
159
|
search,
|
|
@@ -196,7 +200,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
196
200
|
getAllEndedChats.mutate({
|
|
197
201
|
startDate: hasStart ? unifyDateFromat(delegatedStartDate) : formatISO(startOfDay(new Date(startDate))),
|
|
198
202
|
endDate: hasEnd ? unifyDateFromat(delegatedEndDate) : formatISO(endOfDay(new Date(endDate))),
|
|
199
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
200
203
|
pagination,
|
|
201
204
|
sorting,
|
|
202
205
|
search,
|
|
@@ -227,13 +230,12 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
227
230
|
}
|
|
228
231
|
|
|
229
232
|
skipNextSelectedColumnsEffect.current = true;
|
|
230
|
-
setSelectedColumns(newSelectedColumns);
|
|
233
|
+
setSelectedColumns(getUiSelectedColumns(newSelectedColumns));
|
|
231
234
|
setCounterKey(prev => prev + 1);
|
|
232
235
|
|
|
233
236
|
getAllEndedChats.mutate({
|
|
234
237
|
startDate: formatISO(startOfDay(new Date(startDate))),
|
|
235
238
|
endDate: formatISO(endOfDay(new Date(endDate))),
|
|
236
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
237
239
|
pagination: updatedPagination,
|
|
238
240
|
sorting,
|
|
239
241
|
search,
|
|
@@ -262,7 +264,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
262
264
|
getAllEndedChats.mutate({
|
|
263
265
|
startDate: formatISO(startOfDay(new Date(startDate))),
|
|
264
266
|
endDate: formatISO(endOfDay(new Date(endDate))),
|
|
265
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
266
267
|
pagination,
|
|
267
268
|
sorting,
|
|
268
269
|
search,
|
|
@@ -270,10 +271,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
270
271
|
}
|
|
271
272
|
}, [selectedColumns, currentDomains]);
|
|
272
273
|
|
|
273
|
-
useEffect(() => {
|
|
274
|
-
listCustomerSupportAgents.mutate();
|
|
275
|
-
}, []);
|
|
276
|
-
|
|
277
274
|
const updatePagePreferences = useMutation({
|
|
278
275
|
mutationFn: (data: {
|
|
279
276
|
page_results: number;
|
|
@@ -292,7 +289,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
292
289
|
mutationFn: (data: {
|
|
293
290
|
startDate: string;
|
|
294
291
|
endDate: string;
|
|
295
|
-
customerSupportIds: string[];
|
|
296
292
|
pagination: PaginationState;
|
|
297
293
|
sorting: SortingState;
|
|
298
294
|
search: string;
|
|
@@ -307,7 +303,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
307
303
|
}
|
|
308
304
|
|
|
309
305
|
return apiDevEnded.post('agents/chats/ended', {
|
|
310
|
-
customerSupportIds: data.customerSupportIds,
|
|
311
306
|
startDate: formatISO(startOfDay(new Date(data.startDate))),
|
|
312
307
|
endDate: formatISO(endOfDay(new Date(data.endDate))),
|
|
313
308
|
urls: getDomainsArray(currentDomains),
|
|
@@ -334,8 +329,32 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
334
329
|
setTotalPages(res?.data?.response[0]?.totalPages ?? 1);
|
|
335
330
|
setTotalCount(res?.data?.response[0]?.totalCount ?? null);
|
|
336
331
|
},
|
|
332
|
+
onError: (error: AxiosError) => {
|
|
333
|
+
if (error.code === 'ERR_CANCELED' && !timeoutAbortRef.current) return;
|
|
334
|
+
timeoutAbortRef.current = false;
|
|
335
|
+
toast?.open({
|
|
336
|
+
type: 'error',
|
|
337
|
+
title: t('global.notificationError'),
|
|
338
|
+
message: 'Veateade',
|
|
339
|
+
});
|
|
340
|
+
},
|
|
337
341
|
});
|
|
338
342
|
|
|
343
|
+
useEffect(() => {
|
|
344
|
+
if (getAllEndedChats.isPending) {
|
|
345
|
+
loadingTimeoutRef.current = setTimeout(() => {
|
|
346
|
+
timeoutAbortRef.current = true;
|
|
347
|
+
abortRef.current?.abort();
|
|
348
|
+
}, 10000);
|
|
349
|
+
} else if (loadingTimeoutRef.current) {
|
|
350
|
+
clearTimeout(loadingTimeoutRef.current);
|
|
351
|
+
loadingTimeoutRef.current = null;
|
|
352
|
+
}
|
|
353
|
+
return () => {
|
|
354
|
+
if (loadingTimeoutRef.current) clearTimeout(loadingTimeoutRef.current);
|
|
355
|
+
};
|
|
356
|
+
}, [getAllEndedChats.isPending]);
|
|
357
|
+
|
|
339
358
|
const getChatById = useMutation({
|
|
340
359
|
mutationFn: () =>
|
|
341
360
|
apiDev.post('chats/get', {
|
|
@@ -347,27 +366,7 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
347
366
|
},
|
|
348
367
|
});
|
|
349
368
|
|
|
350
|
-
const
|
|
351
|
-
mutationFn: () =>
|
|
352
|
-
apiDev.post('accounts/customer-support-agents', {
|
|
353
|
-
page: 0,
|
|
354
|
-
page_size: 99999,
|
|
355
|
-
sorting: 'name asc',
|
|
356
|
-
show_active_only: false,
|
|
357
|
-
roles: ['ROLE_CUSTOMER_SUPPORT_AGENT'],
|
|
358
|
-
}),
|
|
359
|
-
onSuccess: (res: any) => {
|
|
360
|
-
setCustomerSupportAgents([
|
|
361
|
-
{label: 'Bürokratt', value: 'chatbot'},
|
|
362
|
-
...res.data.response.map((item) => ({
|
|
363
|
-
label: [item.firstName, item.lastName].join(' ').trim(),
|
|
364
|
-
value: item.idCode,
|
|
365
|
-
})),
|
|
366
|
-
]);
|
|
367
|
-
},
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
const visibleColumnOptions = useMemo(() => {
|
|
369
|
+
const realColumnOptions: {readonly label: string; readonly value: string}[] = useMemo(() => {
|
|
371
370
|
const columns = [
|
|
372
371
|
{label: t('chat.history.startTime'), value: 'created'},
|
|
373
372
|
{label: t('chat.history.endTime'), value: 'ended'},
|
|
@@ -396,6 +395,49 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
396
395
|
return columns;
|
|
397
396
|
}, [t, showEmail, testMessageEnabled])
|
|
398
397
|
|
|
398
|
+
const visibleColumnOptions = useMemo(() => [
|
|
399
|
+
{label: t('chat.history.chooseAll'), value: ALL_COLUMNS_VALUE},
|
|
400
|
+
...realColumnOptions,
|
|
401
|
+
], [t, realColumnOptions]);
|
|
402
|
+
|
|
403
|
+
const getRealSelectedColumns = (columns: string[]) =>
|
|
404
|
+
columns.filter((column) => column !== ALL_COLUMNS_VALUE);
|
|
405
|
+
|
|
406
|
+
const getAllColumnValues = () => realColumnOptions.map((option) => option.value);
|
|
407
|
+
|
|
408
|
+
const areAllColumnsSelected = (columns: string[]) => {
|
|
409
|
+
const realSelectedColumns = getRealSelectedColumns(columns);
|
|
410
|
+
const allColumnValues = getAllColumnValues();
|
|
411
|
+
|
|
412
|
+
return allColumnValues.length > 0 &&
|
|
413
|
+
allColumnValues.every((column) => realSelectedColumns.includes(column));
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
const getUiSelectedColumns = (columns: string[]) => {
|
|
417
|
+
const realSelectedColumns = getRealSelectedColumns(columns);
|
|
418
|
+
|
|
419
|
+
if (areAllColumnsSelected(realSelectedColumns)) {
|
|
420
|
+
return [ALL_COLUMNS_VALUE, ...getAllColumnValues()];
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return realSelectedColumns;
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
const normalizeSelectedColumns = (selection: string[]) => {
|
|
427
|
+
const currentAllSelected = selectedColumns.includes(ALL_COLUMNS_VALUE) || areAllColumnsSelected(selectedColumns);
|
|
428
|
+
const nextAllSelected = selection.includes(ALL_COLUMNS_VALUE);
|
|
429
|
+
|
|
430
|
+
if (nextAllSelected && !currentAllSelected) {
|
|
431
|
+
return [ALL_COLUMNS_VALUE, ...getAllColumnValues()];
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
if (!nextAllSelected && currentAllSelected) {
|
|
435
|
+
return [];
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
return getUiSelectedColumns(selection);
|
|
439
|
+
};
|
|
440
|
+
|
|
399
441
|
const chatStatusChangeMutation = useMutation({
|
|
400
442
|
mutationFn: async (data: { chatId: string | number; event: string }) => {
|
|
401
443
|
const changeableTo = [
|
|
@@ -430,7 +472,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
430
472
|
getAllEndedChats.mutate({
|
|
431
473
|
startDate: formatISO(startOfDay(new Date(startDate))),
|
|
432
474
|
endDate: formatISO(endOfDay(new Date(endDate))),
|
|
433
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
434
475
|
pagination,
|
|
435
476
|
sorting,
|
|
436
477
|
search,
|
|
@@ -898,9 +939,11 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
898
939
|
};
|
|
899
940
|
|
|
900
941
|
const getFilteredColumns = () => {
|
|
901
|
-
|
|
942
|
+
const realSelectedColumns = getRealSelectedColumns(selectedColumns);
|
|
943
|
+
|
|
944
|
+
if (realSelectedColumns.length === 0) return endedChatsColumns;
|
|
902
945
|
return endedChatsColumns.filter((c) =>
|
|
903
|
-
['detail', 'forward', ...
|
|
946
|
+
['detail', 'forward', ...realSelectedColumns].includes(c.id ?? '')
|
|
904
947
|
);
|
|
905
948
|
};
|
|
906
949
|
|
|
@@ -927,10 +970,11 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
927
970
|
selectedColumns: string[],
|
|
928
971
|
t: (key: string) => string
|
|
929
972
|
): ExportResult => {
|
|
973
|
+
const realSelectedColumns = getRealSelectedColumns(selectedColumns);
|
|
930
974
|
const activeColumns =
|
|
931
|
-
|
|
975
|
+
realSelectedColumns.length > 0
|
|
932
976
|
? allColumns.filter(
|
|
933
|
-
(col) => col.id && col.id !== 'detail' &&
|
|
977
|
+
(col) => col.id && col.id !== 'detail' && realSelectedColumns.includes(col.id)
|
|
934
978
|
)
|
|
935
979
|
: allColumns.filter((col) => col.id && col.id !== 'detail');
|
|
936
980
|
|
|
@@ -1000,9 +1044,10 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1000
1044
|
sortBy = `${sorting[0].id} ${sortType}`;
|
|
1001
1045
|
}
|
|
1002
1046
|
|
|
1003
|
-
const
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1047
|
+
const realSelectedColumns = getRealSelectedColumns(selectedColumns);
|
|
1048
|
+
const { headers } = mapChatsToExportRows([], endedChatsColumns, realSelectedColumns, t);
|
|
1049
|
+
const activeColumns = realSelectedColumns.length > 0
|
|
1050
|
+
? endedChatsColumns.filter((col) => col.id && col.id !== 'detail' && realSelectedColumns.includes(col.id))
|
|
1006
1051
|
: endedChatsColumns.filter((col) => col.id && col.id !== 'detail');
|
|
1007
1052
|
const columnIds = activeColumns.map((col) => col.id!);
|
|
1008
1053
|
|
|
@@ -1015,7 +1060,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1015
1060
|
urls: getDomainsArray(currentDomains),
|
|
1016
1061
|
sorting: sortBy,
|
|
1017
1062
|
search,
|
|
1018
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
1019
1063
|
});
|
|
1020
1064
|
|
|
1021
1065
|
const downloadData = response.data.data ?? response.data;
|
|
@@ -1034,6 +1078,21 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1034
1078
|
|
|
1035
1079
|
const endUserFullName = getUserName();
|
|
1036
1080
|
|
|
1081
|
+
const isClearFiltersVisible = useMemo(()=> {
|
|
1082
|
+
return search.length > 0 || selectedColumns.length > 0;
|
|
1083
|
+
}, [search, selectedColumns]);
|
|
1084
|
+
|
|
1085
|
+
const onClearFilersClick = () => {
|
|
1086
|
+
const clearedColumns: string[] = [];
|
|
1087
|
+
setSelectedColumns(clearedColumns);
|
|
1088
|
+
setCounterKey(0);
|
|
1089
|
+
setValue('search', '');
|
|
1090
|
+
updatePagePreferences.mutate({
|
|
1091
|
+
page_results: pagination.pageSize,
|
|
1092
|
+
selected_columns: clearedColumns
|
|
1093
|
+
});
|
|
1094
|
+
};
|
|
1095
|
+
|
|
1037
1096
|
if (!filteredEndedChatsList) return <>Loading... {{filteredEndedChatsList}} something is wrong </>;
|
|
1038
1097
|
|
|
1039
1098
|
return (
|
|
@@ -1059,27 +1118,30 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1059
1118
|
)}
|
|
1060
1119
|
</div>
|
|
1061
1120
|
|
|
1062
|
-
<
|
|
1121
|
+
<div className={`history-content${getAllEndedChats.isPending ? ' history-content--loading' : ''}`}>
|
|
1122
|
+
<Card style={{marginBottom: '16px'}}>
|
|
1063
1123
|
<Track gap={16}>
|
|
1064
1124
|
{displaySearchBar && (
|
|
1065
|
-
<
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1125
|
+
<Controller name="search" control={control} render={({ field }) => {
|
|
1126
|
+
return <FormInput
|
|
1127
|
+
label={t('chat.history.searchChats')}
|
|
1128
|
+
hideLabel
|
|
1129
|
+
name="searchChats"
|
|
1130
|
+
value={field.value}
|
|
1131
|
+
placeholder={t('chat.history.searchChats') + '...'}
|
|
1132
|
+
onChange={(e) => {
|
|
1133
|
+
setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
|
|
1134
|
+
setSearchParams((params) => {
|
|
1135
|
+
params.set("page", "1");
|
|
1136
|
+
return params;
|
|
1137
|
+
});
|
|
1138
|
+
field.onChange(e.target.value);
|
|
1139
|
+
debouncedGetAllEnded(e.target.value);
|
|
1140
|
+
}}
|
|
1141
|
+
/>
|
|
1142
|
+
}} />
|
|
1143
|
+
)}
|
|
1144
|
+
<Track gap={16}>
|
|
1083
1145
|
{displayDateFilter && (
|
|
1084
1146
|
<>
|
|
1085
1147
|
<Track gap={10}>
|
|
@@ -1106,7 +1168,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1106
1168
|
getAllEndedChats.mutate({
|
|
1107
1169
|
startDate: start,
|
|
1108
1170
|
endDate: formatISO(endOfDay(new Date(endDate))),
|
|
1109
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
1110
1171
|
pagination: resetPagination,
|
|
1111
1172
|
sorting,
|
|
1112
1173
|
search,
|
|
@@ -1141,7 +1202,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1141
1202
|
getAllEndedChats.mutate({
|
|
1142
1203
|
startDate: formatISO(startOfDay(new Date(startDate))),
|
|
1143
1204
|
endDate: end,
|
|
1144
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
1145
1205
|
pagination: resetPagination,
|
|
1146
1206
|
sorting,
|
|
1147
1207
|
search,
|
|
@@ -1154,6 +1214,7 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1154
1214
|
</Track>
|
|
1155
1215
|
</>
|
|
1156
1216
|
)}
|
|
1217
|
+
<Track style={{width: '240px'}}>
|
|
1157
1218
|
<FormMultiselect
|
|
1158
1219
|
key={counterKey}
|
|
1159
1220
|
name="visibleColumns"
|
|
@@ -1163,54 +1224,18 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1163
1224
|
selectedOptions={visibleColumnOptions.filter((o) =>
|
|
1164
1225
|
selectedColumns.includes(o.value)
|
|
1165
1226
|
)}
|
|
1227
|
+
selectedOptionsCount={getRealSelectedColumns(selectedColumns).length}
|
|
1166
1228
|
onSelectionChange={(selection) => {
|
|
1167
|
-
const columns = selection?.map((s) => s.value) ?? [];
|
|
1229
|
+
const columns = normalizeSelectedColumns(selection?.map((s) => s.value) ?? []);
|
|
1168
1230
|
setSelectedColumns(columns);
|
|
1231
|
+
setCounterKey(prev => prev + 1);
|
|
1169
1232
|
updatePagePreferences.mutate({
|
|
1170
1233
|
page_results: pagination.pageSize,
|
|
1171
|
-
selected_columns: columns
|
|
1234
|
+
selected_columns: getRealSelectedColumns(columns)
|
|
1172
1235
|
})
|
|
1173
1236
|
}}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
name="agent"
|
|
1177
|
-
label={t('')}
|
|
1178
|
-
placeholder={t('chat.history.chosenCsa')}
|
|
1179
|
-
options={customerSupportAgents}
|
|
1180
|
-
selectedOptions={customerSupportAgents.filter((item) =>
|
|
1181
|
-
passedCustomerSupportIds.includes(item.value)
|
|
1182
|
-
)}
|
|
1183
|
-
onSelectionChange={(selection) => {
|
|
1184
|
-
setSearchParams((params) => {
|
|
1185
|
-
params.delete('customerSupportIds');
|
|
1186
|
-
params.set('page', '1');
|
|
1187
|
-
selection?.forEach((s) => {
|
|
1188
|
-
params.append("customerSupportIds", s.value);
|
|
1189
|
-
if (s.value === "chatbot") params.append("customerSupportIds", "-");
|
|
1190
|
-
return params;
|
|
1191
|
-
});
|
|
1192
|
-
return params;
|
|
1193
|
-
});
|
|
1194
|
-
|
|
1195
|
-
setPagination({pageIndex: 0, pageSize: pagination.pageSize});
|
|
1196
|
-
|
|
1197
|
-
const customerSupportIds =
|
|
1198
|
-
selection?.reduce((acc, s) => {
|
|
1199
|
-
acc.push(s.value);
|
|
1200
|
-
if (s.value === "chatbot") acc.push("-");
|
|
1201
|
-
return acc;
|
|
1202
|
-
}, []) || [];
|
|
1203
|
-
|
|
1204
|
-
getAllEndedChats.mutate({
|
|
1205
|
-
startDate,
|
|
1206
|
-
endDate,
|
|
1207
|
-
customerSupportIds: customerSupportIds,
|
|
1208
|
-
pagination: {pageIndex: 0, pageSize: pagination.pageSize},
|
|
1209
|
-
sorting,
|
|
1210
|
-
search,
|
|
1211
|
-
});
|
|
1212
|
-
}}
|
|
1213
|
-
/>
|
|
1237
|
+
/>
|
|
1238
|
+
</Track>
|
|
1214
1239
|
</Track>
|
|
1215
1240
|
</Track>
|
|
1216
1241
|
</Card>
|
|
@@ -1222,6 +1247,11 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1222
1247
|
</Button>
|
|
1223
1248
|
</div>)
|
|
1224
1249
|
}
|
|
1250
|
+
{isClearFiltersVisible && (
|
|
1251
|
+
<Track justify="between" style={{ marginBottom: '16px' }}>
|
|
1252
|
+
<ClearFiltersButton style={{ marginLeft: 'auto' }} onClick={onClearFilersClick} />
|
|
1253
|
+
</Track>
|
|
1254
|
+
)}
|
|
1225
1255
|
<div className="card-drawer-container" style={{height: '100%', overflow: 'auto'}}>
|
|
1226
1256
|
<div className="card-wrapper">
|
|
1227
1257
|
<Card>
|
|
@@ -1242,12 +1272,11 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1242
1272
|
setPagination(state);
|
|
1243
1273
|
updatePagePreferences.mutate({
|
|
1244
1274
|
page_results: state.pageSize,
|
|
1245
|
-
selected_columns: selectedColumns
|
|
1275
|
+
selected_columns: getRealSelectedColumns(selectedColumns)
|
|
1246
1276
|
});
|
|
1247
1277
|
getAllEndedChats.mutate({
|
|
1248
1278
|
startDate: formatISO(startOfDay(new Date(startDate))),
|
|
1249
1279
|
endDate: formatISO(endOfDay(new Date(endDate))),
|
|
1250
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
1251
1280
|
pagination: state,
|
|
1252
1281
|
sorting,
|
|
1253
1282
|
search,
|
|
@@ -1258,7 +1287,6 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1258
1287
|
getAllEndedChats.mutate({
|
|
1259
1288
|
startDate: formatISO(startOfDay(new Date(startDate))),
|
|
1260
1289
|
endDate: formatISO(endOfDay(new Date(endDate))),
|
|
1261
|
-
customerSupportIds: passedCustomerSupportIds,
|
|
1262
1290
|
pagination,
|
|
1263
1291
|
sorting: state,
|
|
1264
1292
|
search,
|
|
@@ -1433,6 +1461,7 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
|
|
|
1433
1461
|
</>
|
|
1434
1462
|
)}
|
|
1435
1463
|
</div>
|
|
1464
|
+
</div>
|
|
1436
1465
|
|
|
1437
1466
|
{statusChangeModal && (
|
|
1438
1467
|
<Dialog
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
"today": "Today",
|
|
46
46
|
"forward": "Forward",
|
|
47
47
|
"chosen": "Chosen",
|
|
48
|
-
"read": "Read"
|
|
48
|
+
"read": "Read",
|
|
49
|
+
"clearFilters": "Clear filters"
|
|
49
50
|
},
|
|
50
51
|
"sorting": {
|
|
51
52
|
"des": "descending",
|
|
@@ -175,7 +176,8 @@
|
|
|
175
176
|
"statusAdder": "Status adder",
|
|
176
177
|
"statusAddedDate": "Status added date",
|
|
177
178
|
"chosenCsa": "Chosen csa(s)",
|
|
178
|
-
"chosenColumn": "Chosen column(s)"
|
|
179
|
+
"chosenColumn": "Chosen column(s)",
|
|
180
|
+
"chooseAll": "Choose all"
|
|
179
181
|
},
|
|
180
182
|
"plainEvents": {
|
|
181
183
|
"answered": "Answered",
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
"today": "Täna",
|
|
46
46
|
"forward": "Suuna",
|
|
47
47
|
"chosen": "Valitud",
|
|
48
|
-
"read": "Loetud"
|
|
48
|
+
"read": "Loetud",
|
|
49
|
+
"clearFilters": "Tühjenda filtrid"
|
|
49
50
|
},
|
|
50
51
|
"sorting": {
|
|
51
52
|
"des": "kahanevalt",
|
|
@@ -175,7 +176,8 @@
|
|
|
175
176
|
"statusAdder": "Staatuse lisaja",
|
|
176
177
|
"statusAddedDate": "Staatuse lisamise kuupäev",
|
|
177
178
|
"chosenCsa": "Valitud nõustaja(d)",
|
|
178
|
-
"chosenColumn": "Valitud tulba(d)"
|
|
179
|
+
"chosenColumn": "Valitud tulba(d)",
|
|
180
|
+
"chooseAll": "Vali kõik"
|
|
179
181
|
},
|
|
180
182
|
"plainEvents": {
|
|
181
183
|
"answered": "Vastatud",
|
|
@@ -10,6 +10,7 @@ type CardProps = {
|
|
|
10
10
|
isHeaderLight?: boolean;
|
|
11
11
|
isBodyDivided?: boolean;
|
|
12
12
|
isScrollable?: boolean;
|
|
13
|
+
style?: React.CSSProperties;
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
const Card: FC<PropsWithChildren<CardProps>> = ({
|
|
@@ -19,10 +20,11 @@ const Card: FC<PropsWithChildren<CardProps>> = ({
|
|
|
19
20
|
isHeaderLight,
|
|
20
21
|
isBodyDivided,
|
|
21
22
|
isScrollable = false,
|
|
23
|
+
style,
|
|
22
24
|
children,
|
|
23
25
|
}) => {
|
|
24
26
|
return (
|
|
25
|
-
<div className={clsx('card', { 'card--borderless': borderless, 'card--scrollable': isScrollable })}>
|
|
27
|
+
<div className={clsx('card', { 'card--borderless': borderless, 'card--scrollable': isScrollable })} style={style}>
|
|
26
28
|
{header && (
|
|
27
29
|
<div className={`card__header ${isHeaderLight ? 'white' : ''}`}>
|
|
28
30
|
{header}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Button } from "@buerokratt-ria/header/src/components";
|
|
2
|
+
import { ComponentProps, FC } from "react";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { MdFilterListOff } from "react-icons/md";
|
|
5
|
+
|
|
6
|
+
type ClearFiltersButtonProps = {
|
|
7
|
+
readonly onClick: () => void;
|
|
8
|
+
readonly style?: Pick<ComponentProps<typeof Button>, 'style'>['style'];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const ClearFiltersButton: FC<ClearFiltersButtonProps> = ({ onClick, style }) => {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
|
|
14
|
+
return <Button
|
|
15
|
+
appearance="primary"
|
|
16
|
+
size="s"
|
|
17
|
+
style={style}
|
|
18
|
+
onClick={onClick}>
|
|
19
|
+
{t('global.clearFilters')}
|
|
20
|
+
<MdFilterListOff style={{ height: '24px', width: '24px' }} />
|
|
21
|
+
</Button>
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default ClearFiltersButton;
|
|
@@ -16,6 +16,7 @@ type FormMultiselectProps = SelectHTMLAttributes<HTMLSelectElement> & {
|
|
|
16
16
|
hideLabel?: boolean;
|
|
17
17
|
options: SelectOption[];
|
|
18
18
|
selectedOptions?: SelectOption[];
|
|
19
|
+
selectedOptionsCount?: number;
|
|
19
20
|
onSelectionChange?: (selection: SelectOption[] | null) => void;
|
|
20
21
|
};
|
|
21
22
|
|
|
@@ -28,6 +29,7 @@ const FormMultiselect: FC<FormMultiselectProps> = (
|
|
|
28
29
|
placeholder,
|
|
29
30
|
defaultValue,
|
|
30
31
|
selectedOptions,
|
|
32
|
+
selectedOptionsCount,
|
|
31
33
|
onSelectionChange,
|
|
32
34
|
...rest
|
|
33
35
|
},
|
|
@@ -84,13 +86,14 @@ const FormMultiselect: FC<FormMultiselectProps> = (
|
|
|
84
86
|
);
|
|
85
87
|
|
|
86
88
|
const placeholderValue = placeholder || t('global.choose');
|
|
89
|
+
const displaySelectedCount = selectedOptionsCount ?? selectedItems.length;
|
|
87
90
|
|
|
88
91
|
return (
|
|
89
92
|
<div className={selectClasses} style={rest.style}>
|
|
90
93
|
{label && !hideLabel && <label htmlFor={id} className='select__label' {...getLabelProps()}>{label}</label>}
|
|
91
94
|
<div className='select__wrapper'>
|
|
92
95
|
<div className='select__trigger' {...getToggleButtonProps()}>
|
|
93
|
-
{selectedItems.length > 0 ? `${placeholder ?? t('global.chosen')} (${
|
|
96
|
+
{selectedItems.length > 0 ? `${placeholder ?? t('global.chosen')} (${displaySelectedCount})` : placeholderValue}
|
|
94
97
|
<Icon label='Dropdown icon' size='medium' icon={<MdArrowDropDown color='#5D6071' />} />
|
|
95
98
|
</div>
|
|
96
99
|
|
package/ui-components/index.tsx
CHANGED
|
@@ -24,6 +24,7 @@ import Drawer from './Drawer';
|
|
|
24
24
|
import HistoricalChat from './HistoricalChat';
|
|
25
25
|
import Dialog from './Dialog';
|
|
26
26
|
import Label from './Label';
|
|
27
|
+
import ClearFiltersButton from './ClearFiltersButton';
|
|
27
28
|
|
|
28
29
|
export {
|
|
29
30
|
Button,
|
|
@@ -49,5 +50,6 @@ export {
|
|
|
49
50
|
HistoricalChat,
|
|
50
51
|
Dialog,
|
|
51
52
|
Toast,
|
|
52
|
-
Label
|
|
53
|
+
Label,
|
|
54
|
+
ClearFiltersButton,
|
|
53
55
|
};
|