@cccsaurora/howler-ui 2.13.0-dev.171 → 2.13.0-dev.176

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.
Files changed (40) hide show
  1. package/commons/components/notification/elements/item/NotificationItemDate.js +2 -2
  2. package/components/app/drawers/ApiKeyDrawer.js +4 -4
  3. package/components/elements/hit/HitSummary.js +1 -1
  4. package/components/elements/hit/aggregate/HitGraph.d.ts +1 -1
  5. package/components/elements/hit/aggregate/HitGraph.js +7 -7
  6. package/components/elements/hit/elements/HitTimestamp.js +8 -8
  7. package/components/hooks/useMyChart.d.ts +1 -1
  8. package/components/hooks/useMyChart.js +1 -1
  9. package/components/routes/advanced/QueryBuilder.js +3 -3
  10. package/components/routes/analytics/AnalyticOverview.d.ts +1 -1
  11. package/components/routes/analytics/AnalyticOverview.js +1 -1
  12. package/components/routes/analytics/AnalyticOverviews.d.ts +1 -1
  13. package/components/routes/analytics/AnalyticOverviews.js +1 -1
  14. package/components/routes/analytics/AnalyticTemplates.d.ts +1 -1
  15. package/components/routes/analytics/AnalyticTemplates.js +1 -1
  16. package/components/routes/analytics/RuleView.d.ts +1 -1
  17. package/components/routes/analytics/RuleView.js +1 -1
  18. package/components/routes/analytics/TriageSettings.d.ts +1 -1
  19. package/components/routes/analytics/TriageSettings.js +1 -1
  20. package/components/routes/analytics/widgets/Assessment.d.ts +1 -1
  21. package/components/routes/analytics/widgets/Assessment.js +1 -1
  22. package/components/routes/analytics/widgets/Created.d.ts +1 -1
  23. package/components/routes/analytics/widgets/Created.js +1 -1
  24. package/components/routes/analytics/widgets/Detection.d.ts +1 -1
  25. package/components/routes/analytics/widgets/Detection.js +1 -1
  26. package/components/routes/analytics/widgets/Escalation.d.ts +1 -1
  27. package/components/routes/analytics/widgets/Escalation.js +1 -1
  28. package/components/routes/analytics/widgets/Stacked.d.ts +1 -1
  29. package/components/routes/analytics/widgets/Stacked.js +1 -1
  30. package/components/routes/analytics/widgets/Status.d.ts +1 -1
  31. package/components/routes/analytics/widgets/Status.js +1 -1
  32. package/components/routes/help/TemplateDocumentation.js +5 -5
  33. package/components/routes/hits/search/HitBrowser.js +2 -2
  34. package/components/routes/hits/search/shared/CustomSpan.js +6 -6
  35. package/components/routes/home/index.js +4 -4
  36. package/components/routes/settings/SecuritySection.js +2 -2
  37. package/index.js +7 -0
  38. package/package.json +3 -3
  39. package/utils/constants.js +2 -2
  40. 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 moment from 'moment';
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: moment(date_published).locale(i18n.language).fromNow() }) }));
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 { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment';
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 moment().add(amount, unit);
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: AdapterMoment, 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 && moment.duration(amount, unit).asSeconds() < moment.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" }) })] })] }))] }) }));
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;
@@ -143,7 +143,7 @@ const HitSummary = ({ query, response, onStart, onComplete }) => {
143
143
  return (_jsxs(Stack, { sx: { mx: 2, height: '100%' }, spacing: 1, children: [_jsx(Typography, { variant: "h6", children: t('hit.summary.aggregate.title') }), _jsx(Divider, { flexItem: true }), _jsx(HitGraph, { query: query }), _jsx(Divider, { flexItem: true }), _jsxs(Stack, { sx: { overflow: 'auto', marginTop: '0 !important' }, pt: 1, spacing: 1, children: [_jsxs(Stack, { direction: "row", spacing: 2, mb: 2, alignItems: "stretch", children: [_jsx(Autocomplete, { fullWidth: true, multiple: true, sx: { minWidth: '175px' }, size: "small", value: customKeys, options: hitFields.map(_field => _field.key), renderInput: _params => _jsx(TextField, { ..._params, label: t('hit.summary.adhoc') }), onChange: (_, value) => setCustomKeys(value) }), _jsx(Button, { variant: "outlined", startIcon: loading ? _jsx(CircularProgress, { size: 20, sx: { ml: 1 } }) : _jsx(Analytics, { sx: { ml: 1 } }), disabled: loading, onClick: () => performAggregation(), children: t('button.aggregate') })] }), isEmpty(aggregateResults) && (_jsxs(Alert, { severity: "info", variant: "outlined", children: [_jsx(AlertTitle, { children: t('hit.summary.aggregate.nokeys.title') }), t('hit.summary.aggregate.nokeys.description')] })), loading && _jsx(LinearProgress, { sx: { minHeight: '4px' } }), Object.keys(aggregateResults)
144
144
  .filter(key => !isEmpty(aggregateResults[key]))
145
145
  .flatMap(key => [
146
- _jsx(Fade, { in: true, children: _jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [_jsx(Typography, { variant: "body1", children: key }, key + '-title'), keyCounts[key]?.count < 0 ? (_jsxs(Typography, { variant: "caption", color: "text.secondary", children: ["(", t('hit.summary.adhoc.custom'), ")"] })) : (_jsxs(Typography, { variant: "caption", color: "text.secondary", children: ["(", keyCounts[key]?.count, " ", t('references'), ")"] })), _jsx(Tooltip, { title: _jsxs(Stack, { children: [_jsx(Typography, { variant: "caption", children: t('hit.summary.aggregate.sources') }), keyCounts[key].sources.map(source => (_jsx(Typography, { variant: "caption", children: source }, source)))] }), children: _jsx(InfoOutlined, { fontSize: "inherit" }) })] }) }, key + '-refs'),
146
+ _jsx(Fade, { in: true, children: _jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [_jsx(Typography, { variant: "body1", children: key }, key + '-title'), keyCounts[key]?.count < 0 ? (_jsxs(Typography, { variant: "caption", color: "text.secondary", children: ["(", t('hit.summary.adhoc.custom'), ")"] })) : (_jsxs(Typography, { variant: "caption", color: "text.secondary", children: ["(", keyCounts[key]?.count ?? '?', " ", t('references'), ")"] })), _jsx(Tooltip, { title: _jsxs(Stack, { children: [_jsx(Typography, { variant: "caption", children: t('hit.summary.aggregate.sources') }), keyCounts[key]?.sources.map(source => (_jsx(Typography, { variant: "caption", children: source }, source))) ?? '?'] }), children: _jsx(InfoOutlined, { fontSize: "inherit" }) })] }) }, key + '-refs'),
147
147
  _jsx(Fade, { in: true, children: hitFields.find(f => f.key === key)?.type !== 'date' ? (_jsx(Box, { sx: theme => ({ ml: `${theme.spacing(1)} !important`, alignSelf: 'start' }), children: _jsx(Grid, { container: true, sx: theme => ({ mr: 1, mt: theme.spacing(-1) }), spacing: 1, children: Object.keys(aggregateResults[key]).map(_key => (_jsx(Grid, { item: true, xs: "auto", children: _jsx(PluginChip, { context: "summary", size: "small", variant: "filled", value: _key, label: `${_key} (${aggregateResults[key][_key]})`, onClick: () => setSearch(key, `"${_key}"`) }) }, _key))) }, key + '-list') })) : (_jsx(Chip, { size: "small", sx: theme => ({ ml: `${theme.spacing(1)} !important`, alignSelf: 'start' }), label: getTimeRange(Object.keys(aggregateResults[key]))
148
148
  .map(d => new Date(d).toLocaleString())
149
149
  .join(' - '), onClick: () => setSearch(key, `[${getTimeRange(Object.keys(aggregateResults[key])).join(' TO ')}]`) })) }, key + '-results')
@@ -1,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { FC } from 'react';
3
3
  declare const HitGraph: FC<{
4
4
  query: string;
@@ -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-moment';
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 createdMoment = moment(hit.event?.created ?? hit.timestamp);
99
+ const createdDate = dayjs(hit.event?.created ?? hit.timestamp);
100
100
  return {
101
- x: createdMoment.clone().hour(0).minute(0).second(0).toISOString(),
102
- y: createdMoment.hour() + createdMoment.minute() / 60 + createdMoment.second() / 3600,
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} (${moment(entry.raw.hit.event.created).format('MMM D HH:mm:ss')})`,
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 moment().hour(hour).minute(minute).format('HH:mm');
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 moment from 'moment';
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(() => moment().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]);
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 moment(earliest).isBefore(current) ? earliest : current;
23
+ return dayjs(earliest).isBefore(current) ? earliest : current;
24
24
  });
25
25
  return earliestDate;
26
26
  }, [hit]);
27
27
  const color = useMemo(() => {
28
- if (moment(timestamp).isBefore(threshold.clone().add(2, 'weeks'))) {
28
+ if (dayjs(timestamp).isBefore(threshold.clone().add(2, 'weeks'))) {
29
29
  return 'error';
30
30
  }
31
- if (moment(timestamp).isBefore(threshold.clone().add(1, 'months'))) {
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 (moment(timestamp).isBefore(threshold)) {
37
+ if (dayjs(timestamp).isBefore(threshold)) {
38
38
  return t('retention.imminent');
39
39
  }
40
- const diff = moment(timestamp).diff(threshold, 'seconds');
41
- const _duration = moment.duration(diff, 'seconds');
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,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  declare const useMyChart: () => {
3
3
  line: (titleKey: string, subtitleKey?: string) => {
4
4
  responsive: boolean;
@@ -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-moment';
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 moment from 'moment';
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: ${moment().format('YYYY/MM/DD')}
45
- modified: ${moment().format('YYYY/MM/DD')}
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:
@@ -1,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  import type { FC } from 'react';
4
4
  declare const AnalyticOverview: FC<{
@@ -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-moment';
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,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  import { type FC } from 'react';
4
4
  declare const AnalyticOverviews: FC<{
@@ -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-moment';
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';
@@ -1,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  import { type FC } from 'react';
4
4
  declare const AnalyticTemplates: FC<{
@@ -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-moment';
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';
@@ -1,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  import type { FC } from 'react';
4
4
  declare const RuleView: FC<{
@@ -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-moment';
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,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  import type { FC } from 'react';
4
4
  declare const TriageSettings: FC<{
@@ -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-moment';
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,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  declare const Assessment: import("react").ForwardRefExoticComponent<{
4
4
  analytic: Analytic;
@@ -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-moment';
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,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  declare const Created: import("react").ForwardRefExoticComponent<{
4
4
  analytic: Analytic;
@@ -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-moment';
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,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  declare const Detection: import("react").ForwardRefExoticComponent<{
4
4
  analytic: Analytic;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import 'chartjs-adapter-moment';
2
+ import 'chartjs-adapter-dayjs';
3
3
  import { forwardRef } from 'react';
4
4
  import { stringToColor } from '@cccsaurora/howler-ui/utils/utils';
5
5
  import Stacked from './Stacked';
@@ -1,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  declare const Escalation: import("react").ForwardRefExoticComponent<{
4
4
  analytic: Analytic;
@@ -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-moment';
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,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  declare const Stacked: import("react").ForwardRefExoticComponent<{
4
4
  analytic: Analytic;
@@ -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-moment';
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,4 +1,4 @@
1
- import 'chartjs-adapter-moment';
1
+ import 'chartjs-adapter-dayjs';
2
2
  import type { Analytic } from '@cccsaurora/howler-ui/models/entities/generated/Analytic';
3
3
  declare const Status: import("react").ForwardRefExoticComponent<{
4
4
  analytic: Analytic;
@@ -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-moment';
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 moment from 'moment';
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: moment().subtract(4, 'hour').toString(),
18
- end: moment().subtract(3, 'hour').toString(),
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: moment().subtract(6, 'hour').toString(),
27
- end: moment().subtract(5, 'hour').toString(),
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 = moment().subtract(1, 'month').toISOString();
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]);
@@ -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 { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment';
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 moment from 'moment';
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 ? moment(ctx.startDate) : null));
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 ? moment(ctx.endDate) : null));
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(moment().subtract(3, 'days').toISOString(), moment().toISOString());
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: AdapterMoment, 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 ? moment(startDate) : moment().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;
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, moment().utc().format(LUCENE_DATE_FMT));
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(moment().utc().format(LUCENE_DATE_FMT)), children: _jsx(OpenInNew, {}) }), _jsx(IconButton, { color: "info", onClick: () => {
85
- setLastViewed(moment().utc().format(LUCENE_DATE_FMT));
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 moment from 'moment';
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: moment.utc(apiKey[2]).isBefore(moment().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'))] }));
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-moment": "^1.0.1",
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,7 +96,7 @@
96
96
  "internal-slot": "1.0.7"
97
97
  },
98
98
  "type": "module",
99
- "version": "2.13.0-dev.171",
99
+ "version": "2.13.0-dev.176",
100
100
  "exports": {
101
101
  "./i18n": "./i18n.js",
102
102
  "./index.css": "./index.css",
@@ -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 moment from 'moment';
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 = moment();
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 moment(date).utc().format(DATE_FORMAT);
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 moment(date).fromNow();
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) => {