@cccsaurora/howler-ui 2.14.0-dev.226 → 2.14.0-dev.228
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.
|
@@ -5,7 +5,7 @@ import { Autocomplete, Box, Card, CardContent, CardHeader, Divider, FormControl,
|
|
|
5
5
|
import api from '@cccsaurora/howler-ui/api';
|
|
6
6
|
import { ViewContext } from '@cccsaurora/howler-ui/components/app/providers/ViewProvider';
|
|
7
7
|
import CustomButton from '@cccsaurora/howler-ui/components/elements/addons/buttons/CustomButton';
|
|
8
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
8
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
10
|
import { useContextSelector } from 'use-context-selector';
|
|
11
11
|
const TYPES = {
|
|
@@ -33,7 +33,14 @@ const AddNewCard = ({ dashboard, addCard }) => {
|
|
|
33
33
|
type: selectedType,
|
|
34
34
|
config: JSON.stringify(config)
|
|
35
35
|
});
|
|
36
|
-
|
|
36
|
+
// Zero the config so we don't prep the user to add the same card
|
|
37
|
+
// We can leave the analyticId, because it is allowed to be duplicated across viz types
|
|
38
|
+
['type', 'viewId'].forEach(key => {
|
|
39
|
+
if (key in config) {
|
|
40
|
+
setConfig(key, '');
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}, [selectedType, addCard, config, setConfig]);
|
|
37
44
|
const fetchAllAnalytics = async () => {
|
|
38
45
|
setAnalyticsLoading(true);
|
|
39
46
|
const batchSize = 150;
|
|
@@ -56,6 +63,15 @@ const AddNewCard = ({ dashboard, addCard }) => {
|
|
|
56
63
|
useEffect(() => {
|
|
57
64
|
fetchAllAnalytics();
|
|
58
65
|
}, []);
|
|
66
|
+
const filteredAnalyticVisualizations = useMemo(() => {
|
|
67
|
+
const existingAnalyticCards = dashboard.filter(_card => _card.type === "analytic");
|
|
68
|
+
return VISUALIZATIONS.filter(viz => {
|
|
69
|
+
return !existingAnalyticCards.some(_card => {
|
|
70
|
+
const parsedConfig = JSON.parse(_card.config);
|
|
71
|
+
return parsedConfig.analyticId === config.analyticId && parsedConfig.type === viz;
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}, [dashboard, config.analyticId]);
|
|
59
75
|
useEffect(() => {
|
|
60
76
|
if (selectedType === 'view') {
|
|
61
77
|
_setConfig({
|
|
@@ -78,7 +94,7 @@ const AddNewCard = ({ dashboard, addCard }) => {
|
|
|
78
94
|
}, [fetchViews]);
|
|
79
95
|
return (_jsx(Grid, { item: true, xs: 12, md: 6, children: _jsxs(Card, { variant: "outlined", sx: { height: '100%' }, children: [_jsx(CardHeader, { title: t('route.home.add'), subheader: _jsx(Typography, { variant: "body2", color: "text.secondary", children: t('route.home.add.description') }) }), _jsx(CardContent, { children: _jsxs(Stack, { spacing: 1, children: [_jsxs(FormControl, { sx: theme => ({ mt: `${theme.spacing(2)} !important` }), children: [_jsx(InputLabel, { children: t('route.home.add.type') }), _jsx(Select, { value: selectedType, onChange: event => setSelectedType(event.target.value), label: t('route.home.add.type'), children: Object.keys(TYPES).map(type => (_jsx(MenuItem, { value: type, children: _jsxs(Stack, { children: [_jsx(Typography, { variant: "body1", children: t(`route.home.add.type.${type}`) }), _jsx(Typography, { variant: "caption", color: "text.secondary", children: t(`route.home.add.type.${type}.description`) })] }) }, type))) })] }), selectedType && _jsx(Divider, { flexItem: true }), selectedType === 'analytic' && (_jsxs(_Fragment, { children: [_jsx(Typography, { variant: "body1", children: t('route.home.add.analytic.title') }), _jsx(Typography, { variant: "caption", color: "text.secondary", children: t('route.home.add.analytic.description') }), _jsx(Autocomplete, { sx: { pt: 1 }, onChange: (__, opt) => setConfig('analyticId', opt.analytic_id), loading: analyticsLoading, options: analytics, filterOptions: (options, state) => options.filter(opt => opt.name.toLowerCase().includes(state.inputValue.toLowerCase()) ||
|
|
80
96
|
opt.description?.split('\n')[0]?.toLowerCase().includes(state.inputValue.toLowerCase())), renderOption: (props, option) => (_createElement("li", { ...props, key: option.analytic_id },
|
|
81
|
-
_jsxs(Stack, { children: [_jsx(Typography, { variant: "body1", children: option.name }), _jsx(Typography, { variant: "caption", color: "text.secondary", children: option.description?.split('\n')[0] })] }))), getOptionLabel: option => option.name, renderInput: params => _jsx(TextField, { ...params, label: t('route.home.add.analytic') }) }), _jsxs(FormControl, { sx: theme => ({ mt: `${theme.spacing(2)} !important` }), children: [_jsx(InputLabel, { children: t('route.home.add.visualization') }), _jsx(Select, { value: config.type ?? '', onChange: event => setConfig('type', event.target.value), label: t('route.home.add.visualization'), children:
|
|
97
|
+
_jsxs(Stack, { children: [_jsx(Typography, { variant: "body1", children: option.name }), _jsx(Typography, { variant: "caption", color: "text.secondary", children: option.description?.split('\n')[0] })] }))), getOptionLabel: option => option.name, renderInput: params => _jsx(TextField, { ...params, label: t('route.home.add.analytic') }) }), _jsxs(FormControl, { sx: theme => ({ mt: `${theme.spacing(2)} !important` }), children: [_jsx(InputLabel, { children: t('route.home.add.visualization') }), _jsx(Select, { value: config.type ?? '', onChange: event => setConfig('type', event.target.value), label: t('route.home.add.visualization'), children: filteredAnalyticVisualizations.length > 0 ? (filteredAnalyticVisualizations.map(viz => (_jsx(MenuItem, { value: viz, children: _jsxs(Stack, { children: [_jsx(Typography, { variant: "body1", children: t(`route.home.add.visualization.${viz}`) }), _jsx(Typography, { variant: "caption", color: "text.secondary", children: t(`route.home.add.visualization.${viz}.description`) })] }) }, viz)))) : (_jsx(MenuItem, { disabled: true, children: _jsx(Typography, { variant: "body1", color: "text.secondary", children: t('route.home.add.visualization.unavailable') }) })) })] })] })), selectedType === 'view' && (_jsxs(_Fragment, { children: [_jsx(Autocomplete, { sx: { pt: 1 }, value: views[config.viewId] || null, onChange: (__, opt) => setConfig('viewId', opt.view_id), onOpen: onViewOpen, onClose: () => setViewOpen(false), open: viewOpen, loading: viewLoading, options: Object.values(views), filterOptions: (options, state) => options.filter(opt => !!opt &&
|
|
82
98
|
!dashboard?.find(entry => entry.type === 'view' && JSON.parse(entry.config).viewId === opt.view_id) &&
|
|
83
99
|
(opt.title.toLowerCase().includes(state.inputValue.toLowerCase()) ||
|
|
84
100
|
opt.query.toLowerCase().includes(state.inputValue.toLowerCase()))), renderOption: (props, option) => (_createElement("li", { ...props, key: option.view_id },
|
|
@@ -543,12 +543,13 @@
|
|
|
543
543
|
"route.home.add.visualization.assessment": "Assessment Result of Created Hits",
|
|
544
544
|
"route.home.add.visualization.created.description": "Time series of the number of hits created by the analytic over the last 90 days.",
|
|
545
545
|
"route.home.add.visualization.created": "Number of Created Hits",
|
|
546
|
+
"route.home.add.visualization.detection.description": "For hits ingested in the last three months, what is their detection?",
|
|
547
|
+
"route.home.add.visualization.detection": "Hits Created by Detection",
|
|
546
548
|
"route.home.add.visualization.escalation.description": "For hits that have been triaged, what was the resulting escalation?",
|
|
547
549
|
"route.home.add.visualization.escalation": "Escalation of Created Hits",
|
|
548
550
|
"route.home.add.visualization.status.description": "For hits ingested in the last three months, what is their status?",
|
|
549
551
|
"route.home.add.visualization.status": "Cumulative Status of Hits Created",
|
|
550
|
-
"route.home.add.visualization.
|
|
551
|
-
"route.home.add.visualization.detection": "Hits Created by Detection",
|
|
552
|
+
"route.home.add.visualization.unavailable": "No visualization options available.",
|
|
552
553
|
"route.home.add.visualization": "Visualization",
|
|
553
554
|
"route.home.add": "Add New Panel",
|
|
554
555
|
"route.home.alert.updated.description": "There have been updates to alerts you are involved in. Since you last viewed, {{count}} alert(s) have updates.",
|
|
@@ -548,6 +548,7 @@
|
|
|
548
548
|
"route.home.add.visualization.escalation": "Escalade des hits créés",
|
|
549
549
|
"route.home.add.visualization.status.description": "Quel est l'état des hits créés au cours des trois derniers mois ?",
|
|
550
550
|
"route.home.add.visualization.status": "État cumulatif des hits créés",
|
|
551
|
+
"route.home.add.visualization.unavailable": "Aucune option de visualisation disponible.",
|
|
551
552
|
"route.home.add.visualization": "Visualisation",
|
|
552
553
|
"route.home.add": "Ajouter un nouveau panneau",
|
|
553
554
|
"route.home.alert.updated.description": "Des mises à jour ont été apportées aux alertes auxquelles vous participez. Depuis votre dernière consultation, {{count}} alertes ont été mises à jour",
|