@cccsaurora/howler-ui 2.17.0-dev.516 → 2.17.0-dev.517
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.
|
@@ -109,6 +109,6 @@ const HitBanner = ({ hit, layout = HitLayout.NORMAL, showAssigned = true }) => {
|
|
|
109
109
|
width: theme.spacing(3)
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
-
], children: [_jsx(HitTimestamp, { hit: hit, layout: layout }), showAssigned && _jsx(Assigned, { hit: hit, layout: layout }), _jsxs(Stack, { direction: "row", spacing: layout !== HitLayout.COMFY ? 0.5 : 1, children: [_jsx(EscalationChip, { hit: hit, layout: layout }), ['in-progress', 'on-hold'].includes(hit.howler.status) && (_jsx(Chip, { sx: { width: 'fit-content', display: 'inline-flex' }, label: hit.howler.status, size: layout !== HitLayout.COMFY ? 'small' : 'medium', color: "primary" })), hit.howler.related && (_jsx(Chip, { size: layout !== HitLayout.COMFY ? 'small' : 'medium', label: t('hit.header.related', { count: hit.howler.related.length }) }))
|
|
112
|
+
], children: [_jsx(HitTimestamp, { hit: hit, layout: layout }), showAssigned && _jsx(Assigned, { hit: hit, layout: layout }), _jsxs(Stack, { direction: "row", spacing: layout !== HitLayout.COMFY ? 0.5 : 1, children: [_jsx(EscalationChip, { hit: hit, layout: layout }), ['in-progress', 'on-hold'].includes(hit.howler.status) && (_jsx(Chip, { sx: { width: 'fit-content', display: 'inline-flex' }, label: hit.howler.status, size: layout !== HitLayout.COMFY ? 'small' : 'medium', color: "primary" }))] }), hit.howler.related && (_jsx(Chip, { size: layout !== HitLayout.COMFY ? 'small' : 'medium', label: t('hit.header.related', { count: hit.howler.related.length }) })), howlerPluginStore.plugins.flatMap(plugin => pluginStore.executeFunction(`${plugin}.status`, { hit, layout }))] })] }));
|
|
113
113
|
};
|
|
114
114
|
export default HitBanner;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Task } from '@cccsaurora/howler-ui/models/entities/generated/Task';
|
|
2
2
|
import { type FC } from 'react';
|
|
3
3
|
declare const CaseTask: FC<{
|
|
4
|
-
task
|
|
4
|
+
task?: Task;
|
|
5
5
|
paths: string[];
|
|
6
|
-
onDelete
|
|
7
|
-
onEdit: (task
|
|
6
|
+
onDelete?: () => Promise<void>;
|
|
7
|
+
onEdit: (task?: Partial<Task>) => Promise<void>;
|
|
8
8
|
loading?: boolean;
|
|
9
|
+
newTask?: boolean;
|
|
9
10
|
}>;
|
|
10
11
|
export default CaseTask;
|
|
@@ -2,45 +2,52 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Check, Close, Delete, Edit } from '@mui/icons-material';
|
|
3
3
|
import { Autocomplete, Card, Checkbox, Chip, IconButton, LinearProgress, Stack, TextField, Tooltip, Typography } from '@mui/material';
|
|
4
4
|
import UserList from '@cccsaurora/howler-ui/components/elements/UserList';
|
|
5
|
-
import { useState } from 'react';
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Link } from 'react-router-dom';
|
|
8
|
-
const CaseTask = ({ task, onEdit, onDelete, paths }) => {
|
|
8
|
+
const CaseTask = ({ task, onEdit, onDelete, paths, newTask = false }) => {
|
|
9
9
|
const { t } = useTranslation();
|
|
10
|
-
const [editing, setEditing] = useState(
|
|
10
|
+
const [editing, setEditing] = useState(newTask);
|
|
11
11
|
const [loading, setLoading] = useState(false);
|
|
12
|
-
const [summary, setSummary] = useState(task
|
|
13
|
-
const [path, setPath] = useState(task
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
await onEdit({
|
|
18
|
-
assignment
|
|
19
|
-
});
|
|
20
|
-
setLoading(false);
|
|
21
|
-
};
|
|
12
|
+
const [summary, setSummary] = useState(task?.summary || '');
|
|
13
|
+
const [path, setPath] = useState(task?.path ?? null);
|
|
14
|
+
const [assignment, setAssignment] = useState(task?.assignment);
|
|
15
|
+
const [complete, setComplete] = useState(task?.complete ?? false);
|
|
16
|
+
const dirty = summary !== task?.summary || path !== task?.path;
|
|
22
17
|
const onSubmit = async () => {
|
|
23
|
-
if (dirty) {
|
|
18
|
+
if (dirty && editing) {
|
|
19
|
+
console.log('confirmed bongo time');
|
|
24
20
|
setLoading(true);
|
|
25
|
-
await onEdit({ summary, path: !path ? null : path });
|
|
21
|
+
await onEdit({ summary, path: !path ? null : path, assignment });
|
|
26
22
|
setLoading(false);
|
|
27
23
|
}
|
|
28
24
|
};
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!editing && task?.assignment !== assignment) {
|
|
27
|
+
console.log('confirmed bongo time 2');
|
|
28
|
+
setLoading(true);
|
|
29
|
+
onEdit({ assignment }).finally(() => setLoading(false));
|
|
30
|
+
}
|
|
31
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
32
|
+
}, [assignment]);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!editing && task?.complete !== complete) {
|
|
35
|
+
console.log('confirmed bongo time 3');
|
|
36
|
+
setLoading(true);
|
|
37
|
+
onEdit({ complete }).finally(() => setLoading(false));
|
|
38
|
+
}
|
|
39
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
40
|
+
}, [complete]);
|
|
41
|
+
return (_jsxs(Card, { sx: { pl: 0.5, pr: 1, py: 0.5, position: 'relative' }, children: [_jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [_jsx(Checkbox, { disabled: loading, color: "success", checked: complete, size: "small", onChange: (_ev, _complete) => setComplete(_complete) }), editing ? (_jsx(TextField, { disabled: loading, value: summary, onChange: e => setSummary(e.target.value), size: "small", fullWidth: true, sx: { minWidth: '40%' } })) : (_jsx(Typography, { sx: [task?.complete && { textDecoration: 'line-through' }], children: task?.summary || summary })), !editing && task?.path && _jsx(Chip, { clickable: true, component: Link, to: task.path, label: task.path }), editing && (_jsx(Autocomplete, { disabled: loading, value: path, options: paths, onChange: (_ev, value) => setPath(value), fullWidth: true, renderInput: params => _jsx(TextField, { ...params, size: "small" }) })), _jsx(UserList, { disabled: loading, userIds: [assignment], onChange: ([_assigment]) => setAssignment(_assigment), i18nLabel: "route.cases.task.set.assignment", avatarHeight: 24 }), _jsx("div", { style: { flex: 1 } }), editing && (_jsx(Tooltip, { title: t('route.cases.task.delete'), children: _jsx(IconButton, { size: "small", color: "error", onClick: () => {
|
|
31
42
|
setLoading(true);
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
setEditing(
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
setEditing(false);
|
|
43
|
-
onSubmit();
|
|
44
|
-
}, disabled: (!dirty && editing) || loading, children: editing ? _jsx(Check, { fontSize: "small" }) : _jsx(Edit, { fontSize: "small" }) }) }), editing && (_jsx(Tooltip, { title: t('route.cases.task.edit.cancel'), children: _jsx(IconButton, { size: "small", onClick: () => setEditing(false), disabled: loading, children: _jsx(Close, { fontSize: "small" }) }) }))] }), loading && _jsx(LinearProgress, { sx: { left: 0, bottom: 0, right: 0, position: 'absolute' } })] }, task.id));
|
|
43
|
+
onDelete().then(() => setLoading(false));
|
|
44
|
+
}, disabled: loading, children: _jsx(Delete, { fontSize: "small" }) }) })), _jsx(Tooltip, { title: t(editing ? 'route.cases.task.edit.save' : 'route.cases.task.edit'), children: _jsx("span", { children: _jsx(IconButton, { size: "small", color: editing ? 'success' : 'default', onClick: async () => {
|
|
45
|
+
if (!editing) {
|
|
46
|
+
setEditing(true);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
await onSubmit();
|
|
50
|
+
setEditing(false);
|
|
51
|
+
}, disabled: (!dirty && editing) || loading || !summary, children: editing ? _jsx(Check, { fontSize: "small" }) : _jsx(Edit, { fontSize: "small" }) }) }) }), editing && (_jsx(Tooltip, { title: t('route.cases.task.edit.cancel'), children: _jsx(IconButton, { size: "small", onClick: () => setEditing(false), disabled: loading, children: _jsx(Close, { fontSize: "small" }) }) }))] }), loading && _jsx(LinearProgress, { sx: { left: 0, bottom: 0, right: 0, position: 'absolute' } })] }));
|
|
45
52
|
};
|
|
46
53
|
export default CaseTask;
|
|
@@ -1,23 +1,52 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Add } from '@mui/icons-material';
|
|
2
3
|
import { Divider, Skeleton, Stack, Typography } from '@mui/material';
|
|
3
|
-
import {} from 'react';
|
|
4
|
+
import { useState } from 'react';
|
|
4
5
|
import { useTranslation } from 'react-i18next';
|
|
5
6
|
import CaseTask from './CaseTask';
|
|
6
7
|
const TaskPanel = ({ case: _case, updateCase }) => {
|
|
7
8
|
const { t } = useTranslation();
|
|
9
|
+
const [addingTask, setAddingTask] = useState(false);
|
|
10
|
+
const onEdit = (task) => async (newTask) => {
|
|
11
|
+
if (task) {
|
|
12
|
+
await updateCase({
|
|
13
|
+
tasks: _case.tasks.map(_task => {
|
|
14
|
+
if (_task.id !== task.id) {
|
|
15
|
+
return _task;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
..._task,
|
|
19
|
+
...newTask
|
|
20
|
+
};
|
|
21
|
+
})
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
await updateCase({
|
|
26
|
+
tasks: [..._case.tasks, newTask]
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
};
|
|
8
30
|
if (!_case) {
|
|
9
31
|
return _jsx(Skeleton, { height: 240 });
|
|
10
32
|
}
|
|
11
|
-
return (_jsxs(Stack, { spacing: 1, children: [_jsx(Typography, { flex: 1, variant: "h4", children: t('page.cases.dashboard.tasks') }), _jsx(Divider, {}), _case.tasks.map(task => (_jsx(CaseTask, { task: task, paths: _case.items.map(item => item.path), onEdit:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
33
|
+
return (_jsxs(Stack, { spacing: 1, children: [_jsx(Typography, { flex: 1, variant: "h4", children: t('page.cases.dashboard.tasks') }), _jsx(Divider, {}), _case.tasks.map(task => (_jsx(CaseTask, { task: task, paths: _case.items.map(item => item.path), onEdit: onEdit(task), onDelete: () => updateCase({ tasks: _case.tasks.filter(_task => _task.id !== task.id) }) }, task.id))), addingTask && (_jsx(CaseTask, { newTask: true, paths: _case.items.map(item => item.path), onEdit: async (task) => {
|
|
34
|
+
await onEdit()(task);
|
|
35
|
+
setAddingTask(false);
|
|
36
|
+
}, onDelete: async () => setAddingTask(false) })), _jsxs(Stack, { onClick: () => setAddingTask(true), direction: "row", spacing: 2, sx: theme => ({
|
|
37
|
+
borderStyle: 'dashed',
|
|
38
|
+
borderColor: theme.palette.text.secondary,
|
|
39
|
+
borderWidth: '0.15rem',
|
|
40
|
+
borderRadius: '0.15rem',
|
|
41
|
+
opacity: 0.3,
|
|
42
|
+
justifyContent: 'center',
|
|
43
|
+
alignItems: 'center',
|
|
44
|
+
padding: 1,
|
|
45
|
+
transition: theme.transitions.create('opacity'),
|
|
46
|
+
'&:hover': {
|
|
47
|
+
opacity: 1,
|
|
48
|
+
cursor: 'pointer'
|
|
49
|
+
}
|
|
50
|
+
}), children: [_jsx(Add, {}), _jsx(Typography, { children: t('page.cases.dashboard.tasks.add') })] })] }));
|
|
22
51
|
};
|
|
23
52
|
export default TaskPanel;
|
|
@@ -114,7 +114,6 @@
|
|
|
114
114
|
"help.hit.banner.description": "See the below hit banner example for the hit keys necessary to properly populate it. If you have any additional questions, ask in the HOWLER support channel.",
|
|
115
115
|
"help.hit.banner.json": "Here is the hit data used to populate this banner:",
|
|
116
116
|
"help.hit.banner.title": "Populating the Hit Banner",
|
|
117
|
-
"help.hit.bundle.title": "Hit Bundles",
|
|
118
117
|
"help.hit.labels.title": "Hit Labels",
|
|
119
118
|
"help.hit.links.title": "Hit Links",
|
|
120
119
|
"help.hit.schema.description.missing": "No description provided.",
|
|
@@ -168,6 +167,7 @@
|
|
|
168
167
|
"hit.header.escalation": "Escalation Level: ",
|
|
169
168
|
"hit.header.indicators": "Indicators",
|
|
170
169
|
"hit.header.rationale": "Rationale",
|
|
170
|
+
"hit.header.related": "{{count}} related records",
|
|
171
171
|
"hit.header.scrutiny": "Scrutiny: ",
|
|
172
172
|
"hit.header.status": "Status: ",
|
|
173
173
|
"hit.header.summary": "Summary",
|
|
@@ -618,7 +618,6 @@
|
|
|
618
618
|
"route.help.views": "Views",
|
|
619
619
|
"route.history": "History mode: See all previous queries",
|
|
620
620
|
"route.hits": "Alerts",
|
|
621
|
-
"route.hits.bundle": "View Bundle",
|
|
622
621
|
"route.hits.view": "View Hit",
|
|
623
622
|
"route.home": "User Dashboard",
|
|
624
623
|
"route.home.add": "Add New Panel",
|