diff --git a/GUI/.env.development b/GUI/.env.development index a27157cb..ef8da7d1 100644 --- a/GUI/.env.development +++ b/GUI/.env.development @@ -28,4 +28,4 @@ REACT_APP_SHOW_TEST_CONVERSATIONS=true REACT_APP_SHOW_TEST_MESSAGE=false REACT_APP_VALIDATIONS_ENABLED=FALSE REACT_APP_CURRENT_VERSION=Version 1.0.0 -REACT_APP_MENU_JSON=[{"id":"conversations","label":{"et":"Vestlused","en":"Conversations"},"path":"/chat","children":[{"label":{"et":"Vastamata","en":"Unanswered"},"path":"/unanswered"},{"label":{"et":"Aktiivsed","en":"Active"},"path":"/active"},{"label":{"et":"Ootel","en":"Pending"},"path":"/pending"},{"label":{"et":"Ajalugu","en":"History"},"path":"/history"}]},{"id":"training","label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Teemad","en":"Themes"},"path":"/training/intents"},{"label":{"et":"Avalikud teemad","en":"Public themes"},"path":"/training/common-intents"},{"label":{"et":"Teemade järeltreenimine","en":"Post training themes"},"path":"/training/intents-followup-training"},{"label":{"et":"Vastused","en":"Answers"},"path":"/training/responses"},{"label":{"et":"Reeglid","en":"Rules"},"path":"/training/rules"},{"label":{"et":"Konfiguratsioon","en":"Configuration"},"path":"/training/configuration"},{"label":{"et":"Vormid","en":"Forms"},"path":"/training/forms"},{"label":{"et":"Mälukohad","en":"Slots"},"path":"/training/slots"}]},{"label":{"et":"Ajaloolised vestlused","en":"Historical conversations"},"path":"/history","children":[{"label":{"et":"Ajalugu","en":"History"},"path":"/history/history"},{"label":{"et":"Pöördumised","en":"Appeals"},"path":"/history/appeal"}]},{"label":{"et":"Mudelipank ja analüütika","en":"Modelbank and analytics"},"path":"/analytics","children":[{"label":{"et":"Teemade ülevaade","en":"Overview of topics"},"path":"/analytics/overview"},{"label":{"et":"Mudelite võrdlus","en":"Comparison of models"},"path":"/analytics/models"},{"label":{"et":"Testlood","en":"testTracks"},"path":"/analytics/testcases"}]},{"label":{"et":"Treeni uus mudel","en":"Train new model"},"path":"/train-new-model"}]},{"id":"analytics","label":{"et":"Analüütika","en":"Analytics"},"path":"/analytics","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Vestlused","en":"Chats"},"path":"/chats"},{"label":{"et":"Tagasiside","en":"Feedback"},"path":"/feedback"},{"label":{"et":"Nõustajad","en":"Advisors"},"path":"/advisors"},{"label":{"et":"Avaandmed","en":"Reports"},"path":"/reports"}]},{"id":"services","label":{"et":"Teenused","en":"Services"},"path":"/services","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Uus teenus","en":"New Service"},"path":"/newService"},{"label":{"et":"Probleemsed teenused","en":"Faulty Services"},"path":"/faultyServices"}]},{"id":"settings","label":{"et":"Haldus","en":"Administration"},"path":"/settings","children":[{"label":{"et":"Kasutajad","en":"Users"},"path":"/users"},{"label":{"et":"Vestlusbot","en":"Chatbot"},"path":"/chatbot","children":[{"label":{"et":"Seaded","en":"Settings"},"path":"/chatbot/settings"},{"label":{"et":"Tervitussõnum","en":"Welcome message"},"path":"/chatbot/welcome-message"},{"label":{"et":"Välimus ja käitumine","en":"Appearance and behavior"},"path":"/chatbot/appearance"},{"label":{"et":"Erakorralised teated","en":"Emergency notices"},"path":"/chatbot/emergency-notices"}]},{"label":{"et":"Vestluste analüüs","en":"Chat analysis"},"path":"/chat-analysis"},{"label":{"et":"Asutuse tööaeg","en":"Office opening hours"},"path":"/working-time"},{"label":{"et":"Sessiooni pikkus","en":"Session length"},"path":"/session-length"},{"hidden": false,"label":{"et":"Multidomeenid","en":"Multi-Domains"},"path":"/multi-domains"},{"label":{"et":"Anonümiseerija","en":"Anonymizer"},"path":"/anonymizer"}]},{"id":"monitoring","label":{"et":"Seire","en":"Monitoring"},"path":"/monitoring","children":[{"label":{"et":"Aktiivaeg","en":"Working hours"},"path":"/uptime"}]}] +REACT_APP_MENU_JSON=[{"id":"conversations","label":{"et":"Vestlused","en":"Conversations"},"path":"/chat","children":[{"label":{"et":"Vastamata","en":"Unanswered"},"path":"/unanswered"},{"label":{"et":"Aktiivsed","en":"Active"},"path":"/active"},{"label":{"et":"Ootel","en":"Pending"},"path":"/pending"},{"label":{"et":"Ajalugu","en":"History"},"path":"/history"}]},{"id":"training","label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Teemad","en":"Themes"},"path":"/training/intents"},{"label":{"et":"Avalikud teemad","en":"Public themes"},"path":"/training/common-intents"},{"label":{"et":"Teemade järeltreenimine","en":"Post training themes"},"path":"/training/intents-followup-training"},{"label":{"et":"Vastused","en":"Answers"},"path":"/training/responses"},{"label":{"et":"Reeglid","en":"Rules"},"path":"/training/rules"},{"label":{"et":"Konfiguratsioon","en":"Configuration"},"path":"/training/configuration"},{"label":{"et":"Vormid","en":"Forms"},"path":"/training/forms"},{"label":{"et":"Mälukohad","en":"Slots"},"path":"/training/slots"}]},{"label":{"et":"Ajaloolised vestlused","en":"Historical conversations"},"path":"/history","children":[{"label":{"et":"Ajalugu","en":"History"},"path":"/history/history"},{"label":{"et":"Pöördumised","en":"Appeals"},"path":"/history/appeal"}]},{"label":{"et":"Mudelipank ja analüütika","en":"Modelbank and analytics"},"path":"/analytics","children":[{"label":{"et":"Teemade ülevaade","en":"Overview of topics"},"path":"/analytics/overview"},{"label":{"et":"Mudelite võrdlus","en":"Comparison of models"},"path":"/analytics/models"},{"label":{"et":"Testlood","en":"testTracks"},"path":"/analytics/testcases"}]},{"label":{"et":"Treeni uus mudel","en":"Train new model"},"path":"/train-new-model"}]},{"id":"analytics","label":{"et":"Analüütika","en":"Analytics"},"path":"/analytics","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Vestlused","en":"Chats"},"path":"/chats"},{"label":{"et":"Tagasiside","en":"Feedback"},"path":"/feedback"},{"label":{"et":"Avaandmed","en":"Reports"},"path":"/reports"}]},{"id":"services","label":{"et":"Teenused","en":"Services"},"path":"/services","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Uus teenus","en":"New Service"},"path":"/newService"},{"label":{"et":"Probleemsed teenused","en":"Faulty Services"},"path":"/faultyServices"}]},{"id":"settings","label":{"et":"Haldus","en":"Administration"},"path":"/settings","children":[{"label":{"et":"Kasutajad","en":"Users"},"path":"/users"},{"label":{"et":"Vestlusbot","en":"Chatbot"},"path":"/chatbot","children":[{"label":{"et":"Seaded","en":"Settings"},"path":"/chatbot/settings"},{"label":{"et":"Tervitussõnum","en":"Welcome message"},"path":"/chatbot/welcome-message"},{"label":{"et":"Välimus ja käitumine","en":"Appearance and behavior"},"path":"/chatbot/appearance"},{"label":{"et":"Erakorralised teated","en":"Emergency notices"},"path":"/chatbot/emergency-notices"}]},{"label":{"et":"Vestluste analüüs","en":"Chat analysis"},"path":"/chat-analysis"},{"label":{"et":"Asutuse tööaeg","en":"Office opening hours"},"path":"/working-time"},{"label":{"et":"Sessiooni pikkus","en":"Session length"},"path":"/session-length"},{"hidden": false,"label":{"et":"Multidomeenid","en":"Multi-Domains"},"path":"/multi-domains"},{"label":{"et":"Anonümiseerija","en":"Anonymizer"},"path":"/anonymizer"}]},{"id":"monitoring","label":{"et":"Seire","en":"Monitoring"},"path":"/monitoring","children":[{"label":{"et":"Aktiivaeg","en":"Working hours"},"path":"/uptime"}]}] diff --git a/GUI/package.json b/GUI/package.json index 8501ed71..fc9ade53 100644 --- a/GUI/package.json +++ b/GUI/package.json @@ -5,7 +5,7 @@ "type": "module", "dependencies": { "@buerokratt-ria/header": "^0.1.52", - "@buerokratt-ria/menu": "^0.2.12", + "@buerokratt-ria/menu": "^0.2.13", "@buerokratt-ria/styles": "^0.0.1", "@buerokratt-ria/common-gui-components": "^0.0.59", "@fontsource/roboto": "^4.5.8", diff --git a/GUI/src/RootComponent.tsx b/GUI/src/RootComponent.tsx index 67ec218e..4bb90699 100644 --- a/GUI/src/RootComponent.tsx +++ b/GUI/src/RootComponent.tsx @@ -1,7 +1,6 @@ import React from 'react' import {Navigate, Route, Routes} from 'react-router-dom' import { Layout } from './components' -import AdvisorsPage from './pages/AdvisorsPage' import ChatsPage from './pages/ChatsPage' import FeedbackPage from './pages/FeedbackPage' import NotFoundPage from './pages/NotFoundPage' @@ -19,7 +18,6 @@ const RootComponent: React.FC = () => { } /> {/* } /> To be Added in release 2.1 or later */} } /> - } /> } /> } /> diff --git a/GUI/src/components/SideMenu/index.tsx b/GUI/src/components/SideMenu/index.tsx index 13884f31..75bdbe9e 100644 --- a/GUI/src/components/SideMenu/index.tsx +++ b/GUI/src/components/SideMenu/index.tsx @@ -9,7 +9,6 @@ const menuItems = [ { to: ROUTES.CHATS_ROUTE, titleKey: 'menu.chats' }, { to: ROUTES.BUROKRATT_ROUTE, titleKey: 'menu.burokratt' }, { to: ROUTES.FEEDBACK_ROUTE, titleKey: 'menu.feedback' }, - { to: ROUTES.ADVISORS_ROUTE, titleKey: 'menu.advisors' }, { to: ROUTES.REPORTS_ROUTE, titleKey: 'menu.reports' }, ] diff --git a/GUI/src/i18n/en/common.json b/GUI/src/i18n/en/common.json index e02413ed..272714f4 100644 --- a/GUI/src/i18n/en/common.json +++ b/GUI/src/i18n/en/common.json @@ -191,6 +191,16 @@ "allCsvAway": "All CSAs away with red status", "medianWaitingTime": "Median (min)", "averageWaitingTime": "Arithmetic (min)", + "chat_forwards": "Forwarding", + "forwards": { + "from_csa": "Number of conversations directed from the advisor", + "to_csa": "Counselor directed conversations", + "to_other": "Out-of-facility forwards" + }, + "avg_pick_time": "Average response speed in the institution", + "avg_present_csa": "Average presence of counselors", + "num_chats_csa": "Number of conversations by adviser", + "avg_chat_time_csa": "Conversation time by advisor", "theme_overview": "Theme overview", "follow_up_action_overview": "Follow-up Action overview", "quality_overview": "Quality overview", diff --git a/GUI/src/i18n/et/common.json b/GUI/src/i18n/et/common.json index e49b78bc..9272f45f 100644 --- a/GUI/src/i18n/et/common.json +++ b/GUI/src/i18n/et/common.json @@ -191,6 +191,16 @@ "allCsvAway": "Kõik nõustajad ära / hõivatud", "medianWaitingTime": "Mediaan (min)", "averageWaitingTime": "Aritmeetiline keskmine (min)", + "chat_forwards": "Suunamised", + "forwards": { + "from_csa": "Nõustajalt suunatud vestluste arv", + "to_csa": "Nõustajale suunatud vestluste arv", + "to_other": "Suunamised asutusest välja" + }, + "avg_pick_time": "Keskmine vastamise kiirus asutuses", + "avg_present_csa": "Keskmine nõustajate kohalolu", + "num_chats_csa": "Vestluste arv nõustaja lõikes", + "avg_chat_time_csa": "Vestluste aeg (min) nõustaja lõikes", "theme_overview": "Valdkonna ülevaade", "follow_up_action_overview": "Järeltegevuste staatuste ülevaade", "quality_overview": "Kvaliteedi ülevaade", diff --git a/GUI/src/pages/AdvisorsPage.tsx b/GUI/src/pages/AdvisorsPage.tsx deleted file mode 100644 index 242d072a..00000000 --- a/GUI/src/pages/AdvisorsPage.tsx +++ /dev/null @@ -1,388 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import OptionsPanel, { Option } from '../components/MetricAndPeriodOptions'; -import MetricsCharts from '../components/MetricsCharts'; -import { MetricOptionsState } from '../components/MetricAndPeriodOptions/types'; -import { - chartDataKey, - getAdvisorChartData, - getAdvisorsList, - translateChartKeys, -} from '../util/charts-utils'; -import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators'; -import {BehaviorSubject} from 'rxjs'; -import { - getAvgCsaPresent, - getAvgPickTime, - getChatForwards, - getCsaAvgChatTime, - getCsaChatsTotal, -} from '../resources/api-constants'; -import { Methods, request } from '../util/axios-client'; -import withAuthorization, { ROLES } from '../hoc/with-authorization'; -import { ChartData } from 'types/chart'; -import { usePeriodStatisticsContext } from 'hooks/usePeriodStatisticsContext'; -import useStore from "../store/user/store"; -import {getDomainsArray} from "../util/multiDomain-utils"; -import {getShowTestData} from "../util/testChat-utils"; -import { endOfDay, formatISO, startOfDay } from 'date-fns'; - -const AdvisorsPage: React.FC = () => { - const { t } = useTranslation(); - const [chartData, setChartData] = useState({ - chartData: [], - colors: [], - }); - const [currentMetric, setCurrentMetric] = useState(''); - const [currentConfigs, setCurrentConfigs] = useState(); - const [unit, setUnit] = useState(''); - const advisors = useRef([]); - const [advisorsList, setAdvisorsList] = useState([]); - const [showSelectAll, setShowSelectAll] = useState(false); - const [advisorsMetrics, setAdvisorsMetrics] = useState([ - { - id: 'chat_forwards', - labelKey: 'advisors.chat_forwards', - subOptions: [ - { id: 'receivedChats', labelKey: 'advisors.forwards.from_csa', color: '#FFB511' }, - { id: 'forwardedChats', labelKey: 'advisors.forwards.to_csa', color: '#ED7D31' }, - { id: 'forwardedExternally', labelKey: 'advisors.forwards.to_other', color: '#8BB4D5' }, - ], - unit: t('units.chats') ?? 'chats', - }, - { - id: 'avg_pick_time', - labelKey: 'advisors.avg_pick_time', - unit: t('units.minutes') ?? 'minutes', - }, - { - id: 'avg_present_csa', - labelKey: 'advisors.avg_present_csa', - unit: t('units.counselors') ?? 'counselors', - }, - { - id: 'num_chats_csa', - labelKey: 'advisors.num_chats_csa', - unit: t('units.chats') ?? 'chats', - }, - { - id: 'avg_chat_time_csa', - labelKey: 'advisors.avg_chat_time_csa', - unit: t('units.minutes') ?? 'minutes', - }, - ]); - const { setPeriodStatistics } = usePeriodStatisticsContext(); - const [updateKey, setUpdateKey] = useState(0) - const multiDomainEnabled = import.meta.env.REACT_APP_ENABLE_MULTI_DOMAIN?.toLowerCase() === 'true'; - - - useEffect(() => { - if (!multiDomainEnabled) return; - - const unsubscribe = useStore.subscribe((state, prevState) => { - if ( - JSON.stringify(state.userDomains) !== - JSON.stringify(prevState.userDomains) - ) { - setUpdateKey((v) => v + 1); - } - }); - - return () => unsubscribe(); - }, [multiDomainEnabled, useStore]); - - useEffect(() => { - setAdvisorsList(advisors.current); - }, [advisorsList]); - - useEffect(() => { - setPeriodStatistics(chartData, unit); - }, [chartData, unit]); - - useEffect(() => { - if (currentConfigs) { - configsSubject.next(currentConfigs); - } - }, [currentConfigs]); - - const [configsSubject] = useState( - () => new BehaviorSubject(null) - ); - - useEffect(() => { - const subscription = configsSubject - .pipe( - distinctUntilChanged(), - debounceTime(300), - switchMap((config: any) => { - switch (config.metric) { - case 'chat_forwards': - return fetchChatsForwards(config); - case 'avg_pick_time': - return fetchAverageChatPickUpTime(config); - case 'avg_present_csa': - return fetchAveragePresentCsas(config); - case 'num_chats_csa': - return fetchTotalCsaChats(config); - case 'avg_chat_time_csa': - return fetchAverageCsaChatTime(config); - default: - return fetchChatsForwards(config); - } - }) - ) - .subscribe((chartData: any) => setChartData(chartData)); - - return () => { - subscription.unsubscribe(); - }; - }, [updateKey]); - - const fetchChatsForwards = async (config: any) => { - let chartData = {}; - setShowSelectAll(false); - try { - const result: any = await request({ - url: getChatForwards(), - method: Methods.post, - withCredentials: true, - data: { - metric: config?.groupByPeriod ?? 'day', - start_date: config?.start, - end_date: config?.end, - urls: getDomainsArray(), - showTest: getShowTestData() - }, - }); - - const res = result.response.map((entry: any) => ({ - ...translateChartKeys(entry, chartDataKey), - [chartDataKey]: new Date(entry[chartDataKey]).getTime(), - })); - - const requiredKeys = [chartDataKey, ...config.options]; - - const response = res.map((item: any) => { - const returnValue: any = {}; - requiredKeys.forEach((key: string) => { - if (key !== chartDataKey) { - const chartKey = t(`chart.${key}`); - returnValue[chartKey] = item[chartKey]; - } else { - returnValue[key] = item[key]; - } - }); - - return returnValue; - }); - - chartData = { - chartData: response, - colors: advisorsMetrics[0].subOptions!.map(({ id, color }) => { - return { - id: t(`chart.${id}`), - color, - }; - }), - }; - } catch (_) { - console.error(_) - } - return chartData; - }; - - const fetchAverageChatPickUpTime = async (config: any) => { - setShowSelectAll(false); - let chartData = {}; - try { - const result: any = await request({ - url: getAvgPickTime(), - method: Methods.post, - withCredentials: true, - data: { - metric: config?.groupByPeriod ?? 'day', - start_date: config?.start, - end_date: config?.end, - urls: getDomainsArray(), - showTest: getShowTestData() - }, - }); - - const response = result.response.map((entry: any) => ({ - ...translateChartKeys(entry, chartDataKey), - [chartDataKey]: new Date(entry[chartDataKey]).getTime(), - })); - - chartData = { - chartData: response, - colors: [{ id: 'Average (Min)', color: '#FFB511' }], - minPointSize: 3, - }; - } catch (_) { - console.error(_) - } - return chartData; - }; - - const fetchAveragePresentCsas = async (config: any) => { - setShowSelectAll(false); - let chartData = {}; - try { - const result: any = await request({ - url: getAvgCsaPresent(), - method: Methods.post, - withCredentials: true, - data: { - metric: config?.groupByPeriod ?? 'day', - start_date: config?.start, - end_date: config?.end, - }, - }); - - const response = result.response.map((entry: any) => ({ - ...translateChartKeys(entry, chartDataKey), - [chartDataKey]: new Date(entry[chartDataKey]).getTime(), - })); - - chartData = { - chartData: response, - colors: [{ id: 'Average', color: '#FFB511' }], - minPointSize: 3, - }; - } catch (_) { - console.error(_) - } - return chartData; - }; - - const fetchTotalCsaChats = async (config: any) => { - setShowSelectAll(true); - let chartData = {}; - try { - const excluded_csas = advisors.current.map((e) => e.id).filter((e) => !config?.options.includes(e)); - const result: any = await request({ - url: getCsaChatsTotal(), - method: Methods.post, - withCredentials: true, - data: { - metric: config?.groupByPeriod ?? 'day', - start_date: config?.start, - end_date: config?.end, - excluded_csas: (excluded_csas.length ?? 0) > 0 ? excluded_csas : [''], - urls: getDomainsArray(), - showTest: getShowTestData() - }, - }); - - const res = result.response; - - const advisorsList = getAdvisorsList(res); - - const updatedMetrics = [...advisorsMetrics]; - updatedMetrics[3].subOptions = advisorsList; - advisors.current = advisorsList; - setAdvisorsMetrics(updatedMetrics); - setAdvisorsList(advisors.current); - - chartData = { - chartData: getAdvisorChartData(res, advisorsList,'chart.count'), - colors: advisorsMetrics[3].subOptions!.map(({ labelKey, color }) => { - return { - id: labelKey, - color, - }; - }), - }; - } catch (_) { - console.error(_) - } - return chartData; - }; - - const fetchAverageCsaChatTime = async (config: any) => { - setShowSelectAll(true); - let chartData = {}; - try { - const excluded_csas = advisors.current.map((e) => e.id).filter((e) => !config?.options.includes(e)); - const result: any = await request({ - url: getCsaAvgChatTime(), - method: Methods.post, - withCredentials: true, - data: { - metric: config?.groupByPeriod ?? 'day', - start_date: config?.start, - end_date: config?.end, - excluded_csas: (excluded_csas.length ?? 0) > 0 ? excluded_csas : [''], - urls: getDomainsArray(), - showTest: getShowTestData() - }, - }); - - const res = result.response; - - const advisorsList = getAdvisorsList(res); - - const updatedMetrics = [...advisorsMetrics]; - updatedMetrics[4].subOptions = advisorsList; - advisors.current = advisorsList; - setAdvisorsMetrics(updatedMetrics); - setAdvisorsList(advisors.current); - - chartData = { - chartData: getAdvisorChartData(res, advisorsList, 'chart.count'), - colors: advisorsMetrics[4].subOptions!.map(({ labelKey, color }) => { - return { - id: labelKey, - color, - }; - }), - minPointSize: 3, - }; - } catch (_) { - console.error(_) - } - return chartData; - }; - - const configsAreEqual = (a: MetricOptionsState, b: MetricOptionsState | undefined) => { - const { options: _, ...restA } = a ?? {}; - const { options: __, ...restB } = b ?? {}; - return JSON.stringify(restA) === JSON.stringify(restB); - }; - - return ( - <> -

{t('menu.advisors')}

- { - if (!configsAreEqual(config, currentConfigs)) { - setCurrentConfigs(config); - configsSubject.next(config); - if (currentMetric != `advisors.${config.metric}`) { - advisors.current = []; - } - setCurrentMetric(`advisors.${config.metric}`); - setAdvisorsList([]); - - const selectedOption = advisorsMetrics.find((x) => x.id === config.metric); - if (!selectedOption) return; - setUnit(selectedOption?.unit ?? 'chats'); - } - }} - /> - - - ); -}; - -export default withAuthorization(AdvisorsPage, [ROLES.ROLE_ADMINISTRATOR, ROLES.ROLE_ANALYST]); diff --git a/GUI/src/pages/ChatsPage/index.tsx b/GUI/src/pages/ChatsPage/index.tsx index be9b1202..addd5f4d 100644 --- a/GUI/src/pages/ChatsPage/index.tsx +++ b/GUI/src/pages/ChatsPage/index.tsx @@ -1,298 +1,547 @@ -import React, {useEffect, useRef, useState} from 'react'; -import {useTranslation} from 'react-i18next'; -import {type ObservableInput, Subject} from 'rxjs'; -import {debounceTime, distinctUntilChanged, switchMap} from 'rxjs/operators'; -import OptionsPanel, {Option} from '../../components/MetricAndPeriodOptions'; -import {MetricOptionsState} from '../../components/MetricAndPeriodOptions/types'; +import React, { useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { type ObservableInput, Subject } from 'rxjs'; +import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators'; +import OptionsPanel, { Option } from '../../components/MetricAndPeriodOptions'; +import { MetricOptionsState } from '../../components/MetricAndPeriodOptions/types'; import MetricsCharts from '../../components/MetricsCharts'; -import {chartDateFormat} from '../../util/charts-utils'; -import {randomColor} from '../../util/generateRandomColor'; -import {fetchData} from './data'; -import {chatOptions} from './options'; -import withAuthorization, {ROLES} from '../../hoc/with-authorization'; -import {ChartData} from 'types/chart'; -import {usePeriodStatisticsContext} from 'hooks/usePeriodStatisticsContext'; +import { + chartDataKey, + chartDateFormat, + getAdvisorChartData, + getAdvisorsList, + translateChartKeys, +} from '../../util/charts-utils'; +import { randomColor } from '../../util/generateRandomColor'; +import { fetchData } from './data'; +import { chatOptions } from './options'; +import withAuthorization, { ROLES } from '../../hoc/with-authorization'; +import { ChartData } from 'types/chart'; +import { usePeriodStatisticsContext } from 'hooks/usePeriodStatisticsContext'; import useStore from '../../store/user/store'; -import {endOfDay, formatISO, startOfDay} from 'date-fns'; -import {getFollowUpActionOverview, getQualityOverview, getThemeOverview} from '../../resources/api-constants'; -import {chartDataKey} from '../../util/charts-utils'; -import {Methods, request} from '../../util/axios-client'; -import {getDomainsArray} from '../../util/multiDomain-utils'; -import {getShowTestData} from '../../util/testChat-utils'; +import { endOfDay, formatISO, startOfDay } from 'date-fns'; +import { + getAvgCsaPresent, + getAvgPickTime, + getChatForwards, + getCsaAvgChatTime, + getCsaChatsTotal, + getThemeOverview, + getFollowUpActionOverview, + getQualityOverview, +} from '../../resources/api-constants'; +import { Methods, request } from '../../util/axios-client'; +import { getDomainsArray } from '../../util/multiDomain-utils'; +import { getShowTestData } from '../../util/testChat-utils'; + +const CSA_METRIC_IDS = new Set(['num_chats_csa', 'avg_chat_time_csa']); type QualityMetricOption = { - readonly id: string; - readonly labelKey: string; - readonly color: string; - readonly isSelected: boolean; + readonly id: string; + readonly labelKey: string; + readonly color: string; + readonly isSelected: boolean; }; const ChatsPage: React.FC = () => { - const {t} = useTranslation(); - const [tableTitleKey, setTableTitleKey] = useState(chatOptions[0].labelKey); - const [unit, setUnit] = useState(chatOptions[0].unit); - const [configs, setConfigs] = useState(); - const [chartData, setChartData] = useState({ - chartData: [], - colors: [], + const { t } = useTranslation(); + const [tableTitleKey, setTableTitleKey] = useState(chatOptions[0].labelKey); + const [unit, setUnit] = useState(chatOptions[0].unit); + const [configs, setConfigs] = useState(); + const [chartData, setChartData] = useState({ + chartData: [], + colors: [], + }); + const { setPeriodStatistics } = usePeriodStatisticsContext(); + const [updateKey, setUpdateKey] = useState(0); + const userDomains = useStore.getState().userDomains; + const multiDomainEnabled = import.meta.env.REACT_APP_ENABLE_MULTI_DOMAIN?.toLowerCase() === 'true'; + + const advisors = useRef([]); + + const themes = useRef([]); + const followUpStatuses = useRef([]); + const [showSelectAll, setShowSelectAll] = useState(false); + const [allMetrics, setAllMetrics] = useState([...chatOptions]); + + if (multiDomainEnabled) { + useStore.subscribe((state, prevState) => { + if (JSON.stringify(state.userDomains) !== JSON.stringify(prevState.userDomains)) { + setUpdateKey((prevState) => prevState + 1); + } }); - const {setPeriodStatistics} = usePeriodStatisticsContext(); - const [updateKey, setUpdateKey] = useState(0); - const userDomains = useStore.getState().userDomains; - const multiDomainEnabled = import.meta.env.REACT_APP_ENABLE_MULTI_DOMAIN?.toLowerCase() === 'true'; + } - const themes = useRef([]); - const followUpStatuses = useRef([]); - const [showSelectAll, setShowSelectAll] = useState(false); - const [allMetrics, setAllMetrics] = useState([...chatOptions]); + useEffect(() => { + setPeriodStatistics(chartData, unit); + }, [chartData, unit, updateKey]); - if (multiDomainEnabled) { - useStore.subscribe((state, prevState) => { - if (JSON.stringify(state.userDomains) !== JSON.stringify(prevState.userDomains)) { - setUpdateKey(prevState => prevState + 1); - } - }); - } + useEffect(() => { + setConfigs((prev) => ({ + ...prev!, + updateKey: updateKey, + })); + }, [updateKey]); - useEffect(() => { - setPeriodStatistics(chartData, unit); - }, [chartData, unit, updateKey]); + useEffect(() => { + if (configs) { + configsSubject.next(configs); + } + }, [configs]); - useEffect(() => { - setConfigs(prev => ({ - ...prev!, - updateKey: updateKey, - })); - }, [updateKey]); + const [configsSubject] = useState(() => new Subject()); - useEffect(() => { - if (configs) { - configsSubject.next(configs); - } - }, [configs]); + const fetchHandlerRef = useRef<(config: MetricOptionsState) => ObservableInput>(() => []); - const [configsSubject] = useState(() => new Subject()); + const fetchChatsForwards = async (config: any) => { + setShowSelectAll(false); + let result: ChartData = { chartData: [], colors: [] }; + try { + const response: any = await request({ + url: getChatForwards(), + method: Methods.post, + withCredentials: true, + data: { + metric: config?.groupByPeriod ?? 'day', + start_date: config?.start, + end_date: config?.end, + urls: getDomainsArray(), + showTest: getShowTestData(), + }, + }); + const res = response.response.map((entry: any) => ({ + ...translateChartKeys(entry, chartDataKey), + [chartDataKey]: new Date(entry[chartDataKey]).getTime(), + })); + const requiredKeys = [chartDataKey, ...config.options]; + const mapped = res.map((item: any) => { + const returnValue: any = {}; + requiredKeys.forEach((key: string) => { + if (key === chartDataKey) { + returnValue[key] = item[key]; + } else { + const chartKey = t(`chart.${key}`); + returnValue[chartKey] = item[chartKey]; + } + }); + return returnValue; + }); + result = { + chartData: mapped, + colors: chatOptions[4].subOptions!.map(({ id, color }) => ({ + id: t(`chart.${id}`), + color, + })), + }; + } catch (e) { + console.error(e); + } + return result; + }; - const fetchHandlerRef = useRef<(config: MetricOptionsState) => ObservableInput>(() => []); + const fetchAverageChatPickUpTime = async (config: any) => { + setShowSelectAll(false); + let result: ChartData = { chartData: [], colors: [] }; + try { + const response: any = await request({ + url: getAvgPickTime(), + method: Methods.post, + withCredentials: true, + data: { + metric: config?.groupByPeriod ?? 'day', + start_date: config?.start, + end_date: config?.end, + urls: getDomainsArray(), + showTest: getShowTestData(), + }, + }); + const mapped = response.response.map((entry: any) => ({ + ...translateChartKeys(entry, chartDataKey), + [chartDataKey]: new Date(entry[chartDataKey]).getTime(), + })); + result = { + chartData: mapped, + colors: [{ id: 'Average (Min)', color: '#FFB511' }], + minPointSize: 3, + }; + } catch (e) { + console.error(e); + } + return result; + }; - const fetchThemeOverview = async (config: MetricOptionsState): Promise => { - setShowSelectAll(true); - let result: ChartData = {chartData: [], colors: []}; - try { - const excluded_themes = themes.current.map((th) => th.id).filter((id) => !config.options.includes(id)); - const response = await request< - Readonly<{ start_date: string; end_date: string; excluded_themes: string[]; urls: (string | null)[]; showTest: boolean }>, - { response: { theme: string; count: number }[] } - >({ - url: getThemeOverview(), - method: Methods.post, - withCredentials: true, - data: { - start_date: config.start, - end_date: config.end, - excluded_themes: excluded_themes.length > 0 ? excluded_themes : [''], - urls: getDomainsArray(), - showTest: getShowTestData(), - }, - }); - const res = response.response; - const fetchedThemes: QualityMetricOption[] = res.map((item) => ({ - id: item.theme, - labelKey: item.theme, - color: themes.current.find((th) => th.id === item.theme)?.color ?? randomColor(), - isSelected: true, - })); - if (themes.current.length === 0) { - themes.current = fetchedThemes; - } - const updatedMetrics = [...allMetrics]; - updatedMetrics[4].subOptions = themes.current; - setAllMetrics(updatedMetrics); - const themeData: Record = {}; - res.forEach((item) => { - themeData[item.theme] = item.count; - }); - result = { - chartData: [themeData], - colors: themes.current.map(({id, color}) => ({id, color})), - }; - } catch (e) { - console.error(e); - } - return result; - }; + const fetchAveragePresentCsas = async (config: any) => { + setShowSelectAll(false); + let result: ChartData = { chartData: [], colors: [] }; + try { + const response: any = await request({ + url: getAvgCsaPresent(), + method: Methods.post, + withCredentials: true, + data: { + metric: config?.groupByPeriod ?? 'day', + start_date: config?.start, + end_date: config?.end, + }, + }); + const mapped = response.response.map((entry: any) => ({ + ...translateChartKeys(entry, chartDataKey), + [chartDataKey]: new Date(entry[chartDataKey]).getTime(), + })); + result = { + chartData: mapped, + colors: [{ id: 'Average', color: '#FFB511' }], + minPointSize: 3, + }; + } catch (e) { + console.error(e); + } + return result; + }; - const fetchQualityOverview = async (config: MetricOptionsState): Promise => { - setShowSelectAll(true); - let result: ChartData = {chartData: [], colors: []}; - try { - const response = await request< - Readonly<{ start_date: string; end_date: string; period: string; urls: (string | null)[]; showTest: boolean }>, - { response: [ - { time: string; total: number; themes: number; responseQuality: number; followUp: number }[], - { totalChats: string; chatsWithThemes: string; totalBuerokrattChats: string; buerokrattChatsWithQuality: string; chatsWithFollowUp: string }[] - ] } - >({ - url: getQualityOverview(), - method: Methods.post, - withCredentials: true, - data: { - start_date: config.start, - end_date: config.end, - period: config.groupByPeriod || 'day', - urls: getDomainsArray(), - showTest: getShowTestData(), - }, - }); - const chartRows = response.response[0] ?? []; - const summary = response.response[1]?.[0]; - const activeOptions: string[] = config.options ?? []; + const fetchTotalCsaChats = async (config: any) => { + setShowSelectAll(true); + let result: ChartData = { chartData: [], colors: [] }; + try { + const excluded_csas = advisors.current.map((e) => e.id).filter((e) => !config?.options.includes(e)); + const response: any = await request({ + url: getCsaChatsTotal(), + method: Methods.post, + withCredentials: true, + data: { + metric: config?.groupByPeriod ?? 'day', + start_date: config?.start, + end_date: config?.end, + excluded_csas: excluded_csas.length > 0 ? excluded_csas : [''], + urls: getDomainsArray(), + showTest: getShowTestData(), + }, + }); + const res = response.response; + if (advisors.current.length === 0) { + const fetchedAdvisors = getAdvisorsList(res); + advisors.current = fetchedAdvisors; + const updatedMetrics = [...allMetrics]; + updatedMetrics[7].subOptions = fetchedAdvisors; + setAllMetrics(updatedMetrics); + } + const responseAdvisors = getAdvisorsList(res).map((a) => ({ + ...a, + color: advisors.current.find((s) => s.id === a.id)?.color ?? a.color, + })); + result = { + chartData: getAdvisorChartData(res, responseAdvisors, 'chart.count'), + colors: responseAdvisors.map(({ labelKey, color }) => ({ id: labelKey, color })), + }; + } catch (e) { + console.error(e); + } + return result; + }; - const chartData = chartRows.map((row) => { - const obj: Record = { - [chartDataKey]: new Date(row.time).getTime(), - [t('chats.totalCount')]: row.total, - }; - if (activeOptions.includes('themes')) obj[t('chats.themes')] = row.themes; - if (activeOptions.includes('response_quality')) obj[t('chats.responseQuality')] = row.responseQuality; - if (activeOptions.includes('follow_up')) obj[t('chats.followUp')] = row.followUp; - return obj; - }); + const fetchAverageCsaChatTime = async (config: any) => { + setShowSelectAll(true); + let result: ChartData = { chartData: [], colors: [] }; + try { + const excluded_csas = advisors.current.map((e) => e.id).filter((e) => !config?.options.includes(e)); + const response: any = await request({ + url: getCsaAvgChatTime(), + method: Methods.post, + withCredentials: true, + data: { + metric: config?.groupByPeriod ?? 'day', + start_date: config?.start, + end_date: config?.end, + excluded_csas: excluded_csas.length > 0 ? excluded_csas : [''], + urls: getDomainsArray(), + showTest: getShowTestData(), + }, + }); + const res = response.response; + if (advisors.current.length === 0) { + const fetchedAdvisors = getAdvisorsList(res); + advisors.current = fetchedAdvisors; + const updatedMetrics = [...allMetrics]; + updatedMetrics[8].subOptions = fetchedAdvisors; + setAllMetrics(updatedMetrics); + } + const responseAdvisors = getAdvisorsList(res).map((a) => ({ + ...a, + color: advisors.current.find((s) => s.id === a.id)?.color ?? a.color, + })); + result = { + chartData: getAdvisorChartData(res, responseAdvisors, 'chart.count'), + colors: responseAdvisors.map(({ labelKey, color }) => ({ id: labelKey, color })), + minPointSize: 3, + }; + } catch (e) { + console.error(e); + } + return result; + }; - const colors: {id: string; color: string}[] = [{id: t('chats.totalCount'), color: '#008000'}]; - if (activeOptions.includes('themes')) colors.push({id: t('chats.themes'), color: '#fdbf47'}); - if (activeOptions.includes('response_quality')) colors.push({id: t('chats.responseQuality'), color: '#ed7d32'}); - if (activeOptions.includes('follow_up')) colors.push({id: t('chats.followUp'), color: '#8ab4d5'}); + const fetchThemeOverview = async (config: MetricOptionsState): Promise => { + setShowSelectAll(true); + let result: ChartData = { chartData: [], colors: [] }; + try { + const excluded_themes = themes.current.map((th) => th.id).filter((id) => !config.options.includes(id)); + const response = await request< + Readonly<{ + start_date: string; + end_date: string; + excluded_themes: string[]; + urls: (string | null)[]; + showTest: boolean; + }>, + { response: { theme: string; count: number }[] } + >({ + url: getThemeOverview(), + method: Methods.post, + withCredentials: true, + data: { + start_date: config.start, + end_date: config.end, + excluded_themes: excluded_themes.length > 0 ? excluded_themes : [''], + urls: getDomainsArray(), + showTest: getShowTestData(), + }, + }); + const res = response.response; + const fetchedThemes: QualityMetricOption[] = res.map((item) => ({ + id: item.theme, + labelKey: item.theme, + color: themes.current.find((th) => th.id === item.theme)?.color ?? randomColor(), + isSelected: true, + })); + if (themes.current.length === 0) { + themes.current = fetchedThemes; + } + const updatedMetrics = [...allMetrics]; + updatedMetrics[9].subOptions = themes.current; + setAllMetrics(updatedMetrics); + const themeData: Record = {}; + res.forEach((item) => { + themeData[item.theme] = item.count; + }); + result = { + chartData: [themeData], + colors: themes.current.map(({ id, color }) => ({ id, color })), + }; + } catch (e) { + console.error(e); + } + return result; + }; - result = { - chartData, - colors, - qualityData: summary - ? { - totalChats: parseInt(summary.totalChats) || 0, - chatsWithThemes: parseInt(summary.chatsWithThemes) || 0, - totalBuerokrattChats: parseInt(summary.totalBuerokrattChats) || 0, - buerokrattChatsWithQuality: parseInt(summary.buerokrattChatsWithQuality) || 0, - chatsWithFollowUp: parseInt(summary.chatsWithFollowUp) || 0, - } - : undefined, - }; - } catch (e) { - console.error(e); + const fetchQualityOverview = async (config: MetricOptionsState): Promise => { + setShowSelectAll(true); + let result: ChartData = { chartData: [], colors: [] }; + try { + const response = await request< + Readonly<{ start_date: string; end_date: string; period: string; urls: (string | null)[]; showTest: boolean }>, + { + response: [ + { time: string; total: number; themes: number; responseQuality: number; followUp: number }[], + { + totalChats: string; + chatsWithThemes: string; + totalBuerokrattChats: string; + buerokrattChatsWithQuality: string; + chatsWithFollowUp: string; + }[], + ]; } - return result; - }; + >({ + url: getQualityOverview(), + method: Methods.post, + withCredentials: true, + data: { + start_date: config.start, + end_date: config.end, + period: config.groupByPeriod || 'day', + urls: getDomainsArray(), + showTest: getShowTestData(), + }, + }); + const chartRows = response.response[0] ?? []; + const summary = response.response[1]?.[0]; + const activeOptions: string[] = config.options ?? []; + + const chartData = chartRows.map((row) => { + const obj: Record = { + [chartDataKey]: new Date(row.time).getTime(), + [t('chats.totalCount')]: row.total, + }; + if (activeOptions.includes('themes')) obj[t('chats.themes')] = row.themes; + if (activeOptions.includes('response_quality')) obj[t('chats.responseQuality')] = row.responseQuality; + if (activeOptions.includes('follow_up')) obj[t('chats.followUp')] = row.followUp; + return obj; + }); + + const colors: { id: string; color: string }[] = [{ id: t('chats.totalCount'), color: '#008000' }]; + if (activeOptions.includes('themes')) colors.push({ id: t('chats.themes'), color: '#fdbf47' }); + if (activeOptions.includes('response_quality')) colors.push({ id: t('chats.responseQuality'), color: '#ed7d32' }); + if (activeOptions.includes('follow_up')) colors.push({ id: t('chats.followUp'), color: '#8ab4d5' }); - const fetchFollowUpActionOverview = async (config: MetricOptionsState): Promise => { - setShowSelectAll(true); - let result: ChartData = {chartData: [], colors: []}; - try { - const excluded_actions = followUpStatuses.current.map((s) => s.id).filter((id) => !config.options.includes(id)); - const response = await request< - Readonly<{ start_date: string; end_date: string; excluded_actions: string[]; urls: (string | null)[]; showTest: boolean }>, - { response: { followUpAction: string; count: number }[] } - >({ - url: getFollowUpActionOverview(), - method: Methods.post, - withCredentials: true, - data: { - start_date: config.start, - end_date: config.end, - excluded_actions: excluded_actions.length > 0 ? excluded_actions : [''], - urls: getDomainsArray(), - showTest: getShowTestData(), - }, - }); - const res = response.response; - const fetchedStatuses = res.map((item) => ({ - id: item.followUpAction, - labelKey: item.followUpAction, - color: followUpStatuses.current.find((s) => s.id === item.followUpAction)?.color ?? randomColor(), - isSelected: true, - })); - if (followUpStatuses.current.length === 0) { - followUpStatuses.current = fetchedStatuses; + result = { + chartData, + colors, + qualityData: summary + ? { + totalChats: parseInt(summary.totalChats) || 0, + chatsWithThemes: parseInt(summary.chatsWithThemes) || 0, + totalBuerokrattChats: parseInt(summary.totalBuerokrattChats) || 0, + buerokrattChatsWithQuality: parseInt(summary.buerokrattChatsWithQuality) || 0, + chatsWithFollowUp: parseInt(summary.chatsWithFollowUp) || 0, } - const updatedMetrics = [...allMetrics]; - updatedMetrics[5].subOptions = followUpStatuses.current; - setAllMetrics(updatedMetrics); - const actionData: Record = {}; - res.forEach((item) => { - actionData[item.followUpAction] = item.count; - }); - result = { - chartData: [actionData], - colors: followUpStatuses.current.map(({id, color}) => ({id, color})), - }; - } catch (e) { - console.error(e); - } - return result; - }; + : undefined, + }; + } catch (e) { + console.error(e); + } + return result; + }; - fetchHandlerRef.current = (config: MetricOptionsState) => { - if (config.metric === 'theme_overview') { - return fetchThemeOverview(config); - } - if (config.metric === 'follow_up_action_overview') { - return fetchFollowUpActionOverview(config); - } - if (config.metric === 'quality_overview') { - return fetchQualityOverview(config); - } + const fetchFollowUpActionOverview = async (config: MetricOptionsState): Promise => { + setShowSelectAll(true); + let result: ChartData = { chartData: [], colors: [] }; + try { + const excluded_actions = followUpStatuses.current.map((s) => s.id).filter((id) => !config.options.includes(id)); + const response = await request< + Readonly<{ + start_date: string; + end_date: string; + excluded_actions: string[]; + urls: (string | null)[]; + showTest: boolean; + }>, + { response: { followUpAction: string; count: number }[] } + >({ + url: getFollowUpActionOverview(), + method: Methods.post, + withCredentials: true, + data: { + start_date: config.start, + end_date: config.end, + excluded_actions: excluded_actions.length > 0 ? excluded_actions : [''], + urls: getDomainsArray(), + showTest: getShowTestData(), + }, + }); + const res = response.response; + const fetchedStatuses = res.map((item) => ({ + id: item.followUpAction, + labelKey: item.followUpAction, + color: followUpStatuses.current.find((s) => s.id === item.followUpAction)?.color ?? randomColor(), + isSelected: true, + })); + if (followUpStatuses.current.length === 0) { + followUpStatuses.current = fetchedStatuses; + } + const updatedMetrics = [...allMetrics]; + updatedMetrics[10].subOptions = followUpStatuses.current; + setAllMetrics(updatedMetrics); + const actionData: Record = {}; + res.forEach((item) => { + actionData[item.followUpAction] = item.count; + }); + result = { + chartData: [actionData], + colors: followUpStatuses.current.map(({ id, color }) => ({ id, color })), + }; + } catch (e) { + console.error(e); + } + return result; + }; + + fetchHandlerRef.current = (config: MetricOptionsState) => { + switch (config.metric) { + case 'chat_forwards': + return fetchChatsForwards(config); + case 'avg_pick_time': + return fetchAverageChatPickUpTime(config); + case 'avg_present_csa': + return fetchAveragePresentCsas(config); + case 'num_chats_csa': + return fetchTotalCsaChats(config); + case 'avg_chat_time_csa': + return fetchAverageCsaChatTime(config); + case 'theme_overview': + return fetchThemeOverview(config); + case 'follow_up_action_overview': + return fetchFollowUpActionOverview(config); + case 'quality_overview': + return fetchQualityOverview(config); + default: return fetchData(config); - }; + } + }; - useEffect(() => { - const subscription = configsSubject - .pipe(distinctUntilChanged(), debounceTime(500), switchMap((config) => fetchHandlerRef.current(config))) - .subscribe((data: ChartData) => data && setChartData(data)); - return () => { - subscription.unsubscribe(); - }; - }, []); + useEffect(() => { + const subscription = configsSubject + .pipe( + distinctUntilChanged(), + debounceTime(500), + switchMap((config) => fetchHandlerRef.current(config)) + ) + .subscribe((data: ChartData) => data && setChartData(data)); + return () => { + subscription.unsubscribe(); + }; + }, []); - return ( - <> -

{t('menu.chats')}

- { - config.urls = userDomains ?? []; - if (config.metric !== 'theme_overview' && config.metric !== 'follow_up_action_overview' && config.metric !== 'quality_overview') { - themes.current = []; - followUpStatuses.current = []; - setShowSelectAll(false); - } else if (config.metric === 'theme_overview') { - followUpStatuses.current = []; - } else if (config.metric === 'follow_up_action_overview') { - themes.current = []; - } else if (config.metric === 'quality_overview') { - themes.current = []; - followUpStatuses.current = []; - setShowSelectAll(true); - } - setConfigs(config); - configsSubject.next(config); - const selectedOption = allMetrics.find((x) => x.id === config.metric); - if (!selectedOption) return; - setTableTitleKey(selectedOption.labelKey); - setUnit(selectedOption.unit); - }} - /> - x.id === configs?.metric)?.defaultChartType} - /> - - ); + return ( + <> +

{t('menu.chats')}

+ { + config.urls = userDomains ?? []; + if (!CSA_METRIC_IDS.has(config.metric)) { + advisors.current = []; + setShowSelectAll(false); + } + if ( + config.metric !== 'theme_overview' && + config.metric !== 'follow_up_action_overview' && + config.metric !== 'quality_overview' + ) { + themes.current = []; + followUpStatuses.current = []; + if (!CSA_METRIC_IDS.has(config.metric)) { + setShowSelectAll(false); + } + } else if (config.metric === 'theme_overview') { + followUpStatuses.current = []; + } else if (config.metric === 'follow_up_action_overview') { + themes.current = []; + } else if (config.metric === 'quality_overview') { + themes.current = []; + followUpStatuses.current = []; + setShowSelectAll(true); + } + setConfigs(config); + configsSubject.next(config); + const selectedOption = allMetrics.find((x) => x.id === config.metric); + if (!selectedOption) return; + setTableTitleKey(selectedOption.labelKey); + setUnit(selectedOption.unit); + }} + /> + x.id === configs?.metric)?.defaultChartType} + /> + + ); }; export default withAuthorization(ChatsPage, [ROLES.ROLE_ADMINISTRATOR, ROLES.ROLE_ANALYST]); diff --git a/GUI/src/pages/ChatsPage/options.tsx b/GUI/src/pages/ChatsPage/options.tsx index 2a5e690c..4cee67fb 100644 --- a/GUI/src/pages/ChatsPage/options.tsx +++ b/GUI/src/pages/ChatsPage/options.tsx @@ -37,6 +37,36 @@ export const chatOptions: Option[] = [ ], unit: t('units.minutes') ?? 'minutes', }, + { + id: 'chat_forwards', + labelKey: 'chats.chat_forwards', + subOptions: [ + { id: 'receivedChats', labelKey: 'chats.forwards.from_csa', color: '#FFB511' }, + { id: 'forwardedChats', labelKey: 'chats.forwards.to_csa', color: '#ED7D31' }, + { id: 'forwardedExternally', labelKey: 'chats.forwards.to_other', color: '#8BB4D5' }, + ], + unit: t('units.chats') ?? 'chats', + }, + { + id: 'avg_pick_time', + labelKey: 'chats.avg_pick_time', + unit: t('units.minutes') ?? 'minutes', + }, + { + id: 'avg_present_csa', + labelKey: 'chats.avg_present_csa', + unit: t('units.counselors') ?? 'counselors', + }, + { + id: 'num_chats_csa', + labelKey: 'chats.num_chats_csa', + unit: t('units.chats') ?? 'chats', + }, + { + id: 'avg_chat_time_csa', + labelKey: 'chats.avg_chat_time_csa', + unit: t('units.minutes') ?? 'minutes', + }, { id: 'theme_overview', labelKey: 'chats.theme_overview', diff --git a/GUI/src/resources/routes-constants.ts b/GUI/src/resources/routes-constants.ts index 6c59b1ef..55d72530 100644 --- a/GUI/src/resources/routes-constants.ts +++ b/GUI/src/resources/routes-constants.ts @@ -3,6 +3,5 @@ export const ROUTES = { CHATS_ROUTE: '/chats', BUROKRATT_ROUTE:'/burokratt', FEEDBACK_ROUTE:'/feedback', - ADVISORS_ROUTE:'/advisors', REPORTS_ROUTE:'/reports', } diff --git a/GUI/src/types/chart.ts b/GUI/src/types/chart.ts index b0522436..adc59e98 100644 --- a/GUI/src/types/chart.ts +++ b/GUI/src/types/chart.ts @@ -17,7 +17,7 @@ export type QualityData = { export type ChartData = { chartData: Record[]; - colors: { id: string; color: string }[]; + colors: { id: string; color: string | undefined }[]; minPointSize?: MinPointSize; periodNps?: number; periodNpsByCsa?: Record; diff --git a/GUI/src/util/api-response-handler.tsx b/GUI/src/util/api-response-handler.tsx index 36662106..06c65688 100644 --- a/GUI/src/util/api-response-handler.tsx +++ b/GUI/src/util/api-response-handler.tsx @@ -68,8 +68,7 @@ export const fetchChartData = async (url: string, config: any, resultId: string, const minPointSize = config.metric === 'avgConversationTime' || - config.metric === 'avgWaitingTime' || - config.metric === 'avgNumOfMessages' + config.metric === 'avgWaitingTime' ? 3 : 0; diff --git a/README.md b/README.md index 4cf331ee..3fed4fa2 100644 --- a/README.md +++ b/README.md @@ -83,12 +83,12 @@ curl -X POST -H "Content-Type: application/json" -d '{ For production deploying on kubernetes use this the variable [`REACT_APP_MENU_JSON`](https://github.com/buerokratt/NoOps/blob/dev/Kubernetes/Modules/Analytics-Module/templates/deployment-byk-analytics-gui.yaml) with the value: ``` -"[{\"id\":\"conversations\",\"label\":{\"et\":\"Vestlused\",\"en\":\"Conversations\"},\"path\":\"/chat\",\"children\":[{\"label\":{\"et\":\"Vastamata\",\"en\":\"Unanswered\"},\"path\":\"/unanswered\"},{\"label\":{\"et\":\"Aktiivsed\",\"en\":\"Active\"},\"path\":\"/active\"},{\"label\":{\"et\":\"Ootel\",\"en\":\"Pending\"},\"path\":\"/pending\"},{\"label\":{\"et\":\"Ajalugu\",\"en\":\"History\"},\"path\":\"/history\"}]},{\"id\":\"training\",\"label\":{\"et\":\"Treening\",\"en\":\"Training\"},\"path\":\"/training\",\"children\":[{\"label\":{\"et\":\"Treening\",\"en\":\"Training\"},\"path\":\"/training\",\"children\":[{\"label\":{\"et\":\"Teemad\",\"en\":\"Themes\"},\"path\":\"/training/intents\"},{\"hidden\":true,\"label\":{\"et\":\"Avalikud teemad\",\"en\":\"Public themes\"},\"path\":\"/training/common-intents\"},{\"label\":{\"et\":\"Teemade järeltreenimine\",\"en\":\"Post training themes\"},\"path\":\"/training/intents-followup-training\"},{\"label\":{\"et\":\"Vastused\",\"en\":\"Answers\"},\"path\":\"/training/responses\"},{\"label\":{\"et\":\"Reeglid\",\"en\":\"Rules\"},\"path\":\"/training/rules\"},{\"hidden\":true,\"label\":{\"et\":\"Konfiguratsioon\",\"en\":\"Configuration\"},\"path\":\"/training/configuration\"},{\"label\":{\"et\":\"Vormid\",\"en\":\"Forms\"},\"path\":\"/training/forms\"},{\"label\":{\"et\":\"Mälukohad\",\"en\":\"Slots\"},\"path\":\"/training/slots\"},{\"hidden\":true,\"label\":{\"et\":\"Automatic Teenused\",\"en\":\"Automatic Services\"},\"path\":\"/auto-services\"}]},{\"label\":{\"et\":\"Ajaloolised vestlused\",\"en\":\"Historical conversations\"},\"path\":\"/history\",\"children\":[{\"label\":{\"et\":\"Ajalugu\",\"en\":\"History\"},\"path\":\"/history/history\"},{\"hidden\":true,\"label\":{\"et\":\"Pöördumised\",\"en\":\"Appeals\"},\"path\":\"/history/appeal\"}]},{\"label\":{\"et\":\"Mudelipank ja analüütika\",\"en\":\"Modelbank and analytics\"},\"path\":\"/analytics\",\"children\":[{\"label\":{\"et\":\"Teemade ülevaade\",\"en\":\"Overview of topics\"},\"path\":\"/analytics/overview\"},{\"label\":{\"et\":\"Mudelite võrdlus\",\"en\":\"Comparison of models\"},\"path\":\"/analytics/models\"},{\"hidden\":true,\"label\":{\"et\":\"Testlood\",\"en\":\"testTracks\"},\"path\":\"/analytics/testcases\"}]},{\"label\":{\"et\":\"Treeni uus mudel\",\"en\":\"Train new model\"},\"path\":\"/train-new-model\"}]},{\"id\":\"analytics\",\"label\":{\"et\":\"Analüütika\",\"en\":\"Analytics\"},\"path\":\"/analytics\",\"children\":[{\"label\":{\"et\":\"Ülevaade\",\"en\":\"Overview\"},\"path\":\"/overview\"},{\"label\":{\"et\":\"Vestlused\",\"en\":\"Chats\"},\"path\":\"/chats\"},{\"label\":{\"et\":\"Tagasiside\",\"en\":\"Feedback\"},\"path\":\"/feedback\"},{\"label\":{\"et\":\"Nõustajad\",\"en\":\"Advisors\"},\"path\":\"/advisors\"},{\"label\":{\"et\":\"Avaandmed\",\"en\":\"Reports\"},\"path\":\"/reports\"}]},{\"id\":\"services\",\"hidden\":true,\"label\":{\"et\":\"Teenused\",\"en\":\"Services\"},\"path\":\"/services\",\"children\":[{\"label\":{\"et\":\"Ülevaade\",\"en\":\"Overview\"},\"path\":\"/overview\"},{\"label\":{\"et\":\"Uus teenus\",\"en\":\"New Service\"},\"path\":\"/newService\"},{\"label\":{\"et\":\"Automatic Teenused\",\"en\":\"Automatic Services\"},\"path\":\"/auto-services\"},{\"label\":{\"et\":\"Probleemsed teenused\",\"en\":\"Faulty Services\"},\"path\":\"/faultyServices\"}]},{\"id\":\"settings\",\"label\":{\"et\":\"Haldus\",\"en\":\"Administration\"},\"path\":\"/settings\",\"children\":[{\"label\":{\"et\":\"Kasutajad\",\"en\":\"Users\"},\"path\":\"/users\"},{\"label\":{\"et\":\"Vestlusbot\",\"en\":\"Chatbot\"},\"path\":\"/chatbot\",\"children\":[{\"label\":{\"et\":\"Seaded\",\"en\":\"Settings\"},\"path\":\"/chatbot/settings\"},{\"label\":{\"et\":\"Tervitussõnum\",\"en\":\"Welcome message\"},\"path\":\"/chatbot/welcome-message\"},{\"label\":{\"et\":\"Välimus ja käitumine\",\"en\":\"Appearance and behavior\"},\"path\":\"/chatbot/appearance\"},{\"label\":{\"et\":\"Erakorralised teated\",\"en\":\"Emergency notices\"},\"path\":\"/chatbot/emergency-notices\"}]},{\"label\":{\"et\":\"Asutuse tööaeg\",\"en\":\"Office opening hours\"},\"path\":\"/working-time\"},{\"label\":{\"et\":\"Sessiooni pikkus\",\"en\":\"Session length\"},\"path\":\"/session-length\"}]},{\"id\":\"monitoring\",\"hidden\":true,\"label\":{\"et\":\"Seire\",\"en\":\"Monitoring\"},\"path\":\"/monitoring\",\"children\":[{\"label\":{\"et\":\"Aktiivaeg\",\"en\":\"Working hours\"},\"path\":\"/uptime\"}]}]" +"[{\"id\":\"conversations\",\"label\":{\"et\":\"Vestlused\",\"en\":\"Conversations\"},\"path\":\"/chat\",\"children\":[{\"label\":{\"et\":\"Vastamata\",\"en\":\"Unanswered\"},\"path\":\"/unanswered\"},{\"label\":{\"et\":\"Aktiivsed\",\"en\":\"Active\"},\"path\":\"/active\"},{\"label\":{\"et\":\"Ootel\",\"en\":\"Pending\"},\"path\":\"/pending\"},{\"label\":{\"et\":\"Ajalugu\",\"en\":\"History\"},\"path\":\"/history\"}]},{\"id\":\"training\",\"label\":{\"et\":\"Treening\",\"en\":\"Training\"},\"path\":\"/training\",\"children\":[{\"label\":{\"et\":\"Treening\",\"en\":\"Training\"},\"path\":\"/training\",\"children\":[{\"label\":{\"et\":\"Teemad\",\"en\":\"Themes\"},\"path\":\"/training/intents\"},{\"hidden\":true,\"label\":{\"et\":\"Avalikud teemad\",\"en\":\"Public themes\"},\"path\":\"/training/common-intents\"},{\"label\":{\"et\":\"Teemade järeltreenimine\",\"en\":\"Post training themes\"},\"path\":\"/training/intents-followup-training\"},{\"label\":{\"et\":\"Vastused\",\"en\":\"Answers\"},\"path\":\"/training/responses\"},{\"label\":{\"et\":\"Reeglid\",\"en\":\"Rules\"},\"path\":\"/training/rules\"},{\"hidden\":true,\"label\":{\"et\":\"Konfiguratsioon\",\"en\":\"Configuration\"},\"path\":\"/training/configuration\"},{\"label\":{\"et\":\"Vormid\",\"en\":\"Forms\"},\"path\":\"/training/forms\"},{\"label\":{\"et\":\"Mälukohad\",\"en\":\"Slots\"},\"path\":\"/training/slots\"},{\"hidden\":true,\"label\":{\"et\":\"Automatic Teenused\",\"en\":\"Automatic Services\"},\"path\":\"/auto-services\"}]},{\"label\":{\"et\":\"Ajaloolised vestlused\",\"en\":\"Historical conversations\"},\"path\":\"/history\",\"children\":[{\"label\":{\"et\":\"Ajalugu\",\"en\":\"History\"},\"path\":\"/history/history\"},{\"hidden\":true,\"label\":{\"et\":\"Pöördumised\",\"en\":\"Appeals\"},\"path\":\"/history/appeal\"}]},{\"label\":{\"et\":\"Mudelipank ja analüütika\",\"en\":\"Modelbank and analytics\"},\"path\":\"/analytics\",\"children\":[{\"label\":{\"et\":\"Teemade ülevaade\",\"en\":\"Overview of topics\"},\"path\":\"/analytics/overview\"},{\"label\":{\"et\":\"Mudelite võrdlus\",\"en\":\"Comparison of models\"},\"path\":\"/analytics/models\"},{\"hidden\":true,\"label\":{\"et\":\"Testlood\",\"en\":\"testTracks\"},\"path\":\"/analytics/testcases\"}]},{\"label\":{\"et\":\"Treeni uus mudel\",\"en\":\"Train new model\"},\"path\":\"/train-new-model\"}]},{\"id\":\"analytics\",\"label\":{\"et\":\"Analüütika\",\"en\":\"Analytics\"},\"path\":\"/analytics\",\"children\":[{\"label\":{\"et\":\"Ülevaade\",\"en\":\"Overview\"},\"path\":\"/overview\"},{\"label\":{\"et\":\"Vestlused\",\"en\":\"Chats\"},\"path\":\"/chats\"},{\"label\":{\"et\":\"Tagasiside\",\"en\":\"Feedback\"},\"path\":\"/feedback\"},{\"label\":{\"et\":\"Avaandmed\",\"en\":\"Reports\"},\"path\":\"/reports\"}]},{\"id\":\"services\",\"hidden\":true,\"label\":{\"et\":\"Teenused\",\"en\":\"Services\"},\"path\":\"/services\",\"children\":[{\"label\":{\"et\":\"Ülevaade\",\"en\":\"Overview\"},\"path\":\"/overview\"},{\"label\":{\"et\":\"Uus teenus\",\"en\":\"New Service\"},\"path\":\"/newService\"},{\"label\":{\"et\":\"Automatic Teenused\",\"en\":\"Automatic Services\"},\"path\":\"/auto-services\"},{\"label\":{\"et\":\"Probleemsed teenused\",\"en\":\"Faulty Services\"},\"path\":\"/faultyServices\"}]},{\"id\":\"settings\",\"label\":{\"et\":\"Haldus\",\"en\":\"Administration\"},\"path\":\"/settings\",\"children\":[{\"label\":{\"et\":\"Kasutajad\",\"en\":\"Users\"},\"path\":\"/users\"},{\"label\":{\"et\":\"Vestlusbot\",\"en\":\"Chatbot\"},\"path\":\"/chatbot\",\"children\":[{\"label\":{\"et\":\"Seaded\",\"en\":\"Settings\"},\"path\":\"/chatbot/settings\"},{\"label\":{\"et\":\"Tervitussõnum\",\"en\":\"Welcome message\"},\"path\":\"/chatbot/welcome-message\"},{\"label\":{\"et\":\"Välimus ja käitumine\",\"en\":\"Appearance and behavior\"},\"path\":\"/chatbot/appearance\"},{\"label\":{\"et\":\"Erakorralised teated\",\"en\":\"Emergency notices\"},\"path\":\"/chatbot/emergency-notices\"}]},{\"label\":{\"et\":\"Asutuse tööaeg\",\"en\":\"Office opening hours\"},\"path\":\"/working-time\"},{\"label\":{\"et\":\"Sessiooni pikkus\",\"en\":\"Session length\"},\"path\":\"/session-length\"}]},{\"id\":\"monitoring\",\"hidden\":true,\"label\":{\"et\":\"Seire\",\"en\":\"Monitoring\"},\"path\":\"/monitoring\",\"children\":[{\"label\":{\"et\":\"Aktiivaeg\",\"en\":\"Working hours\"},\"path\":\"/uptime\"}]}]" ``` like this: ``` - name: REACT_APP_MENU_JSON - value: "[{\"id\":\"conversations\",\"label\":{\"et\":\"Vestlused\",\"en\":\"Conversations\"},\"path\":\"/chat\",\"children\":[{\"label\":{\"et\":\"Vastamata\",\"en\":\"Unanswered\"},\"path\":\"/unanswered\"},{\"label\":{\"et\":\"Aktiivsed\",\"en\":\"Active\"},\"path\":\"/active\"},{\"label\":{\"et\":\"Ootel\",\"en\":\"Pending\"},\"path\":\"/pending\"},{\"label\":{\"et\":\"Ajalugu\",\"en\":\"History\"},\"path\":\"/history\"}]},{\"id\":\"training\",\"label\":{\"et\":\"Treening\",\"en\":\"Training\"},\"path\":\"/training\",\"children\":[{\"label\":{\"et\":\"Treening\",\"en\":\"Training\"},\"path\":\"/training\",\"children\":[{\"label\":{\"et\":\"Teemad\",\"en\":\"Themes\"},\"path\":\"/training/intents\"},{\"hidden\":true,\"label\":{\"et\":\"Avalikud teemad\",\"en\":\"Public themes\"},\"path\":\"/training/common-intents\"},{\"label\":{\"et\":\"Teemade järeltreenimine\",\"en\":\"Post training themes\"},\"path\":\"/training/intents-followup-training\"},{\"label\":{\"et\":\"Vastused\",\"en\":\"Answers\"},\"path\":\"/training/responses\"},{\"label\":{\"et\":\"Reeglid\",\"en\":\"Rules\"},\"path\":\"/training/rules\"},{\"hidden\":true,\"label\":{\"et\":\"Konfiguratsioon\",\"en\":\"Configuration\"},\"path\":\"/training/configuration\"},{\"label\":{\"et\":\"Vormid\",\"en\":\"Forms\"},\"path\":\"/training/forms\"},{\"label\":{\"et\":\"Mälukohad\",\"en\":\"Slots\"},\"path\":\"/training/slots\"},{\"hidden\":true,\"label\":{\"et\":\"Automatic Teenused\",\"en\":\"Automatic Services\"},\"path\":\"/auto-services\"}]},{\"label\":{\"et\":\"Ajaloolised vestlused\",\"en\":\"Historical conversations\"},\"path\":\"/history\",\"children\":[{\"label\":{\"et\":\"Ajalugu\",\"en\":\"History\"},\"path\":\"/history/history\"},{\"hidden\":true,\"label\":{\"et\":\"Pöördumised\",\"en\":\"Appeals\"},\"path\":\"/history/appeal\"}]},{\"label\":{\"et\":\"Mudelipank ja analüütika\",\"en\":\"Modelbank and analytics\"},\"path\":\"/analytics\",\"children\":[{\"label\":{\"et\":\"Teemade ülevaade\",\"en\":\"Overview of topics\"},\"path\":\"/analytics/overview\"},{\"label\":{\"et\":\"Mudelite võrdlus\",\"en\":\"Comparison of models\"},\"path\":\"/analytics/models\"},{\"hidden\":true,\"label\":{\"et\":\"Testlood\",\"en\":\"testTracks\"},\"path\":\"/analytics/testcases\"}]},{\"label\":{\"et\":\"Treeni uus mudel\",\"en\":\"Train new model\"},\"path\":\"/train-new-model\"}]},{\"id\":\"analytics\",\"label\":{\"et\":\"Analüütika\",\"en\":\"Analytics\"},\"path\":\"/analytics\",\"children\":[{\"label\":{\"et\":\"Ülevaade\",\"en\":\"Overview\"},\"path\":\"/overview\"},{\"label\":{\"et\":\"Vestlused\",\"en\":\"Chats\"},\"path\":\"/chats\"},{\"label\":{\"et\":\"Tagasiside\",\"en\":\"Feedback\"},\"path\":\"/feedback\"},{\"label\":{\"et\":\"Nõustajad\",\"en\":\"Advisors\"},\"path\":\"/advisors\"},{\"label\":{\"et\":\"Avaandmed\",\"en\":\"Reports\"},\"path\":\"/reports\"}]},{\"id\":\"services\",\"hidden\":true,\"label\":{\"et\":\"Teenused\",\"en\":\"Services\"},\"path\":\"/services\",\"children\":[{\"label\":{\"et\":\"Ülevaade\",\"en\":\"Overview\"},\"path\":\"/overview\"},{\"label\":{\"et\":\"Uus teenus\",\"en\":\"New Service\"},\"path\":\"/newService\"},{\"label\":{\"et\":\"Automatic Teenused\",\"en\":\"Automatic Services\"},\"path\":\"/auto-services\"},{\"label\":{\"et\":\"Probleemsed teenused\",\"en\":\"Faulty Services\"},\"path\":\"/faultyServices\"}]},{\"id\":\"settings\",\"label\":{\"et\":\"Haldus\",\"en\":\"Administration\"},\"path\":\"/settings\",\"children\":[{\"label\":{\"et\":\"Kasutajad\",\"en\":\"Users\"},\"path\":\"/users\"},{\"label\":{\"et\":\"Vestlusbot\",\"en\":\"Chatbot\"},\"path\":\"/chatbot\",\"children\":[{\"label\":{\"et\":\"Seaded\",\"en\":\"Settings\"},\"path\":\"/chatbot/settings\"},{\"label\":{\"et\":\"Tervitussõnum\",\"en\":\"Welcome message\"},\"path\":\"/chatbot/welcome-message\"},{\"label\":{\"et\":\"Välimus ja käitumine\",\"en\":\"Appearance and behavior\"},\"path\":\"/chatbot/appearance\"},{\"label\":{\"et\":\"Erakorralised teated\",\"en\":\"Emergency notices\"},\"path\":\"/chatbot/emergency-notices\"}]},{\"label\":{\"et\":\"Asutuse tööaeg\",\"en\":\"Office opening hours\"},\"path\":\"/working-time\"},{\"label\":{\"et\":\"Sessiooni pikkus\",\"en\":\"Session length\"},\"path\":\"/session-length\"}]},{\"id\":\"monitoring\",\"hidden\":true,\"label\":{\"et\":\"Seire\",\"en\":\"Monitoring\"},\"path\":\"/monitoring\",\"children\":[{\"label\":{\"et\":\"Aktiivaeg\",\"en\":\"Working hours\"},\"path\":\"/uptime\"}]}]" + value: "[{\"id\":\"conversations\",\"label\":{\"et\":\"Vestlused\",\"en\":\"Conversations\"},\"path\":\"/chat\",\"children\":[{\"label\":{\"et\":\"Vastamata\",\"en\":\"Unanswered\"},\"path\":\"/unanswered\"},{\"label\":{\"et\":\"Aktiivsed\",\"en\":\"Active\"},\"path\":\"/active\"},{\"label\":{\"et\":\"Ootel\",\"en\":\"Pending\"},\"path\":\"/pending\"},{\"label\":{\"et\":\"Ajalugu\",\"en\":\"History\"},\"path\":\"/history\"}]},{\"id\":\"training\",\"label\":{\"et\":\"Treening\",\"en\":\"Training\"},\"path\":\"/training\",\"children\":[{\"label\":{\"et\":\"Treening\",\"en\":\"Training\"},\"path\":\"/training\",\"children\":[{\"label\":{\"et\":\"Teemad\",\"en\":\"Themes\"},\"path\":\"/training/intents\"},{\"hidden\":true,\"label\":{\"et\":\"Avalikud teemad\",\"en\":\"Public themes\"},\"path\":\"/training/common-intents\"},{\"label\":{\"et\":\"Teemade järeltreenimine\",\"en\":\"Post training themes\"},\"path\":\"/training/intents-followup-training\"},{\"label\":{\"et\":\"Vastused\",\"en\":\"Answers\"},\"path\":\"/training/responses\"},{\"label\":{\"et\":\"Reeglid\",\"en\":\"Rules\"},\"path\":\"/training/rules\"},{\"hidden\":true,\"label\":{\"et\":\"Konfiguratsioon\",\"en\":\"Configuration\"},\"path\":\"/training/configuration\"},{\"label\":{\"et\":\"Vormid\",\"en\":\"Forms\"},\"path\":\"/training/forms\"},{\"label\":{\"et\":\"Mälukohad\",\"en\":\"Slots\"},\"path\":\"/training/slots\"},{\"hidden\":true,\"label\":{\"et\":\"Automatic Teenused\",\"en\":\"Automatic Services\"},\"path\":\"/auto-services\"}]},{\"label\":{\"et\":\"Ajaloolised vestlused\",\"en\":\"Historical conversations\"},\"path\":\"/history\",\"children\":[{\"label\":{\"et\":\"Ajalugu\",\"en\":\"History\"},\"path\":\"/history/history\"},{\"hidden\":true,\"label\":{\"et\":\"Pöördumised\",\"en\":\"Appeals\"},\"path\":\"/history/appeal\"}]},{\"label\":{\"et\":\"Mudelipank ja analüütika\",\"en\":\"Modelbank and analytics\"},\"path\":\"/analytics\",\"children\":[{\"label\":{\"et\":\"Teemade ülevaade\",\"en\":\"Overview of topics\"},\"path\":\"/analytics/overview\"},{\"label\":{\"et\":\"Mudelite võrdlus\",\"en\":\"Comparison of models\"},\"path\":\"/analytics/models\"},{\"hidden\":true,\"label\":{\"et\":\"Testlood\",\"en\":\"testTracks\"},\"path\":\"/analytics/testcases\"}]},{\"label\":{\"et\":\"Treeni uus mudel\",\"en\":\"Train new model\"},\"path\":\"/train-new-model\"}]},{\"id\":\"analytics\",\"label\":{\"et\":\"Analüütika\",\"en\":\"Analytics\"},\"path\":\"/analytics\",\"children\":[{\"label\":{\"et\":\"Ülevaade\",\"en\":\"Overview\"},\"path\":\"/overview\"},{\"label\":{\"et\":\"Vestlused\",\"en\":\"Chats\"},\"path\":\"/chats\"},{\"label\":{\"et\":\"Tagasiside\",\"en\":\"Feedback\"},\"path\":\"/feedback\"},{\"label\":{\"et\":\"Avaandmed\",\"en\":\"Reports\"},\"path\":\"/reports\"}]},{\"id\":\"services\",\"hidden\":true,\"label\":{\"et\":\"Teenused\",\"en\":\"Services\"},\"path\":\"/services\",\"children\":[{\"label\":{\"et\":\"Ülevaade\",\"en\":\"Overview\"},\"path\":\"/overview\"},{\"label\":{\"et\":\"Uus teenus\",\"en\":\"New Service\"},\"path\":\"/newService\"},{\"label\":{\"et\":\"Automatic Teenused\",\"en\":\"Automatic Services\"},\"path\":\"/auto-services\"},{\"label\":{\"et\":\"Probleemsed teenused\",\"en\":\"Faulty Services\"},\"path\":\"/faultyServices\"}]},{\"id\":\"settings\",\"label\":{\"et\":\"Haldus\",\"en\":\"Administration\"},\"path\":\"/settings\",\"children\":[{\"label\":{\"et\":\"Kasutajad\",\"en\":\"Users\"},\"path\":\"/users\"},{\"label\":{\"et\":\"Vestlusbot\",\"en\":\"Chatbot\"},\"path\":\"/chatbot\",\"children\":[{\"label\":{\"et\":\"Seaded\",\"en\":\"Settings\"},\"path\":\"/chatbot/settings\"},{\"label\":{\"et\":\"Tervitussõnum\",\"en\":\"Welcome message\"},\"path\":\"/chatbot/welcome-message\"},{\"label\":{\"et\":\"Välimus ja käitumine\",\"en\":\"Appearance and behavior\"},\"path\":\"/chatbot/appearance\"},{\"label\":{\"et\":\"Erakorralised teated\",\"en\":\"Emergency notices\"},\"path\":\"/chatbot/emergency-notices\"}]},{\"label\":{\"et\":\"Asutuse tööaeg\",\"en\":\"Office opening hours\"},\"path\":\"/working-time\"},{\"label\":{\"et\":\"Sessiooni pikkus\",\"en\":\"Session length\"},\"path\":\"/session-length\"}]},{\"id\":\"monitoring\",\"hidden\":true,\"label\":{\"et\":\"Seire\",\"en\":\"Monitoring\"},\"path\":\"/monitoring\",\"children\":[{\"label\":{\"et\":\"Aktiivaeg\",\"en\":\"Working hours\"},\"path\":\"/uptime\"}]}]" ``` diff --git a/docker-compose.yml b/docker-compose.yml index 63152f1a..8d18494f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -88,9 +88,9 @@ services: - REACT_APP_ENABLE_MULTI_DOMAIN=TRUE - REACT_APP_RUUTER_PRIVATE_ENDED_API_URL=http://localhost:8080/analytics - REACT_APP_CURRENT_VERSION=Version 1.0.0 - - REACT_APP_MENU_JSON=[{"id":"conversations","label":{"et":"Vestlused","en":"Conversations"},"path":"/chat","children":[{"label":{"et":"Vastamata","en":"Unanswered"},"path":"/unanswered"},{"label":{"et":"Aktiivsed","en":"Active"},"path":"/active"},{"label":{"et":"Ajalugu","en":"History"},"path":"/history"},{"label":{"et":"Valideerimised","en":"Validations"},"path":"/validations"}]},{"id":"training","label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Teemad","en":"Themes"},"path":"/training/intents"},{"label":{"et":"Avalikud teemad","en":"Public themes"},"path":"/training/common-intents"},{"label":{"et":"Teemade järeltreenimine","en":"Post training themes"},"path":"/training/intents-followup-training"},{"label":{"et":"Vastused","en":"Answers"},"path":"/training/responses"},{"label":{"et":"Reeglid","en":"Rules"},"path":"/training/rules"},{"label":{"et":"Konfiguratsioon","en":"Configuration"},"path":"/training/configuration"},{"label":{"et":"Vormid","en":"Forms"},"path":"/training/forms"},{"label":{"et":"Mälukohad","en":"Slots"},"path":"/training/slots"}]},{"label":{"et":"Ajaloolised vestlused","en":"Historical conversations"},"path":"/history","children":[{"label":{"et":"Ajalugu","en":"History"},"path":"/history/history"},{"label":{"et":"Pöördumised","en":"Appeals"},"path":"/history/appeal"}]},{"label":{"et":"Mudelipank ja analüütika","en":"Modelbank and analytics"},"path":"/analytics","children":[{"label":{"et":"Teemade ülevaade","en":"Overview of topics"},"path":"/analytics/overview"},{"label":{"et":"Mudelite võrdlus","en":"Comparison of models"},"path":"/analytics/models"},{"label":{"et":"Testlood","en":"testTracks"},"path":"/analytics/testcases"}]},{"label":{"et":"Treeni uus mudel","en":"Train new model"},"path":"/train-new-model"}]},{"id":"analytics","label":{"et":"Analüütika","en":"Analytics"},"path":"/analytics","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Vestlused","en":"Chats"},"path":"/chats"},{"label":{"et":"Bürokratt","en":"Burokratt"},"path":"/burokratt", "hidden":true},{"label":{"et":"Tagasiside","en":"Feedback"},"path":"/feedback"},{"label":{"et":"Nõustajad","en":"Advisors"},"path":"/advisors"},{"label":{"et":"Avaandmed","en":"Reports"},"path":"/reports"}]},{"id":"services","label":{"et":"Teenused","en":"Services"},"path":"/services","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Uus teenus","en":"New Service"},"path":"/newService"},{"label":{"et":"Probleemsed teenused","en":"Faulty Services"},"path":"/faultyServices"}]},{"id":"settings","label":{"et":"Haldus","en":"Administration"},"path":"/settings","children":[{"label":{"et":"Kasutajad","en":"Users"},"path":"/users"},{"label":{"et":"Vestlusbot","en":"Chatbot"},"path":"/chatbot","children":[{"label":{"et":"Seaded","en":"Settings"},"path":"/chatbot/settings"},{"label":{"et":"Tervitussõnum","en":"Welcome message"},"path":"/chatbot/welcome-message"},{"label":{"et":"Välimus ja käitumine","en":"Appearance and behavior"},"path":"/chatbot/appearance"},{"label":{"et":"Erakorralised teated","en":"Emergency notices"},"path":"/chatbot/emergency-notices"}]},{"label":{"et":"Vestluste analüüs","en":"Chat analysis"},"path":"/chat-analysis"},{"label":{"et":"Asutuse tööaeg","en":"Office opening hours"},"path":"/working-time"},{"label":{"et":"Sessiooni pikkus","en":"Session length"},"path":"/session-length"},{"label":{"et":"SKMi konfiguratsioon","en":"SKM Configuration"},"path":"/skm-configuration"},{"label":{"et":"Multidomeenid","en":"Multi-Domains"},"path":"/multi-domains"},{"label":{"et":"Anonümiseerija","en":"Anonymizer"},"path":"/anonymizer"}]},{"id":"monitoring","label":{"et":"Seire","en":"Monitoring"},"path":"/monitoring","children":[{"label":{"et":"Aktiivaeg","en":"Working hours"},"path":"/uptime"}]}] + - REACT_APP_MENU_JSON=[{"id":"conversations","label":{"et":"Vestlused","en":"Conversations"},"path":"/chat","children":[{"label":{"et":"Vastamata","en":"Unanswered"},"path":"/unanswered"},{"label":{"et":"Aktiivsed","en":"Active"},"path":"/active"},{"label":{"et":"Ajalugu","en":"History"},"path":"/history"},{"label":{"et":"Valideerimised","en":"Validations"},"path":"/validations"}]},{"id":"training","label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Teemad","en":"Themes"},"path":"/training/intents"},{"label":{"et":"Avalikud teemad","en":"Public themes"},"path":"/training/common-intents"},{"label":{"et":"Teemade järeltreenimine","en":"Post training themes"},"path":"/training/intents-followup-training"},{"label":{"et":"Vastused","en":"Answers"},"path":"/training/responses"},{"label":{"et":"Reeglid","en":"Rules"},"path":"/training/rules"},{"label":{"et":"Konfiguratsioon","en":"Configuration"},"path":"/training/configuration"},{"label":{"et":"Vormid","en":"Forms"},"path":"/training/forms"},{"label":{"et":"Mälukohad","en":"Slots"},"path":"/training/slots"}]},{"label":{"et":"Ajaloolised vestlused","en":"Historical conversations"},"path":"/history","children":[{"label":{"et":"Ajalugu","en":"History"},"path":"/history/history"},{"label":{"et":"Pöördumised","en":"Appeals"},"path":"/history/appeal"}]},{"label":{"et":"Mudelipank ja analüütika","en":"Modelbank and analytics"},"path":"/analytics","children":[{"label":{"et":"Teemade ülevaade","en":"Overview of topics"},"path":"/analytics/overview"},{"label":{"et":"Mudelite võrdlus","en":"Comparison of models"},"path":"/analytics/models"},{"label":{"et":"Testlood","en":"testTracks"},"path":"/analytics/testcases"}]},{"label":{"et":"Treeni uus mudel","en":"Train new model"},"path":"/train-new-model"}]},{"id":"analytics","label":{"et":"Analüütika","en":"Analytics"},"path":"/analytics","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Vestlused","en":"Chats"},"path":"/chats"},{"label":{"et":"Bürokratt","en":"Burokratt"},"path":"/burokratt", "hidden":true},{"label":{"et":"Tagasiside","en":"Feedback"},"path":"/feedback"},{"label":{"et":"Avaandmed","en":"Reports"},"path":"/reports"}]},{"id":"services","label":{"et":"Teenused","en":"Services"},"path":"/services","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Uus teenus","en":"New Service"},"path":"/newService"},{"label":{"et":"Probleemsed teenused","en":"Faulty Services"},"path":"/faultyServices"}]},{"id":"settings","label":{"et":"Haldus","en":"Administration"},"path":"/settings","children":[{"label":{"et":"Kasutajad","en":"Users"},"path":"/users"},{"label":{"et":"Vestlusbot","en":"Chatbot"},"path":"/chatbot","children":[{"label":{"et":"Seaded","en":"Settings"},"path":"/chatbot/settings"},{"label":{"et":"Tervitussõnum","en":"Welcome message"},"path":"/chatbot/welcome-message"},{"label":{"et":"Välimus ja käitumine","en":"Appearance and behavior"},"path":"/chatbot/appearance"},{"label":{"et":"Erakorralised teated","en":"Emergency notices"},"path":"/chatbot/emergency-notices"}]},{"label":{"et":"Vestluste analüüs","en":"Chat analysis"},"path":"/chat-analysis"},{"label":{"et":"Asutuse tööaeg","en":"Office opening hours"},"path":"/working-time"},{"label":{"et":"Sessiooni pikkus","en":"Session length"},"path":"/session-length"},{"label":{"et":"SKMi konfiguratsioon","en":"SKM Configuration"},"path":"/skm-configuration"},{"label":{"et":"Multidomeenid","en":"Multi-Domains"},"path":"/multi-domains"},{"label":{"et":"Anonümiseerija","en":"Anonymizer"},"path":"/anonymizer"}]},{"id":"monitoring","label":{"et":"Seire","en":"Monitoring"},"path":"/monitoring","children":[{"label":{"et":"Aktiivaeg","en":"Working hours"},"path":"/uptime"}]}] # # for production use this one: - # - REACT_APP_MENU_JSON=[{"id":"conversations","label":{"et":"Vestlused","en":"Conversations"},"path":"/chat","children":[{"label":{"et":"Vastamata","en":"Unanswered"},"path":"/unanswered"},{"label":{"et":"Aktiivsed","en":"Active"},"path":"/active"},{"label":{"et":"Ootel","en":"Pending"},"path":"/pending"},{"label":{"et":"Ajalugu","en":"History"},"path":"/history"},{"label":{"et":"Valideerimised","en":"Validations"},"path":"/validations"}]},{"id":"training","label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Teemad","en":"Themes"},"path":"/training/intents"},{"hidden":true,"label":{"et":"Avalikud teemad","en":"Public themes"},"path":"/training/common-intents"},{"label":{"et":"Teemade järeltreenimine","en":"Post training themes"},"path":"/training/intents-followup-training"},{"label":{"et":"Vastused","en":"Answers"},"path":"/training/responses"},{"label":{"et":"Reeglid","en":"Rules"},"path":"/training/rules"},{"hidden":true,"label":{"et":"Konfiguratsioon","en":"Configuration"},"path":"/training/configuration"},{"label":{"et":"Vormid","en":"Forms"},"path":"/training/forms"},{"label":{"et":"Mälukohad","en":"Slots"},"path":"/training/slots"}]},{"label":{"et":"Ajaloolised vestlused","en":"Historical conversations"},"path":"/history","children":[{"label":{"et":"Ajalugu","en":"History"},"path":"/history/history"},{"hidden":true,"label":{"et":"Pöördumised","en":"Appeals"},"path":"/history/appeal"}]},{"label":{"et":"Mudelipank ja analüütika","en":"Modelbank and analytics"},"path":"/analytics","children":[{"label":{"et":"Teemade ülevaade","en":"Overview of topics"},"path":"/analytics/overview"},{"label":{"et":"Mudelite võrdlus","en":"Comparison of models"},"path":"/analytics/models"},{"hidden":true,"label":{"et":"Testlood","en":"testTracks"},"path":"/analytics/testcases"}]},{"label":{"et":"Treeni uus mudel","en":"Train new model"},"path":"/train-new-model"}]},{"id":"analytics","label":{"et":"Analüütika","en":"Analytics"},"path":"/analytics","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Vestlused","en":"Chats"},"path":"/chats"},{"label":{"et":"Tagasiside","en":"Feedback"},"path":"/feedback"},{"label":{"et":"Nõustajad","en":"Advisors"},"path":"/advisors"},{"label":{"et":"Avaandmed","en":"Reports"},"path":"/reports"}]},{"id":"services","hidden":true,"label":{"et":"Teenused","en":"Services"},"path":"/services","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Uus teenus","en":"New Service"},"path":"/newService"},{"label":{"et":"Probleemsed teenused","en":"Faulty Services"},"path":"/faultyServices"}]},{"id":"settings","label":{"et":"Haldus","en":"Administration"},"path":"/settings","children":[{"label":{"et":"Kasutajad","en":"Users"},"path":"/users"},{"label":{"et":"Vestlusbot","en":"Chatbot"},"path":"/chatbot","children":[{"label":{"et":"Seaded","en":"Settings"},"path":"/chatbot/settings"},{"label":{"et":"Tervitussõnum","en":"Welcome message"},"path":"/chatbot/welcome-message"},{"label":{"et":"Välimus ja käitumine","en":"Appearance and behavior"},"path":"/chatbot/appearance"},{"label":{"et":"Erakorralised teated","en":"Emergency notices"},"path":"/chatbot/emergency-notices"},{"label":{"et":"Tagasiside","en":"Feedback"},"path":"/chatbot/feedback"}]},{"label":{"et":"Vestluste analüüs","en":"Chat analysis"},"path":"/chat-analysis"},{"label":{"et":"Asutuse tööaeg","en":"Office opening hours"},"path":"/working-time"},{"label":{"et":"Sessiooni pikkus","en":"Session length"},"path":"/session-length"},{"label":{"et":"SKMi konfiguratsioon","en":"SKM Configuration"},"path":"/skm-configuration"},{"hidden": false,"label":{"et":"Multidomeenid","en":"Multi-Domains"},"path":"/multi-domains"},{"label":{"et":"Anonümiseerija","en":"Anonymizer"},"path":"/anonymizer"}]},{"id":"monitoring","hidden":true,"label":{"et":"Seire","en":"Monitoring"},"path":"/monitoring","children":[{"label":{"et":"Aktiivaeg","en":"Working hours"},"path":"/uptime"}]}] + # - REACT_APP_MENU_JSON=[{"id":"conversations","label":{"et":"Vestlused","en":"Conversations"},"path":"/chat","children":[{"label":{"et":"Vastamata","en":"Unanswered"},"path":"/unanswered"},{"label":{"et":"Aktiivsed","en":"Active"},"path":"/active"},{"label":{"et":"Ootel","en":"Pending"},"path":"/pending"},{"label":{"et":"Ajalugu","en":"History"},"path":"/history"},{"label":{"et":"Valideerimised","en":"Validations"},"path":"/validations"}]},{"id":"training","label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Treening","en":"Training"},"path":"/training","children":[{"label":{"et":"Teemad","en":"Themes"},"path":"/training/intents"},{"hidden":true,"label":{"et":"Avalikud teemad","en":"Public themes"},"path":"/training/common-intents"},{"label":{"et":"Teemade järeltreenimine","en":"Post training themes"},"path":"/training/intents-followup-training"},{"label":{"et":"Vastused","en":"Answers"},"path":"/training/responses"},{"label":{"et":"Reeglid","en":"Rules"},"path":"/training/rules"},{"hidden":true,"label":{"et":"Konfiguratsioon","en":"Configuration"},"path":"/training/configuration"},{"label":{"et":"Vormid","en":"Forms"},"path":"/training/forms"},{"label":{"et":"Mälukohad","en":"Slots"},"path":"/training/slots"}]},{"label":{"et":"Ajaloolised vestlused","en":"Historical conversations"},"path":"/history","children":[{"label":{"et":"Ajalugu","en":"History"},"path":"/history/history"},{"hidden":true,"label":{"et":"Pöördumised","en":"Appeals"},"path":"/history/appeal"}]},{"label":{"et":"Mudelipank ja analüütika","en":"Modelbank and analytics"},"path":"/analytics","children":[{"label":{"et":"Teemade ülevaade","en":"Overview of topics"},"path":"/analytics/overview"},{"label":{"et":"Mudelite võrdlus","en":"Comparison of models"},"path":"/analytics/models"},{"hidden":true,"label":{"et":"Testlood","en":"testTracks"},"path":"/analytics/testcases"}]},{"label":{"et":"Treeni uus mudel","en":"Train new model"},"path":"/train-new-model"}]},{"id":"analytics","label":{"et":"Analüütika","en":"Analytics"},"path":"/analytics","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Vestlused","en":"Chats"},"path":"/chats"},{"label":{"et":"Tagasiside","en":"Feedback"},"path":"/feedback"},{"label":{"et":"Avaandmed","en":"Reports"},"path":"/reports"}]},{"id":"services","hidden":true,"label":{"et":"Teenused","en":"Services"},"path":"/services","children":[{"label":{"et":"Ülevaade","en":"Overview"},"path":"/overview"},{"label":{"et":"Uus teenus","en":"New Service"},"path":"/newService"},{"label":{"et":"Probleemsed teenused","en":"Faulty Services"},"path":"/faultyServices"}]},{"id":"settings","label":{"et":"Haldus","en":"Administration"},"path":"/settings","children":[{"label":{"et":"Kasutajad","en":"Users"},"path":"/users"},{"label":{"et":"Vestlusbot","en":"Chatbot"},"path":"/chatbot","children":[{"label":{"et":"Seaded","en":"Settings"},"path":"/chatbot/settings"},{"label":{"et":"Tervitussõnum","en":"Welcome message"},"path":"/chatbot/welcome-message"},{"label":{"et":"Välimus ja käitumine","en":"Appearance and behavior"},"path":"/chatbot/appearance"},{"label":{"et":"Erakorralised teated","en":"Emergency notices"},"path":"/chatbot/emergency-notices"},{"label":{"et":"Tagasiside","en":"Feedback"},"path":"/chatbot/feedback"}]},{"label":{"et":"Vestluste analüüs","en":"Chat analysis"},"path":"/chat-analysis"},{"label":{"et":"Asutuse tööaeg","en":"Office opening hours"},"path":"/working-time"},{"label":{"et":"Sessiooni pikkus","en":"Session length"},"path":"/session-length"},{"label":{"et":"SKMi konfiguratsioon","en":"SKM Configuration"},"path":"/skm-configuration"},{"hidden": false,"label":{"et":"Multidomeenid","en":"Multi-Domains"},"path":"/multi-domains"},{"label":{"et":"Anonümiseerija","en":"Anonymizer"},"path":"/anonymizer"}]},{"id":"monitoring","hidden":true,"label":{"et":"Seire","en":"Monitoring"},"path":"/monitoring","children":[{"label":{"et":"Aktiivaeg","en":"Working hours"},"path":"/uptime"}]}] build: context: ./GUI dockerfile: Dockerfile.dev