@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 }) }))] }), howlerPluginStore.plugins.flatMap(plugin => pluginStore.executeFunction(`${plugin}.status`, { hit, layout }))] })] }));
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: Task;
4
+ task?: Task;
5
5
  paths: string[];
6
- onDelete: () => void;
7
- onEdit: (task: Partial<Task>) => Promise<void>;
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(false);
10
+ const [editing, setEditing] = useState(newTask);
11
11
  const [loading, setLoading] = useState(false);
12
- const [summary, setSummary] = useState(task.summary);
13
- const [path, setPath] = useState(task.path);
14
- const dirty = summary !== task.summary || path !== task.path;
15
- const onOwnerChange = async ([assignment]) => {
16
- setLoading(true);
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
- 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: task.complete, size: "small", onChange: async (_ev, complete) => {
30
- try {
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
- await onEdit({ complete });
33
- }
34
- finally {
35
- setLoading(false);
36
- }
37
- } }), 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 })), task.path && !editing && _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" }) })), task.assignment && (_jsx(UserList, { disabled: loading, userIds: [task.assignment], onChange: onOwnerChange, 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: onDelete, children: _jsx(Delete, { fontSize: "small" }) }) })), _jsx(Tooltip, { title: t(editing ? 'route.cases.task.edit.save' : 'route.cases.task.edit'), children: _jsx(IconButton, { size: "small", color: editing ? 'success' : 'default', onClick: () => {
38
- if (!editing) {
39
- setEditing(true);
40
- return;
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: newTask => updateCase({
12
- tasks: _case.tasks.map(_task => {
13
- if (_task.id !== task.id) {
14
- return _task;
15
- }
16
- return {
17
- ..._task,
18
- ...newTask
19
- };
20
- })
21
- }), onDelete: () => updateCase({ tasks: _case.tasks.filter(_task => _task.id !== task.id) }) }, task.id)))] }));
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",
package/package.json CHANGED
@@ -101,7 +101,7 @@
101
101
  "internal-slot": "1.0.7"
102
102
  },
103
103
  "type": "module",
104
- "version": "2.17.0-dev.516",
104
+ "version": "2.17.0-dev.517",
105
105
  "exports": {
106
106
  "./i18n": "./i18n.js",
107
107
  "./index.css": "./index.css",