@cccsaurora/howler-ui 2.13.0-dev.169 → 2.13.0-dev.173
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commons/components/notification/elements/item/NotificationItemDate.js +2 -2
- package/components/app/drawers/ApiKeyDrawer.js +4 -4
- package/components/app/hooks/useMatchers.js +29 -4
- package/components/app/hooks/useMatchers.test.js +3 -3
- package/components/elements/hit/aggregate/HitGraph.d.ts +1 -1
- package/components/elements/hit/aggregate/HitGraph.js +7 -7
- package/components/elements/hit/elements/HitTimestamp.js +8 -8
- package/components/hooks/useMyChart.d.ts +1 -1
- package/components/hooks/useMyChart.js +1 -1
- package/components/routes/advanced/QueryBuilder.js +3 -3
- package/components/routes/analytics/AnalyticOverview.d.ts +1 -1
- package/components/routes/analytics/AnalyticOverview.js +1 -1
- package/components/routes/analytics/AnalyticOverviews.d.ts +1 -1
- package/components/routes/analytics/AnalyticOverviews.js +1 -1
- package/components/routes/analytics/AnalyticTemplates.d.ts +1 -1
- package/components/routes/analytics/AnalyticTemplates.js +1 -1
- package/components/routes/analytics/RuleView.d.ts +1 -1
- package/components/routes/analytics/RuleView.js +1 -1
- package/components/routes/analytics/TriageSettings.d.ts +1 -1
- package/components/routes/analytics/TriageSettings.js +1 -1
- package/components/routes/analytics/widgets/Assessment.d.ts +1 -1
- package/components/routes/analytics/widgets/Assessment.js +1 -1
- package/components/routes/analytics/widgets/Created.d.ts +1 -1
- package/components/routes/analytics/widgets/Created.js +1 -1
- package/components/routes/analytics/widgets/Detection.d.ts +1 -1
- package/components/routes/analytics/widgets/Detection.js +1 -1
- package/components/routes/analytics/widgets/Escalation.d.ts +1 -1
- package/components/routes/analytics/widgets/Escalation.js +1 -1
- package/components/routes/analytics/widgets/Stacked.d.ts +1 -1
- package/components/routes/analytics/widgets/Stacked.js +1 -1
- package/components/routes/analytics/widgets/Status.d.ts +1 -1
- package/components/routes/analytics/widgets/Status.js +1 -1
- package/components/routes/help/TemplateDocumentation.js +5 -5
- package/components/routes/hits/search/HitBrowser.js +2 -2
- package/components/routes/hits/search/InformationPane.js +16 -6
- package/components/routes/hits/search/shared/CustomSpan.js +6 -6
- package/components/routes/home/index.js +4 -4
- package/components/routes/settings/SecuritySection.js +2 -2
- package/index.js +7 -0
- package/package.json +103 -103
- package/utils/constants.js +2 -2
- package/utils/utils.js +3 -3
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Typography } from '@mui/material';
|
|
3
3
|
import {} from '@cccsaurora/howler-ui/commons/components/notification';
|
|
4
|
-
import
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
5
|
import { memo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
export const NotificationItemDate = memo(({ date_published = null }) => {
|
|
8
8
|
const { i18n } = useTranslation(['notification']);
|
|
9
|
-
return !date_published ? null : (_jsx(Typography, { lineHeight: "revert", display: "block", variant: "caption", color: "textSecondary", children: _jsx(_Fragment, { children:
|
|
9
|
+
return !date_published ? null : (_jsx(Typography, { lineHeight: "revert", display: "block", variant: "caption", color: "textSecondary", children: _jsx(_Fragment, { children: dayjs(date_published).locale(i18n.language).fromNow() }) }));
|
|
10
10
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Alert, AlertTitle, Button, Checkbox, Divider, FormControl, FormControlLabel, FormGroup, FormLabel, Stack, TextField, Typography } from '@mui/material';
|
|
3
3
|
import { LocalizationProvider, StaticDateTimePicker } from '@mui/x-date-pickers';
|
|
4
|
-
import {
|
|
4
|
+
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
|
5
5
|
import api from '@cccsaurora/howler-ui/api';
|
|
6
6
|
import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
|
|
7
7
|
import useMySnackbar from '@cccsaurora/howler-ui/components/hooks/useMySnackbar';
|
|
8
|
+
import dayjs from 'dayjs';
|
|
8
9
|
import {} from '@cccsaurora/howler-ui/models/entities/generated/ApiType';
|
|
9
|
-
import moment from 'moment';
|
|
10
10
|
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
11
11
|
import { Trans, useTranslation } from 'react-i18next';
|
|
12
12
|
import { ApiConfigContext } from '../providers/ApiConfigProvider';
|
|
@@ -30,7 +30,7 @@ const ApiKeyDrawer = ({ onCreated }) => {
|
|
|
30
30
|
if (!amount || !unit) {
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
|
-
return
|
|
33
|
+
return dayjs().add(amount, unit);
|
|
34
34
|
}, [amount, unit]);
|
|
35
35
|
const updatePrivs = useCallback((priv) => (ev) => {
|
|
36
36
|
if (ev.target.checked) {
|
|
@@ -62,6 +62,6 @@ const ApiKeyDrawer = ({ onCreated }) => {
|
|
|
62
62
|
useEffect(() => {
|
|
63
63
|
setExpiryDate(maxDate);
|
|
64
64
|
}, [maxDate]);
|
|
65
|
-
return (_jsx(LocalizationProvider, { dateAdapter:
|
|
65
|
+
return (_jsx(LocalizationProvider, { dateAdapter: AdapterDayjs, children: _jsxs(Stack, { direction: "column", spacing: 2, sx: { mt: 2 }, children: [_jsx(Typography, { sx: { maxWidth: '500px' }, children: _jsx(Trans, { i18nKey: "app.drawer.user.apikey.description" }) }), amount && unit && dayjs.duration(amount, unit).asSeconds() < dayjs.duration(7, 'days').asSeconds() && (_jsxs(Alert, { severity: "warning", variant: "outlined", sx: { maxWidth: '500px' }, children: [_jsx(AlertTitle, { children: t('app.drawer.user.apikey.limit.title') }), t('app.drawer.user.apikey.limit.description'), " (", maxDate?.format('MMM D HH:mm:ss'), ")"] })), _jsx(TextField, { label: t('app.drawer.user.apikey.field.name'), required: true, fullWidth: true, value: keyName, onChange: onChange }), _jsxs(FormControl, { required: true, children: [_jsx(FormLabel, { component: "legend", children: t('app.drawer.user.apikey.permissions') }), _jsxs(FormGroup, { sx: { display: 'grid', gridTemplateColumns: '1fr 1fr' }, children: [_jsx(FormControlLabel, { control: _jsx(Checkbox, { onChange: updatePrivs('R') }), label: t('@cccsaurora/howler-ui/apikey.read') }), _jsx(FormControlLabel, { control: _jsx(Checkbox, { onChange: updatePrivs('W') }), label: t('@cccsaurora/howler-ui/apikey.write') }), _jsx(FormControlLabel, { disabled: privs.includes('E'), control: _jsx(Checkbox, { onChange: updatePrivs('I') }), label: t('@cccsaurora/howler-ui/apikey.impersonate') }), config.configuration.auth.allow_extended_apikeys && (_jsx(FormControlLabel, { disabled: privs.includes('I'), control: _jsx(Checkbox, { onChange: updatePrivs('E') }), label: t('@cccsaurora/howler-ui/apikey.extended') }))] })] }), _jsxs(FormControl, { required: !!maxDate, children: [_jsx(FormLabel, { children: t('app.drawer.user.apikey.expiry.date') }), _jsx(StaticDateTimePicker, { orientation: "landscape", ampm: false, value: expiryDate, onChange: newValue => setExpiryDate(newValue), disablePast: true, maxDate: maxDate, maxTime: maxDate, sx: { backgroundColor: 'transparent', '& > div:first-of-type': { maxWidth: '300px' } } })] }), _jsx(Button, { onClick: onSubmit, disabled: !keyName || (!privs.includes('R') && !privs.includes('W')) || (maxDate && !expiryDate), variant: "outlined", children: _jsx(Trans, { i18nKey: "button.create" }) }), createdKey && (_jsxs(_Fragment, { children: [_jsx(Divider, { orientation: "horizontal" }), _jsxs(Stack, { direction: "row", spacing: 1, alignItems: "stretch", children: [_jsx(TextField, { size: "small", value: createdKey, inputProps: { readOnly: true }, fullWidth: true }), _jsx(Button, { variant: "outlined", onClick: onCopy, disabled: !createdKey, children: _jsx(Trans, { i18nKey: "button.copy" }) })] })] }))] }) }));
|
|
66
66
|
};
|
|
67
67
|
export default ApiKeyDrawer;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
import { has } from 'lodash-es';
|
|
2
3
|
import { useCallback } from 'react';
|
|
3
4
|
import { useContextSelector } from 'use-context-selector';
|
|
@@ -13,7 +14,13 @@ const useMatchers = () => {
|
|
|
13
14
|
}
|
|
14
15
|
// This is a fallback in case metadata is not included. In most cases templates are shown, the template metadata
|
|
15
16
|
// should also exist
|
|
16
|
-
|
|
17
|
+
try {
|
|
18
|
+
return (await getHit(hit.howler.id, true)).__template;
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
console.warn(e);
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
17
24
|
}, [getHit]);
|
|
18
25
|
const getMatchingOverview = useCallback(async (hit) => {
|
|
19
26
|
if (!hit) {
|
|
@@ -24,7 +31,13 @@ const useMatchers = () => {
|
|
|
24
31
|
}
|
|
25
32
|
// This is a fallback in case metadata is not included. In most cases templates are shown, the template metadata
|
|
26
33
|
// should also exist
|
|
27
|
-
|
|
34
|
+
try {
|
|
35
|
+
return (await getHit(hit.howler.id, true)).__overview;
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
console.warn(e);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
28
41
|
}, [getHit]);
|
|
29
42
|
const getMatchingDossiers = useCallback(async (hit) => {
|
|
30
43
|
if (!hit) {
|
|
@@ -35,7 +48,13 @@ const useMatchers = () => {
|
|
|
35
48
|
}
|
|
36
49
|
// This is a fallback in case metadata is not included. In most cases templates are shown, the template metadata
|
|
37
50
|
// should also exist
|
|
38
|
-
|
|
51
|
+
try {
|
|
52
|
+
return (await getHit(hit.howler.id, true)).__dossiers ?? [];
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
console.warn(e);
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
39
58
|
}, [getHit]);
|
|
40
59
|
const getMatchingAnalytic = useCallback(async (hit) => {
|
|
41
60
|
if (!hit) {
|
|
@@ -45,7 +64,13 @@ const useMatchers = () => {
|
|
|
45
64
|
return hit.__analytic;
|
|
46
65
|
}
|
|
47
66
|
// This is a fallback in case metadata is not included.
|
|
48
|
-
|
|
67
|
+
try {
|
|
68
|
+
return (await getHit(hit.howler.id, true)).__analytic;
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
console.warn(e);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
49
74
|
}, [getHit]);
|
|
50
75
|
return {
|
|
51
76
|
getMatchingDossiers,
|
|
@@ -86,7 +86,7 @@ describe('useMatchers', () => {
|
|
|
86
86
|
has.mockReturnValue(false);
|
|
87
87
|
mockGetHit.mockRejectedValue(new Error('Failed to fetch hit'));
|
|
88
88
|
const { result } = renderHook(() => useMatchers());
|
|
89
|
-
await expect(result.current.getMatchingTemplate(mockHit)).
|
|
89
|
+
await expect(result.current.getMatchingTemplate(mockHit)).resolves.toBeNull();
|
|
90
90
|
expect(mockGetHit).toHaveBeenCalledWith('test-hit-id', true);
|
|
91
91
|
});
|
|
92
92
|
});
|
|
@@ -124,7 +124,7 @@ describe('useMatchers', () => {
|
|
|
124
124
|
has.mockReturnValue(false);
|
|
125
125
|
mockGetHit.mockRejectedValue(new Error('Failed to fetch hit'));
|
|
126
126
|
const { result } = renderHook(() => useMatchers());
|
|
127
|
-
await expect(result.current.getMatchingOverview(mockHit)).
|
|
127
|
+
await expect(result.current.getMatchingOverview(mockHit)).resolves.toBeNull();
|
|
128
128
|
expect(mockGetHit).toHaveBeenCalledWith('test-hit-id', true);
|
|
129
129
|
});
|
|
130
130
|
});
|
|
@@ -162,7 +162,7 @@ describe('useMatchers', () => {
|
|
|
162
162
|
has.mockReturnValue(false);
|
|
163
163
|
mockGetHit.mockRejectedValue(new Error('Failed to fetch hit'));
|
|
164
164
|
const { result } = renderHook(() => useMatchers());
|
|
165
|
-
await expect(result.current.getMatchingDossiers(mockHit)).
|
|
165
|
+
await expect(result.current.getMatchingDossiers(mockHit)).resolves.toEqual([]);
|
|
166
166
|
expect(mockGetHit).toHaveBeenCalledWith('test-hit-id', true);
|
|
167
167
|
});
|
|
168
168
|
});
|
|
@@ -2,15 +2,15 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { CenterFocusWeak, Refresh } from '@mui/icons-material';
|
|
3
3
|
import { Alert, AlertTitle, Autocomplete, Box, Button, CircularProgress, IconButton, Stack, TextField, Tooltip, alpha, useTheme } from '@mui/material';
|
|
4
4
|
import api from '@cccsaurora/howler-ui/api';
|
|
5
|
-
import 'chartjs-adapter-
|
|
5
|
+
import 'chartjs-adapter-dayjs';
|
|
6
6
|
import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
|
|
7
7
|
import { HitContext } from '@cccsaurora/howler-ui/components/app/providers/HitProvider';
|
|
8
8
|
import { HitSearchContext } from '@cccsaurora/howler-ui/components/app/providers/HitSearchProvider';
|
|
9
9
|
import { ParameterContext } from '@cccsaurora/howler-ui/components/app/providers/ParameterProvider';
|
|
10
10
|
import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
|
|
11
11
|
import useMyChart from '@cccsaurora/howler-ui/components/hooks/useMyChart';
|
|
12
|
+
import dayjs from 'dayjs';
|
|
12
13
|
import { capitalize } from 'lodash-es';
|
|
13
|
-
import moment from 'moment';
|
|
14
14
|
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
15
15
|
import { Scatter } from 'react-chartjs-2';
|
|
16
16
|
import { useTranslation } from 'react-i18next';
|
|
@@ -96,10 +96,10 @@ const HitGraph = ({ query }) => {
|
|
|
96
96
|
return {
|
|
97
97
|
label: `${label} (${category.total})`,
|
|
98
98
|
data: category.items.map(hit => {
|
|
99
|
-
const
|
|
99
|
+
const createdDate = dayjs(hit.event?.created ?? hit.timestamp);
|
|
100
100
|
return {
|
|
101
|
-
x:
|
|
102
|
-
y:
|
|
101
|
+
x: createdDate.clone().hour(0).minute(0).second(0).toISOString(),
|
|
102
|
+
y: createdDate.hour() + createdDate.minute() / 60 + createdDate.second() / 3600,
|
|
103
103
|
hit,
|
|
104
104
|
label
|
|
105
105
|
};
|
|
@@ -157,7 +157,7 @@ const HitGraph = ({ query }) => {
|
|
|
157
157
|
tooltip: {
|
|
158
158
|
callbacks: {
|
|
159
159
|
title: entries => `${entries.length} ${t('hits')}`,
|
|
160
|
-
label: entry => `${entry.raw.hit.howler.analytic}: ${entry.raw.hit.howler.detection} (${
|
|
160
|
+
label: entry => `${entry.raw.hit.howler.analytic}: ${entry.raw.hit.howler.detection} (${dayjs(entry.raw.hit.event.created).format('MMM D HH:mm:ss')})`,
|
|
161
161
|
afterLabel: entry => `${entry.raw.hit.howler.outline.threat} ${entry.raw.hit.howler.outline.target}`
|
|
162
162
|
}
|
|
163
163
|
},
|
|
@@ -183,7 +183,7 @@ const HitGraph = ({ query }) => {
|
|
|
183
183
|
ticks: {
|
|
184
184
|
callback: (value) => {
|
|
185
185
|
const [hour, minute] = [Math.floor(value), Math.floor((value - Math.floor(value)) * 60)];
|
|
186
|
-
return
|
|
186
|
+
return dayjs().hour(hour).minute(minute).format('HH:mm');
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Chip, Tooltip } from '@mui/material';
|
|
3
3
|
import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
|
|
4
|
-
import
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
5
|
import { useContext, useMemo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { formatDate } from '@cccsaurora/howler-ui/utils/utils';
|
|
@@ -14,31 +14,31 @@ const TIMESTAMP_MESSAGES = {
|
|
|
14
14
|
const HitTimestamp = ({ hit, layout }) => {
|
|
15
15
|
const { t } = useTranslation();
|
|
16
16
|
const { config } = useContext(ApiConfigContext);
|
|
17
|
-
const threshold = useMemo(() =>
|
|
17
|
+
const threshold = useMemo(() => dayjs().subtract(config.configuration.system.retention?.limit_amount ?? 350, config.configuration.system.retention?.limit_unit ?? 'days'), [config.configuration.system.retention?.limit_amount, config.configuration.system.retention?.limit_unit]);
|
|
18
18
|
const timestamp = useMemo(() => {
|
|
19
19
|
const validFieldValues = [hit.howler?.expiry, hit.event?.created, hit.timestamp];
|
|
20
20
|
const earliestDate = validFieldValues
|
|
21
21
|
.filter(entry => !!entry)
|
|
22
22
|
.reduce((earliest, current) => {
|
|
23
|
-
return
|
|
23
|
+
return dayjs(earliest).isBefore(current) ? earliest : current;
|
|
24
24
|
});
|
|
25
25
|
return earliestDate;
|
|
26
26
|
}, [hit]);
|
|
27
27
|
const color = useMemo(() => {
|
|
28
|
-
if (
|
|
28
|
+
if (dayjs(timestamp).isBefore(threshold.clone().add(2, 'weeks'))) {
|
|
29
29
|
return 'error';
|
|
30
30
|
}
|
|
31
|
-
if (
|
|
31
|
+
if (dayjs(timestamp).isBefore(threshold.clone().add(1, 'months'))) {
|
|
32
32
|
return 'warning';
|
|
33
33
|
}
|
|
34
34
|
return 'default';
|
|
35
35
|
}, [threshold, timestamp]);
|
|
36
36
|
const duration = useMemo(() => {
|
|
37
|
-
if (
|
|
37
|
+
if (dayjs(timestamp).isBefore(threshold)) {
|
|
38
38
|
return t('retention.imminent');
|
|
39
39
|
}
|
|
40
|
-
const diff =
|
|
41
|
-
const _duration =
|
|
40
|
+
const diff = dayjs(timestamp).diff(threshold, 'seconds');
|
|
41
|
+
const _duration = dayjs.duration(diff, 'seconds');
|
|
42
42
|
return _duration.humanize();
|
|
43
43
|
}, [t, threshold, timestamp]);
|
|
44
44
|
return (_jsx(Tooltip, { title: t(TIMESTAMP_MESSAGES[color], {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useTheme } from '@mui/material';
|
|
2
2
|
import { ArcElement, BarElement, CategoryScale, Chart as ChartJS, Filler, Legend, LinearScale, LineElement, PointElement, SubTitle, TimeScale, Title, Tooltip } from 'chart.js';
|
|
3
|
-
import 'chartjs-adapter-
|
|
3
|
+
import 'chartjs-adapter-dayjs';
|
|
4
4
|
import zoomPlugin from 'chartjs-plugin-zoom';
|
|
5
5
|
import { useCallback } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
@@ -13,7 +13,7 @@ import CustomButton from '@cccsaurora/howler-ui/components/elements/addons/butto
|
|
|
13
13
|
import FlexOne from '@cccsaurora/howler-ui/components/elements/addons/layout/FlexOne';
|
|
14
14
|
import JSONViewer from '@cccsaurora/howler-ui/components/elements/display/json/JSONViewer';
|
|
15
15
|
import useMySnackbar from '@cccsaurora/howler-ui/components/hooks/useMySnackbar';
|
|
16
|
-
import
|
|
16
|
+
import dayjs from 'dayjs';
|
|
17
17
|
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
18
18
|
import { useTranslation } from 'react-i18next';
|
|
19
19
|
import { Link } from 'react-router-dom';
|
|
@@ -41,8 +41,8 @@ description: A basic example of using sigma rule notation to query howler
|
|
|
41
41
|
references:
|
|
42
42
|
- https://github.com/SigmaHQ/sigma
|
|
43
43
|
author: You
|
|
44
|
-
date: ${
|
|
45
|
-
modified: ${
|
|
44
|
+
date: ${dayjs().format('YYYY/MM/DD')}
|
|
45
|
+
modified: ${dayjs().format('YYYY/MM/DD')}
|
|
46
46
|
tags:
|
|
47
47
|
- attack.command_and_control
|
|
48
48
|
logsource:
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { Check, Edit } from '@mui/icons-material';
|
|
3
3
|
import { Alert, AlertTitle, Box, Card, CardContent, CircularProgress, Divider, IconButton, Skeleton, Stack, TextField, Typography, useMediaQuery, useTheme } from '@mui/material';
|
|
4
4
|
import api from '@cccsaurora/howler-ui/api';
|
|
5
|
-
import 'chartjs-adapter-
|
|
5
|
+
import 'chartjs-adapter-dayjs';
|
|
6
6
|
import Markdown from '@cccsaurora/howler-ui/components/elements/display/Markdown';
|
|
7
7
|
import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
|
|
8
8
|
import useMySnackbar from '@cccsaurora/howler-ui/components/hooks/useMySnackbar';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Article } from '@mui/icons-material';
|
|
3
3
|
import { Box, Fab, Skeleton, Stack, Typography, useMediaQuery } from '@mui/material';
|
|
4
|
-
import 'chartjs-adapter-
|
|
4
|
+
import 'chartjs-adapter-dayjs';
|
|
5
5
|
import AppListEmpty from '@cccsaurora/howler-ui/commons/components/display/AppListEmpty';
|
|
6
6
|
import { OverviewContext } from '@cccsaurora/howler-ui/components/app/providers/OverviewProvider';
|
|
7
7
|
import { useContext, useEffect, useMemo, useState } from 'react';
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Article } from '@mui/icons-material';
|
|
3
3
|
import { Box, Fab, Skeleton, Stack, Typography, useMediaQuery } from '@mui/material';
|
|
4
4
|
import api from '@cccsaurora/howler-ui/api';
|
|
5
|
-
import 'chartjs-adapter-
|
|
5
|
+
import 'chartjs-adapter-dayjs';
|
|
6
6
|
import AppListEmpty from '@cccsaurora/howler-ui/commons/components/display/AppListEmpty';
|
|
7
7
|
import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
|
|
8
8
|
import { useEffect, useState } from 'react';
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Check, Edit } from '@mui/icons-material';
|
|
3
3
|
import { Box, CircularProgress, IconButton, Stack, Typography, useTheme } from '@mui/material';
|
|
4
4
|
import api from '@cccsaurora/howler-ui/api';
|
|
5
|
-
import 'chartjs-adapter-
|
|
5
|
+
import 'chartjs-adapter-dayjs';
|
|
6
6
|
import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
|
|
7
7
|
import useMySnackbar from '@cccsaurora/howler-ui/components/hooks/useMySnackbar';
|
|
8
8
|
import { useCallback, useState } from 'react';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Checkbox, Divider, Grid, Paper, Stack, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Tooltip, Typography } from '@mui/material';
|
|
3
3
|
import api from '@cccsaurora/howler-ui/api';
|
|
4
|
-
import 'chartjs-adapter-
|
|
4
|
+
import 'chartjs-adapter-dayjs';
|
|
5
5
|
import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
|
|
6
6
|
import EditRow from '@cccsaurora/howler-ui/components/elements/EditRow';
|
|
7
7
|
import useMyApi from '@cccsaurora/howler-ui/components/hooks/useMyApi';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Skeleton, Typography } from '@mui/material';
|
|
3
3
|
import api from '@cccsaurora/howler-ui/api';
|
|
4
|
-
import 'chartjs-adapter-
|
|
4
|
+
import 'chartjs-adapter-dayjs';
|
|
5
5
|
import useMyChart from '@cccsaurora/howler-ui/components/hooks/useMyChart';
|
|
6
6
|
import { forwardRef, useEffect, useState } from 'react';
|
|
7
7
|
import { Bar } from 'react-chartjs-2';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Skeleton } from '@mui/material';
|
|
3
3
|
import api from '@cccsaurora/howler-ui/api';
|
|
4
|
-
import 'chartjs-adapter-
|
|
4
|
+
import 'chartjs-adapter-dayjs';
|
|
5
5
|
import useMyChart from '@cccsaurora/howler-ui/components/hooks/useMyChart';
|
|
6
6
|
import { forwardRef, useEffect, useState } from 'react';
|
|
7
7
|
import { Line } from 'react-chartjs-2';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Skeleton, useTheme } from '@mui/material';
|
|
3
3
|
import api from '@cccsaurora/howler-ui/api';
|
|
4
|
-
import 'chartjs-adapter-
|
|
4
|
+
import 'chartjs-adapter-dayjs';
|
|
5
5
|
import useMyChart from '@cccsaurora/howler-ui/components/hooks/useMyChart';
|
|
6
6
|
import { forwardRef, useEffect, useMemo, useState } from 'react';
|
|
7
7
|
import { Doughnut } from 'react-chartjs-2';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Skeleton } from '@mui/material';
|
|
3
3
|
import api from '@cccsaurora/howler-ui/api';
|
|
4
|
-
import 'chartjs-adapter-
|
|
4
|
+
import 'chartjs-adapter-dayjs';
|
|
5
5
|
import useMyChart from '@cccsaurora/howler-ui/components/hooks/useMyChart';
|
|
6
6
|
import sum from 'lodash-es/sum';
|
|
7
7
|
import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useTheme } from '@mui/material';
|
|
3
|
-
import 'chartjs-adapter-
|
|
3
|
+
import 'chartjs-adapter-dayjs';
|
|
4
4
|
import { forwardRef } from 'react';
|
|
5
5
|
import { STATUS_COLORS } from '@cccsaurora/howler-ui/utils/constants';
|
|
6
6
|
import Stacked from './Stacked';
|
|
@@ -5,7 +5,7 @@ import Markdown from '@cccsaurora/howler-ui/components/elements/display/Markdown
|
|
|
5
5
|
import { HitLayout } from '@cccsaurora/howler-ui/components/elements/hit/HitLayout';
|
|
6
6
|
import DefaultOutline from '@cccsaurora/howler-ui/components/elements/hit/outlines/DefaultOutline';
|
|
7
7
|
import { useScrollRestoration } from '@cccsaurora/howler-ui/components/hooks/useScrollRestoration';
|
|
8
|
-
import
|
|
8
|
+
import dayjs from 'dayjs';
|
|
9
9
|
import { useMemo } from 'react';
|
|
10
10
|
import { useTranslation } from 'react-i18next';
|
|
11
11
|
import TEMPLATES_EN from './markdown/en/templates.md';
|
|
@@ -14,8 +14,8 @@ const ALERTS = [
|
|
|
14
14
|
{
|
|
15
15
|
howler: { id: 'hit1', analytic: 'Cat Checker', detection: 'Listening for Meows' },
|
|
16
16
|
event: {
|
|
17
|
-
start:
|
|
18
|
-
end:
|
|
17
|
+
start: dayjs().subtract(4, 'hour').toString(),
|
|
18
|
+
end: dayjs().subtract(3, 'hour').toString(),
|
|
19
19
|
kind: 'Loud meow',
|
|
20
20
|
outcome: 'Food provided'
|
|
21
21
|
}
|
|
@@ -23,8 +23,8 @@ const ALERTS = [
|
|
|
23
23
|
{
|
|
24
24
|
howler: { id: 'hit2', analytic: 'Cat Checker', detection: 'Looking for paw prints' },
|
|
25
25
|
event: {
|
|
26
|
-
start:
|
|
27
|
-
end:
|
|
26
|
+
start: dayjs().subtract(6, 'hour').toString(),
|
|
27
|
+
end: dayjs().subtract(5, 'hour').toString(),
|
|
28
28
|
provider: "The neighbour's cat (probably)",
|
|
29
29
|
reason: 'There was some fish we forgot to put away in the kitchen'
|
|
30
30
|
}
|
|
@@ -10,8 +10,8 @@ import FlexPort from '@cccsaurora/howler-ui/components/elements/addons/layout/Fl
|
|
|
10
10
|
import HitSummary from '@cccsaurora/howler-ui/components/elements/hit/HitSummary';
|
|
11
11
|
import { useMyLocalStorageItem } from '@cccsaurora/howler-ui/components/hooks/useMyLocalStorage';
|
|
12
12
|
import ErrorBoundary from '@cccsaurora/howler-ui/components/routes/ErrorBoundary';
|
|
13
|
+
import dayjs from 'dayjs';
|
|
13
14
|
import { has, isNull } from 'lodash-es';
|
|
14
|
-
import moment from 'moment';
|
|
15
15
|
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
|
16
16
|
import { Trans, useTranslation } from 'react-i18next';
|
|
17
17
|
import { useLocation, useParams, useSearchParams } from 'react-router-dom';
|
|
@@ -88,7 +88,7 @@ const HitBrowser = () => {
|
|
|
88
88
|
useEffect(() => {
|
|
89
89
|
// On load check to filter out any queries older than one month
|
|
90
90
|
setQueryHistory(_queryHistory => {
|
|
91
|
-
const filterQueryTime =
|
|
91
|
+
const filterQueryTime = dayjs().subtract(1, 'month').toISOString();
|
|
92
92
|
return Object.fromEntries(Object.entries(_queryHistory).filter(([_, value]) => value > filterQueryTime));
|
|
93
93
|
});
|
|
94
94
|
}, [setQueryHistory]);
|
|
@@ -56,16 +56,15 @@ const InformationPane = ({ onClose }) => {
|
|
|
56
56
|
const [hasOverview, setHasOverview] = useState(false);
|
|
57
57
|
const [tab, setTab] = useState('overview');
|
|
58
58
|
const [loading, setLoading] = useState(false);
|
|
59
|
-
const [dossiers, setDossiers] = useState([]);
|
|
60
59
|
const [filter, setFilter] = useState('');
|
|
60
|
+
// In order to properly check for dossiers, we split dossiers into two
|
|
61
|
+
const [_dossiers, setDossiers] = useState(null);
|
|
62
|
+
const dossiers = useMemo(() => _dossiers ?? [], [_dossiers]);
|
|
61
63
|
const users = useMyUserList(userIds);
|
|
62
64
|
const hit = useContextSelector(HitContext, ctx => ctx.hits[selected]);
|
|
63
65
|
howlerPluginStore.plugins.forEach(plugin => {
|
|
64
66
|
pluginStore.executeFunction(`${plugin}.on`, 'viewing');
|
|
65
67
|
});
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
getMatchingOverview(hit).then(_overview => setHasOverview(!!_overview));
|
|
68
|
-
}, [getMatchingOverview, hit]);
|
|
69
68
|
useEffect(() => {
|
|
70
69
|
if (!selected) {
|
|
71
70
|
return;
|
|
@@ -76,10 +75,21 @@ const InformationPane = ({ onClose }) => {
|
|
|
76
75
|
return;
|
|
77
76
|
}
|
|
78
77
|
setUserIds(getUserList(hit));
|
|
79
|
-
getMatchingAnalytic(hit).then(setAnalytic);
|
|
80
|
-
getMatchingDossiers(hit).then(setDossiers);
|
|
81
78
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
82
79
|
}, [getHit, selected]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (hit && !analytic) {
|
|
82
|
+
getMatchingAnalytic(hit).then(setAnalytic);
|
|
83
|
+
}
|
|
84
|
+
}, [analytic, getMatchingAnalytic, hit]);
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (hit && !_dossiers) {
|
|
87
|
+
getMatchingDossiers(hit).then(setDossiers);
|
|
88
|
+
}
|
|
89
|
+
}, [_dossiers, getMatchingDossiers, hit]);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
getMatchingOverview(hit).then(_overview => setHasOverview(!!_overview));
|
|
92
|
+
}, [getMatchingOverview, hit]);
|
|
83
93
|
useEffect(() => {
|
|
84
94
|
if (tab === 'hit_aggregate' && !hit?.howler.is_bundle) {
|
|
85
95
|
setTab('overview');
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Stack } from '@mui/material';
|
|
3
3
|
import { LocalizationProvider } from '@mui/x-date-pickers';
|
|
4
|
-
import {
|
|
4
|
+
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
|
5
5
|
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
|
|
6
6
|
import { ParameterContext } from '@cccsaurora/howler-ui/components/app/providers/ParameterProvider';
|
|
7
|
-
import
|
|
7
|
+
import dayjs from 'dayjs';
|
|
8
8
|
import { memo, useEffect } from 'react';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
10
|
import { useContextSelector } from 'use-context-selector';
|
|
11
11
|
const CustomSpan = () => {
|
|
12
12
|
const { t } = useTranslation();
|
|
13
13
|
const span = useContextSelector(ParameterContext, ctx => ctx.span);
|
|
14
|
-
const startDate = useContextSelector(ParameterContext, ctx => (ctx.startDate ?
|
|
14
|
+
const startDate = useContextSelector(ParameterContext, ctx => (ctx.startDate ? dayjs(ctx.startDate) : null));
|
|
15
15
|
const setCustomSpan = useContextSelector(ParameterContext, ctx => ctx.setCustomSpan);
|
|
16
|
-
const endDate = useContextSelector(ParameterContext, ctx => (ctx.endDate ?
|
|
16
|
+
const endDate = useContextSelector(ParameterContext, ctx => (ctx.endDate ? dayjs(ctx.endDate) : null));
|
|
17
17
|
useEffect(() => {
|
|
18
18
|
if (span?.endsWith('custom') && (!startDate || !endDate)) {
|
|
19
|
-
setCustomSpan(
|
|
19
|
+
setCustomSpan(dayjs().subtract(3, 'days').toISOString(), dayjs().toISOString());
|
|
20
20
|
}
|
|
21
21
|
}, [endDate, setCustomSpan, span, startDate]);
|
|
22
|
-
return span?.endsWith('custom') ? (_jsx(LocalizationProvider, { dateAdapter:
|
|
22
|
+
return span?.endsWith('custom') ? (_jsx(LocalizationProvider, { dateAdapter: AdapterDayjs, children: _jsxs(Stack, { direction: "row", spacing: 1, useFlexGap: true, flexWrap: "wrap", children: [_jsx(DateTimePicker, { sx: { minWidth: '175px', flexGrow: 1, marginTop: 1 }, slotProps: { textField: { size: 'small' } }, label: t('date.select.start'), value: startDate ? dayjs(startDate) : dayjs().subtract(1, 'days'), maxDate: endDate, onChange: (newStartDate) => setCustomSpan(newStartDate.toISOString(), endDate.toISOString()), ampm: false, disableFuture: true }), _jsx(DateTimePicker, { sx: { minWidth: '175px', flexGrow: 1, marginTop: 1 }, slotProps: { textField: { size: 'small' } }, label: t('date.select.end'), value: endDate, minDate: startDate, onChange: (newEndDate) => setCustomSpan(startDate.toISOString(), newEndDate.toISOString()), ampm: false, disableFuture: true })] }) })) : null;
|
|
23
23
|
};
|
|
24
24
|
export default memo(CustomSpan);
|
|
@@ -10,8 +10,8 @@ import PageCenter from '@cccsaurora/howler-ui/commons/components/pages/PageCente
|
|
|
10
10
|
import CustomButton from '@cccsaurora/howler-ui/components/elements/addons/buttons/CustomButton';
|
|
11
11
|
import { useMyLocalStorageItem } from '@cccsaurora/howler-ui/components/hooks/useMyLocalStorage';
|
|
12
12
|
import useMyUserFunctions from '@cccsaurora/howler-ui/components/hooks/useMyUserFunctions';
|
|
13
|
+
import dayjs from 'dayjs';
|
|
13
14
|
import isEqual from 'lodash-es/isEqual';
|
|
14
|
-
import moment from 'moment';
|
|
15
15
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
16
16
|
import { useTranslation } from 'react-i18next';
|
|
17
17
|
import { Link } from 'react-router-dom';
|
|
@@ -26,7 +26,7 @@ const Home = () => {
|
|
|
26
26
|
const { user, setUser } = useAppUser();
|
|
27
27
|
const { setDashboard } = useMyUserFunctions();
|
|
28
28
|
const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
|
|
29
|
-
const [lastViewed, setLastViewed] = useMyLocalStorageItem(StorageKey.LAST_VIEW,
|
|
29
|
+
const [lastViewed, setLastViewed] = useMyLocalStorageItem(StorageKey.LAST_VIEW, dayjs().utc().format(LUCENE_DATE_FMT));
|
|
30
30
|
const [loading, setLoading] = useState(false);
|
|
31
31
|
const [isEditing, setIsEditing] = useState(false);
|
|
32
32
|
const [updatedHitTotal, setUpdatedHitTotal] = useState(0);
|
|
@@ -81,8 +81,8 @@ const Home = () => {
|
|
|
81
81
|
})
|
|
82
82
|
.then(result => setUpdatedHitTotal(result.total));
|
|
83
83
|
}, [updateQuery]);
|
|
84
|
-
return (_jsx(PageCenter, { maxWidth: "1800px", textAlign: "left", height: "100%", children: _jsxs(Stack, { direction: "column", spacing: 1, sx: { height: '100%' }, children: [_jsxs(Stack, { direction: "row", justifyContent: "end", spacing: 1, children: [isEditing && (_jsx(CustomButton, { variant: "outlined", size: "small", color: "error", startIcon: _jsx(Cancel, {}), onClick: discardChanges, children: t('cancel') })), _jsx(CustomButton, { variant: "outlined", size: "small", disabled: isEditing && isEqual(dashboard, user.dashboard), color: isEditing ? 'success' : 'primary', startIcon: isEditing ? loading ? _jsx(CircularProgress, { size: 20 }) : _jsx(Check, {}) : _jsx(Edit, {}), onClick: () => (!isEditing ? setIsEditing(true) : saveChanges()), children: t(isEditing ? 'save' : 'edit') })] }), updatedHitTotal > 0 && (_jsxs(Alert, { severity: "info", variant: "outlined", action: _jsxs(Stack, { spacing: 1, direction: "row", children: [_jsx(IconButton, { color: "info", component: Link, to: `/hits?query=${encodeURIComponent(updateQuery)}`, onClick: () => setLastViewed(
|
|
85
|
-
setLastViewed(
|
|
84
|
+
return (_jsx(PageCenter, { maxWidth: "1800px", textAlign: "left", height: "100%", children: _jsxs(Stack, { direction: "column", spacing: 1, sx: { height: '100%' }, children: [_jsxs(Stack, { direction: "row", justifyContent: "end", spacing: 1, children: [isEditing && (_jsx(CustomButton, { variant: "outlined", size: "small", color: "error", startIcon: _jsx(Cancel, {}), onClick: discardChanges, children: t('cancel') })), _jsx(CustomButton, { variant: "outlined", size: "small", disabled: isEditing && isEqual(dashboard, user.dashboard), color: isEditing ? 'success' : 'primary', startIcon: isEditing ? loading ? _jsx(CircularProgress, { size: 20 }) : _jsx(Check, {}) : _jsx(Edit, {}), onClick: () => (!isEditing ? setIsEditing(true) : saveChanges()), children: t(isEditing ? 'save' : 'edit') })] }), updatedHitTotal > 0 && (_jsxs(Alert, { severity: "info", variant: "outlined", action: _jsxs(Stack, { spacing: 1, direction: "row", children: [_jsx(IconButton, { color: "info", component: Link, to: `/hits?query=${encodeURIComponent(updateQuery)}`, onClick: () => setLastViewed(dayjs().utc().format(LUCENE_DATE_FMT)), children: _jsx(OpenInNew, {}) }), _jsx(IconButton, { color: "info", onClick: () => {
|
|
85
|
+
setLastViewed(dayjs().utc().format(LUCENE_DATE_FMT));
|
|
86
86
|
setUpdatedHitTotal(0);
|
|
87
87
|
}, children: _jsx(Close, {}) })] }), children: [_jsx(AlertTitle, { children: t('route.home.alert.updated.title') }), t('route.home.alert.updated.description', { count: updatedHitTotal })] })), _jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, children: _jsx(SortableContext, { items: (dashboard ?? []).map(entry => getIdFromEntry(entry)), children: _jsxs(Grid, { container: true, spacing: 1, alignItems: "stretch", sx: [
|
|
88
88
|
theme => ({
|
|
@@ -3,7 +3,7 @@ import { Add } from '@mui/icons-material';
|
|
|
3
3
|
import { Chip, Grid, IconButton, TableCell, TableRow } from '@mui/material';
|
|
4
4
|
import { ApiConfigContext } from '@cccsaurora/howler-ui/components/app/providers/ApiConfigProvider';
|
|
5
5
|
import useMyLocalStorage from '@cccsaurora/howler-ui/components/hooks/useMyLocalStorage';
|
|
6
|
-
import
|
|
6
|
+
import dayjs from 'dayjs';
|
|
7
7
|
import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
|
|
8
8
|
import { useContext, useMemo } from 'react';
|
|
9
9
|
import { Trans, useTranslation } from 'react-i18next';
|
|
@@ -26,6 +26,6 @@ const SecuritySection = ({ user, editPassword, addApiKey, removeApiKey, editQuot
|
|
|
26
26
|
return (_jsxs(SettingsSection, { title: t('page.settings.security.title'), colSpan: 3, children: [!isOAuth && editPassword && (_jsx(EditRow, { titleKey: "page.settings.security.table.password", value: "\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF\u25CF", onEdit: editPassword, type: "password" })), config?.configuration.auth.allow_apikeys && (_jsxs(TableRow, { sx: { cursor: 'pointer' }, children: [_jsx(TableCell, { style: { whiteSpace: 'nowrap' }, children: t('page.settings.security.table.apikeys') }), _jsx(TableCell, { width: "100%", children: _jsxs(Grid, { container: true, spacing: 1, children: [user?.apikeys?.map(apiKey => (_jsx(Grid, { item: true, children: _jsx(Chip, { label: apiKey[0].toLocaleLowerCase() +
|
|
27
27
|
(apiKey[1].length > 0
|
|
28
28
|
? ` (${apiKey[1].map(permission => t(APIKEY_LABELS[permission])).join(', ')})`
|
|
29
|
-
: ''), style: { backgroundColor:
|
|
29
|
+
: ''), style: { backgroundColor: dayjs.utc(apiKey[2]).isBefore(dayjs().utc()) ? 'orange' : 'default' }, onDelete: removeApiKey ? () => removeApiKey(apiKey) : null }) }, apiKey[0]))), user?.apikeys?.length < 1 && (_jsx(Grid, { item: true, children: _jsx(Trans, { i18nKey: "none" }) }))] }) }), _jsx(TableCell, { align: "right", children: addApiKey && (_jsx(IconButton, { onClick: addApiKey, children: _jsx(Add, { fontSize: "small" }) })) })] })), _jsx(EditRow, { titleKey: "page.settings.security.table.apiquota", descriptionKey: "page.settings.security.table.apiquota.description", value: user?.api_quota, validate: value => value && /^[0-9]*$/m.test(value.toString()), type: "number", onEdit: editQuota }), howlerPluginStore.plugins.map(plugin => pluginStore.executeFunction(`${plugin}.settings`, 'security'))] }));
|
|
30
30
|
};
|
|
31
31
|
export default SecuritySection;
|
package/index.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import '@fontsource/roboto';
|
|
3
3
|
import App from '@cccsaurora/howler-ui/components/app/App';
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
|
+
import duration from 'dayjs/plugin/duration';
|
|
6
|
+
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
7
|
+
import utc from 'dayjs/plugin/utc';
|
|
4
8
|
import '@cccsaurora/howler-ui/i18n';
|
|
5
9
|
import 'index.css';
|
|
6
10
|
// import howlerPluginStore from '@cccsaurora/howler-ui/plugins/store';
|
|
7
11
|
import * as ReactDOM from 'react-dom/client';
|
|
12
|
+
dayjs.extend(utc);
|
|
13
|
+
dayjs.extend(duration);
|
|
14
|
+
dayjs.extend(relativeTime);
|
|
8
15
|
// This is where you can inject UI plugins to modify Howler's interface.
|
|
9
16
|
// howlerPluginStore.install(new ExamplePlugin());
|
|
10
17
|
ReactDOM.createRoot(document.getElementById('root')).render(_jsx(App, {}));
|
package/package.json
CHANGED
|
@@ -31,10 +31,11 @@
|
|
|
31
31
|
"axios-retry": "^3.9.1",
|
|
32
32
|
"borealis-ui": "0.11.0",
|
|
33
33
|
"chart.js": "^4.5.0",
|
|
34
|
-
"chartjs-adapter-
|
|
34
|
+
"chartjs-adapter-dayjs": "^1.0.0",
|
|
35
35
|
"chartjs-plugin-zoom": "^2.2.0",
|
|
36
36
|
"clsx": "^2.1.1",
|
|
37
37
|
"csstype": "^3.1.3",
|
|
38
|
+
"dayjs": "^1.11.13",
|
|
38
39
|
"dompurify": "^3.2.6",
|
|
39
40
|
"express": "^4.21.2",
|
|
40
41
|
"flat": "^6.0.1",
|
|
@@ -47,7 +48,6 @@
|
|
|
47
48
|
"lodash-es": "^4.17.21",
|
|
48
49
|
"md5": "^2.3.0",
|
|
49
50
|
"mermaid": "^11.10.0",
|
|
50
|
-
"moment": "^2.30.1",
|
|
51
51
|
"monaco-editor": "^0.49.0",
|
|
52
52
|
"notistack": "^3.0.2",
|
|
53
53
|
"react": "^18.3.1",
|
|
@@ -96,163 +96,163 @@
|
|
|
96
96
|
"internal-slot": "1.0.7"
|
|
97
97
|
},
|
|
98
98
|
"type": "module",
|
|
99
|
-
"version": "2.13.0-dev.
|
|
99
|
+
"version": "2.13.0-dev.173",
|
|
100
100
|
"exports": {
|
|
101
101
|
"./i18n": "./i18n.js",
|
|
102
102
|
"./index.css": "./index.css",
|
|
103
|
+
"./utils/*": "./utils/*.js",
|
|
104
|
+
"./utils/*.json": "./utils/*.json",
|
|
105
|
+
"./locales/*.json": "./locales/*.json",
|
|
106
|
+
"./commons/*": "./commons/*.js",
|
|
103
107
|
"./api/*": "./api/*.js",
|
|
104
108
|
"./api": "./api/index.js",
|
|
105
|
-
"./commons/*": "./commons/*.js",
|
|
106
109
|
"./tests/*": "./tests/*.js",
|
|
107
|
-
"./
|
|
108
|
-
"./rest": "./rest/index.js",
|
|
109
|
-
"./locales/*.json": "./locales/*.json",
|
|
110
|
+
"./plugins/*": "./plugins/*.js",
|
|
110
111
|
"./branding/*": "./branding/*.js",
|
|
111
112
|
"./components/*": "./components/*.js",
|
|
113
|
+
"./rest/*": "./rest/*.js",
|
|
114
|
+
"./rest": "./rest/index.js",
|
|
112
115
|
"./models/*": "./models/*.js",
|
|
113
|
-
"./
|
|
114
|
-
"./
|
|
115
|
-
"./
|
|
116
|
-
"./
|
|
117
|
-
"./
|
|
118
|
-
"./
|
|
119
|
-
"./
|
|
120
|
-
"./
|
|
121
|
-
"./
|
|
122
|
-
"./
|
|
123
|
-
"./
|
|
124
|
-
"./
|
|
125
|
-
"./
|
|
116
|
+
"./locales/fr/*.json": "./locales/fr/*.json",
|
|
117
|
+
"./locales/en/*.json": "./locales/en/*.json",
|
|
118
|
+
"./locales/fr/help/*.json": "./locales/fr/help/*.json",
|
|
119
|
+
"./locales/en/help/*.json": "./locales/en/help/*.json",
|
|
120
|
+
"./commons/components/*": "./commons/components/*.js",
|
|
121
|
+
"./commons/components/utils/*": "./commons/components/utils/*.js",
|
|
122
|
+
"./commons/components/topnav/*": "./commons/components/topnav/*.js",
|
|
123
|
+
"./commons/components/app/*": "./commons/components/app/*.js",
|
|
124
|
+
"./commons/components/display/*": "./commons/components/display/*.js",
|
|
125
|
+
"./commons/components/breadcrumbs/*": "./commons/components/breadcrumbs/*.js",
|
|
126
|
+
"./commons/components/search/*": "./commons/components/search/*.js",
|
|
127
|
+
"./commons/components/pages/*": "./commons/components/pages/*.js",
|
|
128
|
+
"./commons/components/notification/*": "./commons/components/notification/*.js",
|
|
129
|
+
"./commons/components/notification": "./commons/components/notification/index.js",
|
|
130
|
+
"./commons/components/leftnav/*": "./commons/components/leftnav/*.js",
|
|
131
|
+
"./commons/components/utils/hooks/*": "./commons/components/utils/hooks/*.js",
|
|
132
|
+
"./commons/components/app/providers/*": "./commons/components/app/providers/*.js",
|
|
133
|
+
"./commons/components/app/hooks/*": "./commons/components/app/hooks/*.js",
|
|
134
|
+
"./commons/components/app/hooks": "./commons/components/app/hooks/index.js",
|
|
135
|
+
"./commons/components/display/hooks/*": "./commons/components/display/hooks/*.js",
|
|
136
|
+
"./commons/components/pages/hooks/*": "./commons/components/pages/hooks/*.js",
|
|
137
|
+
"./commons/components/notification/elements/*": "./commons/components/notification/elements/*.js",
|
|
138
|
+
"./commons/components/notification/elements/item/*": "./commons/components/notification/elements/item/*.js",
|
|
139
|
+
"./api/template/*": "./api/template/*.js",
|
|
140
|
+
"./api/template": "./api/template/index.js",
|
|
126
141
|
"./api/action/*": "./api/action/*.js",
|
|
127
142
|
"./api/action": "./api/action/index.js",
|
|
143
|
+
"./api/user/*": "./api/user/*.js",
|
|
144
|
+
"./api/user": "./api/user/index.js",
|
|
145
|
+
"./api/hit/*": "./api/hit/*.js",
|
|
146
|
+
"./api/hit": "./api/hit/index.js",
|
|
147
|
+
"./api/configs/*": "./api/configs/*.js",
|
|
148
|
+
"./api/configs": "./api/configs/index.js",
|
|
128
149
|
"./api/auth/*": "./api/auth/*.js",
|
|
129
150
|
"./api/auth": "./api/auth/index.js",
|
|
130
151
|
"./api/search/*": "./api/search/*.js",
|
|
131
152
|
"./api/search": "./api/search/index.js",
|
|
153
|
+
"./api/analytic/*": "./api/analytic/*.js",
|
|
154
|
+
"./api/analytic": "./api/analytic/index.js",
|
|
155
|
+
"./api/notebook/*": "./api/notebook/*.js",
|
|
156
|
+
"./api/notebook": "./api/notebook/index.js",
|
|
132
157
|
"./api/view/*": "./api/view/*.js",
|
|
133
158
|
"./api/view": "./api/view/index.js",
|
|
159
|
+
"./api/dossier/*": "./api/dossier/*.js",
|
|
160
|
+
"./api/dossier": "./api/dossier/index.js",
|
|
134
161
|
"./api/overview/*": "./api/overview/*.js",
|
|
135
162
|
"./api/overview": "./api/overview/index.js",
|
|
136
|
-
"./api/hit/*": "./api/hit/*.js",
|
|
137
|
-
"./api/hit": "./api/hit/index.js",
|
|
138
|
-
"./api/template/*": "./api/template/*.js",
|
|
139
|
-
"./api/template": "./api/template/index.js",
|
|
140
|
-
"./api/analytic/notebooks/*": "./api/analytic/notebooks/*.js",
|
|
141
|
-
"./api/analytic/notebooks": "./api/analytic/notebooks/index.js",
|
|
142
|
-
"./api/analytic/comments/*": "./api/analytic/comments/*.js",
|
|
143
|
-
"./api/analytic/comments": "./api/analytic/comments/index.js",
|
|
144
163
|
"./api/user/avatar/*": "./api/user/avatar/*.js",
|
|
145
164
|
"./api/user/avatar": "./api/user/avatar/index.js",
|
|
146
|
-
"./api/
|
|
147
|
-
"./api/
|
|
148
|
-
"./api/search/sigma/*": "./api/search/sigma/*.js",
|
|
149
|
-
"./api/search/histogram/*": "./api/search/histogram/*.js",
|
|
150
|
-
"./api/search/histogram": "./api/search/histogram/index.js",
|
|
165
|
+
"./api/hit/comments/*": "./api/hit/comments/*.js",
|
|
166
|
+
"./api/hit/comments": "./api/hit/comments/index.js",
|
|
151
167
|
"./api/search/grouped/*": "./api/search/grouped/*.js",
|
|
152
168
|
"./api/search/grouped": "./api/search/grouped/index.js",
|
|
153
|
-
"./api/search/
|
|
154
|
-
"./api/search/
|
|
169
|
+
"./api/search/fields/*": "./api/search/fields/*.js",
|
|
170
|
+
"./api/search/fields": "./api/search/fields/index.js",
|
|
155
171
|
"./api/search/eql/*": "./api/search/eql/*.js",
|
|
156
172
|
"./api/search/facet/*": "./api/search/facet/*.js",
|
|
157
173
|
"./api/search/facet": "./api/search/facet/index.js",
|
|
158
|
-
"./api/
|
|
159
|
-
"./api/
|
|
160
|
-
"./
|
|
161
|
-
"./
|
|
162
|
-
"./
|
|
163
|
-
"./
|
|
164
|
-
"./
|
|
165
|
-
"./
|
|
166
|
-
"./
|
|
167
|
-
"./
|
|
168
|
-
"./
|
|
169
|
-
"./
|
|
170
|
-
"./
|
|
171
|
-
"./commons/components/app/hooks/*": "./commons/components/app/hooks/*.js",
|
|
172
|
-
"./commons/components/app/hooks": "./commons/components/app/hooks/index.js",
|
|
173
|
-
"./commons/components/app/providers/*": "./commons/components/app/providers/*.js",
|
|
174
|
-
"./commons/components/notification/elements/*": "./commons/components/notification/elements/*.js",
|
|
175
|
-
"./commons/components/notification/elements/item/*": "./commons/components/notification/elements/item/*.js",
|
|
176
|
-
"./commons/components/pages/hooks/*": "./commons/components/pages/hooks/*.js",
|
|
177
|
-
"./commons/components/display/hooks/*": "./commons/components/display/hooks/*.js",
|
|
178
|
-
"./commons/components/utils/hooks/*": "./commons/components/utils/hooks/*.js",
|
|
179
|
-
"./locales/en/*.json": "./locales/en/*.json",
|
|
180
|
-
"./locales/fr/*.json": "./locales/fr/*.json",
|
|
181
|
-
"./locales/en/help/*.json": "./locales/en/help/*.json",
|
|
182
|
-
"./locales/fr/help/*.json": "./locales/fr/help/*.json",
|
|
174
|
+
"./api/search/count/*": "./api/search/count/*.js",
|
|
175
|
+
"./api/search/count": "./api/search/count/index.js",
|
|
176
|
+
"./api/search/histogram/*": "./api/search/histogram/*.js",
|
|
177
|
+
"./api/search/histogram": "./api/search/histogram/index.js",
|
|
178
|
+
"./api/search/sigma/*": "./api/search/sigma/*.js",
|
|
179
|
+
"./api/analytic/notebooks/*": "./api/analytic/notebooks/*.js",
|
|
180
|
+
"./api/analytic/notebooks": "./api/analytic/notebooks/index.js",
|
|
181
|
+
"./api/analytic/comments/*": "./api/analytic/comments/*.js",
|
|
182
|
+
"./api/analytic/comments": "./api/analytic/comments/index.js",
|
|
183
|
+
"./plugins/borealis/*": "./plugins/borealis/*.js",
|
|
184
|
+
"./plugins/borealis": "./plugins/borealis/index.js",
|
|
185
|
+
"./plugins/borealis/locales/*": "./plugins/borealis/locales/*.js",
|
|
186
|
+
"./plugins/borealis/components/*": "./plugins/borealis/components/*.js",
|
|
183
187
|
"./components/app/*": "./components/app/*.js",
|
|
184
|
-
"./components/hooks/*": "./components/hooks/*.js",
|
|
185
188
|
"./components/elements/*": "./components/elements/*.js",
|
|
186
189
|
"./components/routes/*": "./components/routes/*.js",
|
|
187
190
|
"./components/logins/*": "./components/logins/*.js",
|
|
191
|
+
"./components/hooks/*": "./components/hooks/*.js",
|
|
192
|
+
"./components/app/providers/*": "./components/app/providers/*.js",
|
|
188
193
|
"./components/app/hooks/*": "./components/app/hooks/*.js",
|
|
189
194
|
"./components/app/drawers/*": "./components/app/drawers/*.js",
|
|
190
|
-
"./components/app/providers/*": "./components/app/providers/*.js",
|
|
191
|
-
"./components/elements/addons/*": "./components/elements/addons/*.js",
|
|
192
195
|
"./components/elements/display/*": "./components/elements/display/*.js",
|
|
193
|
-
"./components/elements/view/*": "./components/elements/view/*.js",
|
|
194
196
|
"./components/elements/hit/*": "./components/elements/hit/*.js",
|
|
195
|
-
"./components/elements/
|
|
196
|
-
"./components/elements/addons
|
|
197
|
+
"./components/elements/view/*": "./components/elements/view/*.js",
|
|
198
|
+
"./components/elements/addons/*": "./components/elements/addons/*.js",
|
|
199
|
+
"./components/elements/display/markdownPlugins/*.md": "./components/elements/display/markdownPlugins/*.md.js",
|
|
200
|
+
"./components/elements/display/modals/*": "./components/elements/display/modals/*.js",
|
|
201
|
+
"./components/elements/display/features/*": "./components/elements/display/features/*.js",
|
|
202
|
+
"./components/elements/display/icons/*": "./components/elements/display/icons/*.js",
|
|
203
|
+
"./components/elements/display/json/*": "./components/elements/display/json/*.js",
|
|
204
|
+
"./components/elements/display/handlebars/*": "./components/elements/display/handlebars/*.js",
|
|
205
|
+
"./components/elements/display/icons/svg/*": "./components/elements/display/icons/svg/*.js",
|
|
206
|
+
"./components/elements/hit/elements/*": "./components/elements/hit/elements/*.js",
|
|
207
|
+
"./components/elements/hit/outlines/*": "./components/elements/hit/outlines/*.js",
|
|
208
|
+
"./components/elements/hit/related/*": "./components/elements/hit/related/*.js",
|
|
209
|
+
"./components/elements/hit/aggregate/*": "./components/elements/hit/aggregate/*.js",
|
|
210
|
+
"./components/elements/hit/actions/*": "./components/elements/hit/actions/*.js",
|
|
211
|
+
"./components/elements/hit/outlines/al/*": "./components/elements/hit/outlines/al/*.js",
|
|
197
212
|
"./components/elements/addons/buttons/*": "./components/elements/addons/buttons/*.js",
|
|
198
213
|
"./components/elements/addons/buttons": "./components/elements/addons/buttons/index.js",
|
|
199
214
|
"./components/elements/addons/layout/*": "./components/elements/addons/layout/*.js",
|
|
200
215
|
"./components/elements/addons/search/*": "./components/elements/addons/search/*.js",
|
|
201
|
-
"./components/elements/addons/lists
|
|
202
|
-
"./components/elements/addons/lists
|
|
203
|
-
"./components/elements/addons/lists/table": "./components/elements/addons/lists/table/index.js",
|
|
216
|
+
"./components/elements/addons/lists/*": "./components/elements/addons/lists/*.js",
|
|
217
|
+
"./components/elements/addons/lists": "./components/elements/addons/lists/index.js",
|
|
204
218
|
"./components/elements/addons/layout/vsbox/*": "./components/elements/addons/layout/vsbox/*.js",
|
|
205
219
|
"./components/elements/addons/search/phrase/*": "./components/elements/addons/search/phrase/*.js",
|
|
206
220
|
"./components/elements/addons/search/phrase": "./components/elements/addons/search/phrase/index.js",
|
|
207
221
|
"./components/elements/addons/search/phrase/word/*": "./components/elements/addons/search/phrase/word/*.js",
|
|
208
222
|
"./components/elements/addons/search/phrase/word/consumers/*": "./components/elements/addons/search/phrase/word/consumers/*.js",
|
|
209
|
-
"./components/elements/
|
|
210
|
-
"./components/elements/
|
|
211
|
-
"./components/elements/
|
|
212
|
-
"./components/elements/display/handlebars/*": "./components/elements/display/handlebars/*.js",
|
|
213
|
-
"./components/elements/display/modals/*": "./components/elements/display/modals/*.js",
|
|
214
|
-
"./components/elements/display/json/*": "./components/elements/display/json/*.js",
|
|
215
|
-
"./components/elements/display/icons/svg/*": "./components/elements/display/icons/svg/*.js",
|
|
216
|
-
"./components/elements/hit/related/*": "./components/elements/hit/related/*.js",
|
|
217
|
-
"./components/elements/hit/aggregate/*": "./components/elements/hit/aggregate/*.js",
|
|
218
|
-
"./components/elements/hit/elements/*": "./components/elements/hit/elements/*.js",
|
|
219
|
-
"./components/elements/hit/actions/*": "./components/elements/hit/actions/*.js",
|
|
220
|
-
"./components/elements/hit/outlines/*": "./components/elements/hit/outlines/*.js",
|
|
221
|
-
"./components/elements/hit/outlines/al/*": "./components/elements/hit/outlines/al/*.js",
|
|
222
|
-
"./components/routes/home/*": "./components/routes/home/*.js",
|
|
223
|
-
"./components/routes/home": "./components/routes/home/index.js",
|
|
223
|
+
"./components/elements/addons/lists/hooks/*": "./components/elements/addons/lists/hooks/*.js",
|
|
224
|
+
"./components/elements/addons/lists/table/*": "./components/elements/addons/lists/table/*.js",
|
|
225
|
+
"./components/elements/addons/lists/table": "./components/elements/addons/lists/table/index.js",
|
|
224
226
|
"./components/routes/views/*": "./components/routes/views/*.js",
|
|
225
|
-
"./components/routes/hits/*": "./components/routes/hits/*.js",
|
|
226
|
-
"./components/routes/advanced/*": "./components/routes/advanced/*.js",
|
|
227
|
-
"./components/routes/admin/*": "./components/routes/admin/*.js",
|
|
228
227
|
"./components/routes/dossiers/*": "./components/routes/dossiers/*.js",
|
|
229
|
-
"./components/routes/templates/*": "./components/routes/templates/*.js",
|
|
230
228
|
"./components/routes/action/*": "./components/routes/action/*.js",
|
|
229
|
+
"./components/routes/admin/*": "./components/routes/admin/*.js",
|
|
230
|
+
"./components/routes/hits/*": "./components/routes/hits/*.js",
|
|
231
231
|
"./components/routes/settings/*": "./components/routes/settings/*.js",
|
|
232
|
+
"./components/routes/home/*": "./components/routes/home/*.js",
|
|
233
|
+
"./components/routes/home": "./components/routes/home/index.js",
|
|
232
234
|
"./components/routes/overviews/*": "./components/routes/overviews/*.js",
|
|
233
|
-
"./components/routes/
|
|
235
|
+
"./components/routes/advanced/*": "./components/routes/advanced/*.js",
|
|
234
236
|
"./components/routes/analytics/*": "./components/routes/analytics/*.js",
|
|
237
|
+
"./components/routes/templates/*": "./components/routes/templates/*.js",
|
|
238
|
+
"./components/routes/help/*": "./components/routes/help/*.js",
|
|
239
|
+
"./components/routes/action/shared/*": "./components/routes/action/shared/*.js",
|
|
240
|
+
"./components/routes/action/view/*": "./components/routes/action/view/*.js",
|
|
241
|
+
"./components/routes/action/edit/*": "./components/routes/action/edit/*.js",
|
|
242
|
+
"./components/routes/admin/users/*": "./components/routes/admin/users/*.js",
|
|
235
243
|
"./components/routes/hits/search/*": "./components/routes/hits/search/*.js",
|
|
236
244
|
"./components/routes/hits/view/*": "./components/routes/hits/view/*.js",
|
|
237
|
-
"./components/routes/hits/search/grid/*": "./components/routes/hits/search/grid/*.js",
|
|
238
245
|
"./components/routes/hits/search/shared/*": "./components/routes/hits/search/shared/*.js",
|
|
239
|
-
"./components/routes/
|
|
240
|
-
"./components/routes/
|
|
241
|
-
"./components/routes/action/shared/*": "./components/routes/action/shared/*.js",
|
|
242
|
-
"./components/routes/action/view/*": "./components/routes/action/view/*.js",
|
|
246
|
+
"./components/routes/hits/search/grid/*": "./components/routes/hits/search/grid/*.js",
|
|
247
|
+
"./components/routes/analytics/widgets/*": "./components/routes/analytics/widgets/*.js",
|
|
243
248
|
"./components/routes/help/markdown/*.md": "./components/routes/help/markdown/*.md.js",
|
|
244
249
|
"./components/routes/help/components/*": "./components/routes/help/components/*.js",
|
|
245
|
-
"./components/routes/help/markdown/en/*.md": "./components/routes/help/markdown/en/*.md.js",
|
|
246
250
|
"./components/routes/help/markdown/fr/*.md": "./components/routes/help/markdown/fr/*.md.js",
|
|
247
|
-
"./components/routes/
|
|
248
|
-
"./components/logins/hooks/*": "./components/logins/hooks/*.js",
|
|
251
|
+
"./components/routes/help/markdown/en/*.md": "./components/routes/help/markdown/en/*.md.js",
|
|
249
252
|
"./components/logins/auth/*": "./components/logins/auth/*.js",
|
|
250
|
-
"./
|
|
253
|
+
"./components/logins/hooks/*": "./components/logins/hooks/*.js",
|
|
251
254
|
"./models/entities/*": "./models/entities/*.js",
|
|
252
|
-
"./models/
|
|
253
|
-
"./
|
|
254
|
-
"./plugins/borealis": "./plugins/borealis/index.js",
|
|
255
|
-
"./plugins/borealis/locales/*": "./plugins/borealis/locales/*.js",
|
|
256
|
-
"./plugins/borealis/components/*": "./plugins/borealis/components/*.js"
|
|
255
|
+
"./models/socket/*": "./models/socket/*.js",
|
|
256
|
+
"./models/entities/generated/*": "./models/entities/generated/*.js"
|
|
257
257
|
}
|
|
258
258
|
}
|
package/utils/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { LocalPolice, MoodBad, NewReleases, PsychologyAlt, Star, Timeline } from '@mui/icons-material';
|
|
3
3
|
import { blue, grey, indigo, orange, pink, red, teal, yellow } from '@mui/material/colors';
|
|
4
|
-
import
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
5
|
export const HOWLER_API = import.meta.env.VITE_API;
|
|
6
6
|
export const LOCAL = HOWLER_API === 'MOCK';
|
|
7
7
|
export const VERSION = import.meta.env.VITE_VERSION;
|
|
@@ -66,7 +66,7 @@ export var StorageKey;
|
|
|
66
66
|
export const MOCK_SEARCH_QUERY_STORE = `${MY_LOCAL_STORAGE_PREFIX}.${StorageKey.MOCK_SEARCH_QUERY_STORE}`;
|
|
67
67
|
export const MOCK_FAVOURITES_STORE = `${MY_LOCAL_STORAGE_PREFIX}.${StorageKey.MOCK_FAVOURITES_STORE}`;
|
|
68
68
|
export const VALID_ACTION_TRIGGERS = ['create', 'promote', 'demote'];
|
|
69
|
-
const CURRENT_TIME =
|
|
69
|
+
const CURRENT_TIME = dayjs();
|
|
70
70
|
export const minutes = [CURRENT_TIME.get('minute'), CURRENT_TIME.add(30, 'minute').get('minute')].sort();
|
|
71
71
|
export const hours = [
|
|
72
72
|
CURRENT_TIME.get('hour'),
|
package/utils/utils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as colors from '@mui/material/colors';
|
|
2
|
+
import dayjs from 'dayjs';
|
|
2
3
|
import { flatten, unflatten } from 'flat';
|
|
3
4
|
import { isArray, isEmpty, isNil, isObject, isPlainObject } from 'lodash-es';
|
|
4
|
-
import moment from 'moment';
|
|
5
5
|
export const bytesToSize = (bytes) => {
|
|
6
6
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
7
7
|
if (bytes === 0 || bytes === null)
|
|
@@ -39,7 +39,7 @@ export const formatDate = (date) => {
|
|
|
39
39
|
if (!date) {
|
|
40
40
|
return '?';
|
|
41
41
|
}
|
|
42
|
-
return
|
|
42
|
+
return dayjs(date).utc().format(DATE_FORMAT);
|
|
43
43
|
};
|
|
44
44
|
export const compareTimestamp = (a, b) => {
|
|
45
45
|
return (new Date(a).getTime() - new Date(b).getTime()) / 1000;
|
|
@@ -48,7 +48,7 @@ export const twitterShort = (date) => {
|
|
|
48
48
|
if (!date || date === '?') {
|
|
49
49
|
return '?';
|
|
50
50
|
}
|
|
51
|
-
return
|
|
51
|
+
return dayjs(date).fromNow();
|
|
52
52
|
};
|
|
53
53
|
export const hashCode = (s) => s.split('').reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0);
|
|
54
54
|
export const stringToColor = (string) => {
|