From 2fd99ab08667fe29f66e6e427d77bb99cc648572 Mon Sep 17 00:00:00 2001 From: James Brunskill Date: Fri, 29 Sep 2023 16:26:04 +1300 Subject: [PATCH 1/9] NotificationQuerySelection --- .../common/src/intl/locales/en/system.json | 4 +- .../ScheduledNotificationEditForm.tsx | 61 +++---- .../Pages/Scheduled/parseConfig.ts | 2 +- .../NotificationQuerySelectionModal.tsx | 154 ++++++++++++++++++ .../components/SqlQuerySelector.tsx | 114 ++++++++++--- .../src/Notifications/components/index.ts | 1 + .../system/src/Notifications/types.ts | 2 +- 7 files changed, 270 insertions(+), 68 deletions(-) create mode 100644 frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx diff --git a/frontend/packages/common/src/intl/locales/en/system.json b/frontend/packages/common/src/intl/locales/en/system.json index fbb688a8..8142e48a 100644 --- a/frontend/packages/common/src/intl/locales/en/system.json +++ b/frontend/packages/common/src/intl/locales/en/system.json @@ -85,5 +85,7 @@ "helper-text.sql-query": "Your sql query can contain parameters, which are created using double curly braces within the query. For example: SELECT * FROM my_table WHERE id = {{param1}} AND name = {{param2}}", "label.test-sql-query": "Test SQL Query", "tooltip.manage-recipient-list": "Manage Recipient List", - "message.no-parameters": "No parameters found" + "message.no-parameters": "No parameters found", + "label.select-queries": "Select Queries", + "label.schedule": "Schedule" } \ No newline at end of file diff --git a/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx b/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx index c9837a06..abd5d6d7 100644 --- a/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx +++ b/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx @@ -5,49 +5,12 @@ import { DateTimeInput, Select, Typography, + useQueryParamsState, useTranslation, } from '@notify-frontend/common'; import { ScheduledNotification } from '../../types'; import { SqlQuerySelector } from '../../components'; - -const dummySqlQueries = [ - { - id: '1', - name: 'Last Sync By Province', - query: `SELECT - category3 AS project, category1_level2 AS province, - COUNT(last_sync_date) AS num_of_stores_synced_once -FROM store_categories sc -JOIN store s ON sc.code = s.code -JOIN ( - SELECT site_id, MAX(date) AS last_sync_date FROM site_log GROUP BY site_id -) sl ON s.sync_id_remote_site = sl.site_id -WHERE mode IN ('store', 'dispensary') -AND sc.disabled = false -AND category3 IN ({{project}}) -AND category1_level2 IN ({{province}}) -GROUP BY category3, category1_level2`, - parameters: ['project', 'province'], - }, - { - id: '2', - name: 'First Stock Take', - query: `SELECT - category3 AS project, category1_level2 AS province, - COUNT(first_stock_take_date) AS first_stock_take_date -FROM store_categories sc -JOIN store s ON sc.code = s.code -JOIN ( - SELECT store_id, MAX(stock_take_created_date) AS fist_stock_take_date FROM stock_take GROUP BY store_id -) st ON s.id = st.store_id -WHERE mode IN ('store', 'dispensary') -AND sc.disabled = false -AND category3 IN ({{project}}) -AND category1_level2 IN ({{province}}) -GROUP BY category3, category1_level2 `, - parameters: ['project', 'province'], - }, -]; +import { useNotificationQueries } from 'packages/system/src/Queries/api'; type ScheduledNotificationEditFormProps = { onUpdate: (patch: Partial) => void; @@ -59,6 +22,12 @@ export const ScheduledNotificationEditForm = ({ draft, }: ScheduledNotificationEditFormProps) => { const t = useTranslation('system'); + + const { queryParams } = useQueryParamsState(); + + const { data, isLoading } = useNotificationQueries(queryParams); + const queries = data?.nodes ?? []; + return ( <> - Queries + {t('label.queries')} - + { + console.log('props', props); + onUpdate(props as Partial); + }} + /> - Schedule + {t('label.schedule')} Starting From void; + setSelection: (input: { notificationQueryIds: string[] }) => void; +} + +interface NotificationQueryOption { + id: string; + name: string; + detail: string; +} + +export const NotificationQuerySelectionModal: FC< + NotificationQuerySelectionModalProps +> = ({ sqlQueries, initialSelectedIds, isOpen, onClose, setSelection }) => { + const t = useTranslation('system'); + const [errorMessage, setErrorMessage] = useState(''); + const [selectedIds, setSelectedIds] = useState([]); + + const { Modal } = useDialog({ isOpen, onClose }); + + const options = useMemo(() => { + return sqlQueries.map(sqlQuery => ({ + id: sqlQuery.id, + name: sqlQuery.name, + detail: sqlQuery.query, + })); + }, [sqlQueries]); + + const onChangeSelectedQueries = (ids: string[]) => { + setSelectedIds(ids); + }; + + const onSubmit = async () => { + if (selectedIds.length === 0) { + setErrorMessage(t('messages.nothing-selected')); + return; + } + + setSelection({ notificationQueryIds: selectedIds }); + onClose(); + }; + + const modalHeight = Math.min(window.innerHeight - 100, 700); + const modalWidth = Math.min(window.innerWidth - 100, 924); + + return ( + + + } + > + {t('label.select-queries')} + + + + } + cancelButton={} + title={t('label.select-queries')} + slideAnimation={false} + > + + {errorMessage ? ( + + { + setErrorMessage(''); + }} + > + {t('error')} + {errorMessage} + + + ) : null} + + `${option.detail} ${option.name}`} + filterProperties={['name', 'detail']} + filterPlaceholder={t('placeholder.search')} + width={modalWidth - 50} + height={modalHeight - 300} + defaultSelection={options.filter(o => + initialSelectedIds.includes(o.id) + )} + /> + + + + ); +}; + +const renderOption: AutocompleteOptionRenderer = ( + props, + option, + { selected } +): JSX.Element => ( +
  • + + + + {option.name} + + + + {option.detail} + +
  • +); diff --git a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx index c29869c1..bc2cf02b 100644 --- a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx +++ b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx @@ -1,26 +1,39 @@ import React, { FC } from 'react'; import { - TableProvider, - DataTable, useColumns, - createTableStore, useTranslation, StringUtils, + useEditModal, + Table, + TableHead, + TableRow, + TableCell, + TableBody, + IconButton, + EditIcon, + LocaleKey, } from '@notify-frontend/common'; +import { NotificationQuerySelectionModal } from './NotificationQuerySelectionModal'; +import { NotificationQueryRowFragment } from '../../Queries/api'; -interface SqlQuery { - id: string; - name: string; - query: string; - parameters: string[]; -} - -type QueryListProps = { records: SqlQuery[] }; +type QueryListProps = { + allQueries: NotificationQueryRowFragment[]; + selectedQueryIds: string[]; + setSelection: (input: { notificationQueryIds: string[] }) => void; + isLoading: boolean; +}; -export const SqlQuerySelector: FC = ({ records }) => { +export const SqlQuerySelector: FC = ({ + allQueries, + selectedQueryIds, + setSelection, + isLoading, +}) => { const t = useTranslation(); - const columns = useColumns([ + const { isOpen, onClose, onOpen } = useEditModal(); + + const columns = useColumns([ { key: 'name', label: 'label.name', @@ -35,21 +48,76 @@ export const SqlQuerySelector: FC = ({ records }) => { accessor: ({ rowData }) => StringUtils.ellipsis(rowData?.query, 35), }, { - key: 'parameters', + key: 'requiredParameters', label: 'label.parameters', sortable: false, - accessor: ({ rowData }) => rowData?.parameters.join(', '), + accessor: ({ rowData }) => rowData?.requiredParameters.join(', '), }, ]); + const selectedQueries = (allQueries ?? []).filter(q => + selectedQueryIds.includes(q.id) + ); + return ( - - - + <> + {isLoading ? ( +
    Loading Queries...
    + ) : ( + <> + + } + label={t('label.edit')} + onClick={onOpen} + /> + + + + + {columns.map(column => ( + + {t(column.label as LocaleKey)} + + ))} + + + + {selectedQueries.map((row, idx) => ( + + {columns.map(column => ( + + { + column.accessor({ + rowData: row, + rows: selectedQueries, + }) as string + } + + ))} + + ))} + +
    + + )} + ); }; diff --git a/frontend/packages/system/src/Notifications/components/index.ts b/frontend/packages/system/src/Notifications/components/index.ts index 695a7b08..0af9fa19 100644 --- a/frontend/packages/system/src/Notifications/components/index.ts +++ b/frontend/packages/system/src/Notifications/components/index.ts @@ -1 +1,2 @@ export * from './SqlQuerySelector'; +export * from './NotificationQuerySelectionModal'; diff --git a/frontend/packages/system/src/Notifications/types.ts b/frontend/packages/system/src/Notifications/types.ts index c73c66ab..15c34188 100644 --- a/frontend/packages/system/src/Notifications/types.ts +++ b/frontend/packages/system/src/Notifications/types.ts @@ -62,5 +62,5 @@ export interface ScheduledNotification extends BaseNotificationConfig { scheduleStartTime: Date; subjectTemplate: string; bodyTemplate: string; - sqlQueries: string[]; + notificationQueryIds: string[]; } From ede0d5af40c4c284b36a078a70f9ccee5cafa54f Mon Sep 17 00:00:00 2001 From: James Brunskill Date: Mon, 2 Oct 2023 11:12:11 +1300 Subject: [PATCH 2/9] Use 'normal' table for query selection. --- .../common/src/ui/layout/tables/DataTable.tsx | 6 +- .../components/SqlQuerySelector.tsx | 89 ++++++------------- 2 files changed, 26 insertions(+), 69 deletions(-) diff --git a/frontend/packages/common/src/ui/layout/tables/DataTable.tsx b/frontend/packages/common/src/ui/layout/tables/DataTable.tsx index 8ae11c60..27c3ec8e 100644 --- a/frontend/packages/common/src/ui/layout/tables/DataTable.tsx +++ b/frontend/packages/common/src/ui/layout/tables/DataTable.tsx @@ -9,10 +9,7 @@ import { Table as MuiTable, Typography, } from '@mui/material'; -import { - BasicSpinner, - useRegisterActions, -} from '@notify-frontend/common'; +import { BasicSpinner, useRegisterActions } from '@notify-frontend/common'; import { TableProps } from './types'; import { DataRow } from './components/DataRow/DataRow'; @@ -108,7 +105,6 @@ export const DataTableComponent = ({ display: 'flex', flexDirection: 'column', flex: 1, - height: '100%', }} > diff --git a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx index bc2cf02b..17bb83b6 100644 --- a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx +++ b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx @@ -4,14 +4,11 @@ import { useTranslation, StringUtils, useEditModal, - Table, - TableHead, - TableRow, - TableCell, - TableBody, IconButton, EditIcon, - LocaleKey, + DataTable, + TableProvider, + createTableStore, } from '@notify-frontend/common'; import { NotificationQuerySelectionModal } from './NotificationQuerySelectionModal'; import { NotificationQueryRowFragment } from '../../Queries/api'; @@ -45,7 +42,7 @@ export const SqlQuerySelector: FC = ({ label: 'label.query', width: 150, sortable: false, - accessor: ({ rowData }) => StringUtils.ellipsis(rowData?.query, 35), + accessor: ({ rowData }) => StringUtils.ellipsis(rowData?.query, 100), }, { key: 'requiredParameters', @@ -61,63 +58,27 @@ export const SqlQuerySelector: FC = ({ return ( <> - {isLoading ? ( -
    Loading Queries...
    - ) : ( - <> - - } - label={t('label.edit')} - onClick={onOpen} - /> - - - - - {columns.map(column => ( - - {t(column.label as LocaleKey)} - - ))} - - - - {selectedQueries.map((row, idx) => ( - - {columns.map(column => ( - - { - column.accessor({ - rowData: row, - rows: selectedQueries, - }) as string - } - - ))} - - ))} - -
    - - )} + + } + label={t('label.edit')} + onClick={onOpen} + /> + + + ); }; From e430d98260a072ba3e73e02769c89825192c4a0f Mon Sep 17 00:00:00 2001 From: James Brunskill Date: Wed, 11 Oct 2023 14:39:06 +1300 Subject: [PATCH 3/9] Change from EditIcon to Select Queries button --- .../components/SqlQuerySelector.tsx | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx index 17bb83b6..faf2e1f0 100644 --- a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx +++ b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx @@ -4,11 +4,11 @@ import { useTranslation, StringUtils, useEditModal, - IconButton, EditIcon, DataTable, TableProvider, createTableStore, + LoadingButton, } from '@notify-frontend/common'; import { NotificationQuerySelectionModal } from './NotificationQuerySelectionModal'; import { NotificationQueryRowFragment } from '../../Queries/api'; @@ -26,16 +26,22 @@ export const SqlQuerySelector: FC = ({ setSelection, isLoading, }) => { - const t = useTranslation(); + const t = useTranslation('system'); const { isOpen, onClose, onOpen } = useEditModal(); const columns = useColumns([ + { + key: 'referenceName', + label: 'label.reference-name', + width: 200, + sortable: false, + }, { key: 'name', label: 'label.name', width: 150, - sortable: true, + sortable: false, }, { key: 'query', @@ -65,11 +71,14 @@ export const SqlQuerySelector: FC = ({ onClose={onClose} setSelection={setSelection} /> - } - label={t('label.edit')} + + isLoading={false} + startIcon={} + > + {t('label.select-queries')} + Date: Wed, 11 Oct 2023 15:10:38 +1300 Subject: [PATCH 4/9] Translation for no-queries-selected --- frontend/packages/common/src/intl/locales/en/system.json | 1 + .../system/src/Notifications/components/SqlQuerySelector.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/packages/common/src/intl/locales/en/system.json b/frontend/packages/common/src/intl/locales/en/system.json index 8581ce10..6af7401a 100644 --- a/frontend/packages/common/src/intl/locales/en/system.json +++ b/frontend/packages/common/src/intl/locales/en/system.json @@ -91,5 +91,6 @@ "tooltip.manage-recipient-list": "Manage Recipient List", "message.no-parameters": "No parameters found", "label.select-queries": "Select Queries", + "message.no-queries-selected": "No queries selected", "label.schedule": "Schedule" } \ No newline at end of file diff --git a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx index faf2e1f0..4b285a9e 100644 --- a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx +++ b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx @@ -85,7 +85,7 @@ export const SqlQuerySelector: FC = ({ isLoading={isLoading} columns={columns} data={selectedQueries} - noDataMessage="No Queries Configured" + noDataMessage={t('message.no-queries-selected')} /> From 10c5916eaff32ca7847668517da3fe8d598e0290 Mon Sep 17 00:00:00 2001 From: James Brunskill Date: Wed, 11 Oct 2023 15:12:14 +1300 Subject: [PATCH 5/9] Allow selecting no queries --- .../components/NotificationQuerySelectionModal.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx b/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx index 12181b47..1b4571c1 100644 --- a/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx +++ b/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx @@ -52,11 +52,6 @@ export const NotificationQuerySelectionModal: FC< }; const onSubmit = async () => { - if (selectedIds.length === 0) { - setErrorMessage(t('messages.nothing-selected')); - return; - } - setSelection({ notificationQueryIds: selectedIds }); onClose(); }; @@ -72,7 +67,7 @@ export const NotificationQuerySelectionModal: FC< } From 2a8a844d4ea0a9a708dd9310cd8cd159358b818a Mon Sep 17 00:00:00 2001 From: James Brunskill Date: Wed, 11 Oct 2023 15:50:28 +1300 Subject: [PATCH 6/9] Add required parameters from Selected SQL Queries --- .../Pages/Base/BaseNotificationEditPage.tsx | 6 +++++- .../Pages/ColdChain/CCNotificationEditPage.tsx | 1 + .../src/Notifications/Pages/ColdChain/parseConfig.ts | 1 + .../Pages/Scheduled/ScheduledNotificationEditForm.tsx | 1 - .../src/Notifications/Pages/Scheduled/parseConfig.ts | 1 + .../components/NotificationQuerySelectionModal.tsx | 11 +++++++++-- .../src/Notifications/components/SqlQuerySelector.tsx | 5 ++++- frontend/packages/system/src/Notifications/types.ts | 1 + 8 files changed, 22 insertions(+), 5 deletions(-) diff --git a/frontend/packages/system/src/Notifications/Pages/Base/BaseNotificationEditPage.tsx b/frontend/packages/system/src/Notifications/Pages/Base/BaseNotificationEditPage.tsx index bc48bd61..5f58d8be 100644 --- a/frontend/packages/system/src/Notifications/Pages/Base/BaseNotificationEditPage.tsx +++ b/frontend/packages/system/src/Notifications/Pages/Base/BaseNotificationEditPage.tsx @@ -90,11 +90,15 @@ export const BaseNotificationEditPage = ({ }); }; - const requiredParams = (sqlRecipientLists?.nodes ?? []) + const requiredRecipientParams = (sqlRecipientLists?.nodes ?? []) .filter(list => draft.sqlRecipientListIds.includes(list.id)) .map(list => list.parameters) .flat(1); + const requiredConfigParams = draft.requiredParameters; + + const requiredParams = requiredRecipientParams.concat(requiredConfigParams); + const allParamsSet = requiredParams.every(param => { if (param) { return draft.parsedParameters[param] !== undefined; // This allows the user to set the param to an empty string if they edit the field then delete the value diff --git a/frontend/packages/system/src/Notifications/Pages/ColdChain/CCNotificationEditPage.tsx b/frontend/packages/system/src/Notifications/Pages/ColdChain/CCNotificationEditPage.tsx index 5453f615..afa85704 100644 --- a/frontend/packages/system/src/Notifications/Pages/ColdChain/CCNotificationEditPage.tsx +++ b/frontend/packages/system/src/Notifications/Pages/ColdChain/CCNotificationEditPage.tsx @@ -43,6 +43,7 @@ const createCCNotification = ( sqlRecipientListIds: seed?.sqlRecipientListIds ?? [], parameters: seed?.parameters ?? '{}', parsedParameters: seed?.parsedParameters ?? {}, + requiredParameters: seed?.requiredParameters ?? [], }); export const CCNotificationEditPage = () => { diff --git a/frontend/packages/system/src/Notifications/Pages/ColdChain/parseConfig.ts b/frontend/packages/system/src/Notifications/Pages/ColdChain/parseConfig.ts index 30d750ca..cb1c4c66 100644 --- a/frontend/packages/system/src/Notifications/Pages/ColdChain/parseConfig.ts +++ b/frontend/packages/system/src/Notifications/Pages/ColdChain/parseConfig.ts @@ -50,6 +50,7 @@ export function parseColdChainNotificationConfig( status: config.status, parameters: config.parameters, parsedParameters: TeraUtils.keyedParamsFromTeraJson(config.parameters), + requiredParameters: [], }; } catch (e) { showError(); diff --git a/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx b/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx index abd5d6d7..1e11d8b4 100644 --- a/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx +++ b/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx @@ -66,7 +66,6 @@ export const ScheduledNotificationEditForm = ({ selectedQueryIds={draft.notificationQueryIds} isLoading={isLoading} setSelection={props => { - console.log('props', props); onUpdate(props as Partial); }} /> diff --git a/frontend/packages/system/src/Notifications/Pages/Scheduled/parseConfig.ts b/frontend/packages/system/src/Notifications/Pages/Scheduled/parseConfig.ts index 4d4f17bc..a74d4a7c 100644 --- a/frontend/packages/system/src/Notifications/Pages/Scheduled/parseConfig.ts +++ b/frontend/packages/system/src/Notifications/Pages/Scheduled/parseConfig.ts @@ -43,6 +43,7 @@ export const defaultSchedulerNotification: ScheduledNotification = { sqlRecipientListIds: [], parameters: '{}', parsedParameters: {}, + requiredParameters: [], scheduleFrequency: 'daily', scheduleStartTime: new Date(), subjectTemplate: '', diff --git a/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx b/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx index 1b4571c1..15094920 100644 --- a/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx +++ b/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx @@ -21,7 +21,10 @@ interface NotificationQuerySelectionModalProps { initialSelectedIds: string[]; isOpen: boolean; onClose: () => void; - setSelection: (input: { notificationQueryIds: string[] }) => void; + setSelection: (input: { + notificationQueryIds: string[]; + requiredParameters: string[]; + }) => void; } interface NotificationQueryOption { @@ -52,7 +55,11 @@ export const NotificationQuerySelectionModal: FC< }; const onSubmit = async () => { - setSelection({ notificationQueryIds: selectedIds }); + const requiredParameters = sqlQueries + .filter(sqlQuery => selectedIds.includes(sqlQuery.id)) + .map(sqlQuery => sqlQuery.requiredParameters) + .flat(); + setSelection({ notificationQueryIds: selectedIds, requiredParameters }); onClose(); }; diff --git a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx index 4b285a9e..06b057e8 100644 --- a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx +++ b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx @@ -16,7 +16,10 @@ import { NotificationQueryRowFragment } from '../../Queries/api'; type QueryListProps = { allQueries: NotificationQueryRowFragment[]; selectedQueryIds: string[]; - setSelection: (input: { notificationQueryIds: string[] }) => void; + setSelection: (input: { + notificationQueryIds: string[]; + requiredParameters: string[]; + }) => void; isLoading: boolean; }; diff --git a/frontend/packages/system/src/Notifications/types.ts b/frontend/packages/system/src/Notifications/types.ts index df86bf16..ce994e81 100644 --- a/frontend/packages/system/src/Notifications/types.ts +++ b/frontend/packages/system/src/Notifications/types.ts @@ -42,6 +42,7 @@ type BaseConfig = Pick< export interface BaseNotificationConfig extends BaseConfig { parsedParameters: KeyedParams; + requiredParameters: string[]; } export interface CCNotification extends BaseNotificationConfig { From ac0ea936b31daf36366bdde7827146458d27746b Mon Sep 17 00:00:00 2001 From: Mark Prins Date: Tue, 17 Oct 2023 10:17:18 +1300 Subject: [PATCH 7/9] some ui suggestions --- .../ScheduledNotificationEditForm.tsx | 164 ++++++++++-------- .../ScheduledNotificationEditPage.tsx | 4 + .../components/SqlQuerySelector.tsx | 19 +- 3 files changed, 107 insertions(+), 80 deletions(-) diff --git a/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx b/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx index 1e11d8b4..b35d228b 100644 --- a/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx +++ b/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditForm.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { BasicTextInput, + Box, BufferedTextArea, DateTimeInput, Select, @@ -17,6 +18,21 @@ type ScheduledNotificationEditFormProps = { draft: ScheduledNotification; }; +const FormRow = ({ + title, + children, +}: { + title: string; + children: React.ReactNode; +}) => ( + + + {title} + + {children} + +); + export const ScheduledNotificationEditForm = ({ onUpdate, draft, @@ -29,77 +45,81 @@ export const ScheduledNotificationEditForm = ({ const queries = data?.nodes ?? []; return ( - <> - - onUpdate({ - subjectTemplate: e.target - .value as ScheduledNotification['subjectTemplate'], - }) - } - label={t('label.subject-template')} - InputLabelProps={{ shrink: true }} - /> - onUpdate({ bodyTemplate: e.target.value })} - label={t('label.body-template')} - InputProps={{ sx: { backgroundColor: 'background.menu' } }} - InputLabelProps={{ shrink: true }} - /> - - onUpdate({ parameters: e.target.value })} - label={t('label.parameters')} - InputProps={{ sx: { backgroundColor: 'background.menu' } }} - InputLabelProps={{ shrink: true }} - /> - - {t('label.queries')} - - { - onUpdate(props as Partial); - }} - /> - - - {t('label.schedule')} - - Starting From - - onUpdate({ - scheduleStartTime: d as ScheduledNotification['scheduleStartTime'], - }) - } - date={draft.scheduleStartTime} - /> - Repeat - + onUpdate({ + scheduleFrequency: e.target + .value as ScheduledNotification['scheduleFrequency'], + }) + } + options={[ + { label: t('label.daily'), value: 'daily' }, + { label: t('label.weekly'), value: 'weekly' }, + { label: t('label.monthly'), value: 'monthly' }, + ]} + /> + + ); }; diff --git a/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditPage.tsx b/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditPage.tsx index b9e43459..52fb975e 100644 --- a/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditPage.tsx +++ b/frontend/packages/system/src/Notifications/Pages/Scheduled/ScheduledNotificationEditPage.tsx @@ -3,6 +3,7 @@ import { useTranslation, useNotification, useParams, + useBreadcrumbs, } from '@notify-frontend/common'; import { ScheduledNotificationEditForm } from './ScheduledNotificationEditForm'; import { BaseNotificationEditPage } from '../Base/BaseNotificationEditPage'; @@ -22,6 +23,7 @@ export const ScheduledNotificationEditPage = () => { const t = useTranslation('system'); const { error } = useNotification(); const parsingErrorSnack = error(t('error.parsing-notification-config')); + const { setSuffix } = useBreadcrumbs(); const { id } = useParams<{ id: string }>(); const [draft, setDraft] = useState( @@ -32,6 +34,7 @@ export const ScheduledNotificationEditPage = () => { const { data, isLoading } = useNotificationConfigs({ filterBy: { id: { equalTo: id } }, }); + useEffect(() => { const entity = data?.nodes[0]; // Once we get the notification config from the API, parse it and load into the draft @@ -40,6 +43,7 @@ export const ScheduledNotificationEditPage = () => { parsingErrorSnack ); setDraft(parsedDraft ?? defaultSchedulerNotification); + if (parsedDraft?.title) setSuffix(parsedDraft?.title); }, [data]); const { mutateAsync: update, isLoading: updateIsLoading } = diff --git a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx index 06b057e8..c0683314 100644 --- a/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx +++ b/frontend/packages/system/src/Notifications/components/SqlQuerySelector.tsx @@ -9,6 +9,7 @@ import { TableProvider, createTableStore, LoadingButton, + Box, } from '@notify-frontend/common'; import { NotificationQuerySelectionModal } from './NotificationQuerySelectionModal'; import { NotificationQueryRowFragment } from '../../Queries/api'; @@ -74,14 +75,6 @@ export const SqlQuerySelector: FC = ({ onClose={onClose} setSelection={setSelection} /> - } - > - {t('label.select-queries')} - = ({ noDataMessage={t('message.no-queries-selected')} /> + + } + > + {t('label.select-queries')} + + ); }; From 4066af3fa176f510b2fb50dbd3d47b5d5403b9bf Mon Sep 17 00:00:00 2001 From: James Brunskill Date: Wed, 25 Oct 2023 15:18:25 +1300 Subject: [PATCH 8/9] Use a dialog button for select queries modal --- .../NotificationQuerySelectionModal.tsx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx b/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx index 15094920..35e087d7 100644 --- a/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx +++ b/frontend/packages/system/src/Notifications/components/NotificationQuerySelectionModal.tsx @@ -9,10 +9,8 @@ import { AutocompleteOptionRenderer, Checkbox, DialogButton, - LoadingButton, Tooltip, } from '@common/components'; -import { CheckIcon } from '@common/icons'; import { NotificationQueryRowFragment } from '../../Queries/api'; import { Grid } from '@common/ui'; @@ -71,18 +69,7 @@ export const NotificationQuerySelectionModal: FC< height={modalHeight} width={modalWidth} okButton={ - - - } - > - {t('label.select-queries')} - - - + } cancelButton={} title={t('label.select-queries')} From 9d2a339ac27d5877139b862acacfa11c014a8e05 Mon Sep 17 00:00:00 2001 From: James Brunskill Date: Wed, 25 Oct 2023 15:31:57 +1300 Subject: [PATCH 9/9] Make required parameters more obvious --- .../src/Notifications/Pages/Base/NotificationDetailPanel.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/packages/system/src/Notifications/Pages/Base/NotificationDetailPanel.tsx b/frontend/packages/system/src/Notifications/Pages/Base/NotificationDetailPanel.tsx index a0d0410f..facc0ef2 100644 --- a/frontend/packages/system/src/Notifications/Pages/Base/NotificationDetailPanel.tsx +++ b/frontend/packages/system/src/Notifications/Pages/Base/NotificationDetailPanel.tsx @@ -42,6 +42,7 @@ export const NotificationDetailPanel = ({ onUpdateParams(param ?? '', e.target.value)} + error={requiredParams.includes(param) && !params[param ?? '']} /> { // if param is not required allow it to be removed