From 1c63e3c80982b26cf0ca90f15f83be18b95c8716 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 13 Jul 2026 14:48:29 -0400 Subject: [PATCH 01/35] move byReport away from slices --- .../Scripts/TSX/Report/ByReport.tsx | 85 +++++++++++++------ 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ByReport.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ByReport.tsx index 26a6f4f19..dc96bb44d 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ByReport.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ByReport.tsx @@ -21,13 +21,11 @@ // //****************************************************************************************************** -import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; -import { LoadingScreen, Modal, Search, SearchBar } from '@gpa-gemstone/react-interactive' +import { LoadingScreen, Modal, Search, SearchBar, GenericController } from '@gpa-gemstone/react-interactive' import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { Application } from '@gpa-gemstone/application-typings'; -import { ScheduledEmailType } from '../global'; -import { EmailCategorySlice, ScheduledEmailTypeSlice } from '../Store'; +import { ScheduledEmailType, EmailCategory } from '../global'; import { Table, Column, Paging } from '@gpa-gemstone/react-table'; import { IsCron } from '@gpa-gemstone/helper-functions'; import ReportForm from './ReportForm'; @@ -50,17 +48,14 @@ const emptyEmail: ScheduledEmailType = { interface IProps {} const ByReport = (props: IProps) => { - const dispatch = useAppDispatch(); const navigate = useNavigate(); - - const search: Search.IFilter[] = useAppSelector(ScheduledEmailTypeSlice.SearchFilters); - const status: Application.Types.Status = useAppSelector(ScheduledEmailTypeSlice.Status); - const searchStatus: Application.Types.Status = useAppSelector(ScheduledEmailTypeSlice.SearchStatus); - const data: ScheduledEmailType[] = useAppSelector(ScheduledEmailTypeSlice.SearchResults); - const allData: ScheduledEmailType[] = useAppSelector(ScheduledEmailTypeSlice.Data); - const categoryStatus = useAppSelector(EmailCategorySlice.Status); - const categories = useAppSelector(EmailCategorySlice.Data); - const parentID = useAppSelector(ScheduledEmailTypeSlice.ParentID); + const [filters, setFilters] = React.useState[]>([]) + const [status, setStatus] = React.useState('uninitiated'); + const [searchStatus, setSearchStatus] = React.useState('uninitiated'); + const [data, setData] = React.useState([]); + const [allData, setAllData] = React.useState([]); + const [categoryStatus, setCategoryStatus] = React.useState('uninitiated'); + const [categories, setCategories] = React.useState([]); const [showModal, setShowModal] = React.useState(false); const [errors, setErrors] = React.useState([]); @@ -71,24 +66,60 @@ const ByReport = (props: IProps) => { const [ascending, setAscending] = React.useState(false); const [page, setPage] = React.useState(0); - const totalPages = useAppSelector(ScheduledEmailTypeSlice.TotalPages); - const totalRecords = useAppSelector(ScheduledEmailTypeSlice.TotalRecords); - const recordsPerPage = useAppSelector(ScheduledEmailTypeSlice.RecordsPerPage); - + const [totalPages, setTotalPages] = React.useState(0); + const [totalRecords, setTotalRecords] = React.useState(0); + const [recordsPerPage, setRecordsPerPage] = React.useState(0); const [refreshTrigger, setRefreshTrigger] = React.useState(false); + const scheduledEmailTypeController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/ScheduledEmailType`, "Name", true), []) + const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []) + React.useEffect(() => { - if (categoryStatus == 'uninitiated' || categoryStatus == 'changed') - dispatch(EmailCategorySlice.Fetch()); - }, []); + setCategoryStatus('loading') + const h = emailCategoryController.Fetch(); + h.done((d) => { + setCategories(d) + setCategoryStatus('idle') + }); + h.fail(() => setCategoryStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [emailCategoryController.Fetch]); React.useEffect(() => { - dispatch(ScheduledEmailTypeSlice.Fetch()); - }, [parentID, refreshTrigger]); + setStatus('uninitiated') + const h = scheduledEmailTypeController.Fetch(); + h.done((d) => { + setAllData(d) + setStatus('idle') + }); + h.fail(() => setStatus('error')) + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + }, [scheduledEmailTypeController.Fetch, refreshTrigger]); React.useEffect(() => { - dispatch(ScheduledEmailTypeSlice.PagedSearch({ filter: undefined, sortField, ascending: ascending, page: page })); - }, [sortField, ascending, page, refreshTrigger]) + setSearchStatus('loading') + const h = scheduledEmailTypeController.PagedSearch(filters, sortField, ascending, page); + h.done((d) => { + setData(JSON.parse(d.Data as unknown as string)) + setTotalPages(d.NumberOfPages); + setRecordsPerPage(d.RecordsPerPage); + setTotalRecords(d.TotalRecords); + setSearchStatus('idle'); + }); + h.fail(() => setSearchStatus('error')) + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + }, [sortField, filters, ascending, page, refreshTrigger, scheduledEmailTypeController.PagedSearch]) React.useEffect(() => { let e = []; @@ -122,7 +153,7 @@ const ByReport = (props: IProps) => {
CollumnList={searchFields} - SetFilter={(flds) => dispatch(ScheduledEmailTypeSlice.PagedSearch({ filter: flds }))} + SetFilter={setFilters} Direction={'left'} defaultCollumn={{ key: 'Name', label: 'Name', type: 'string', isPivotField: false }} Width={'50%'} Label={'Search'} ShowLoading={searchStatus === 'loading'} ResultNote={searchStatus === 'error' ? 'Could not complete Search' : `Displaying Report(s) ${totalRecords > 0 ? recordsPerPage * page + 1 : 0}-${recordsPerPage * page + data.length} out of ${totalRecords}`} GetEnum={() => { @@ -228,7 +259,7 @@ const ByReport = (props: IProps) => { Show={showModal} ShowX={true} Size={'lg'} ShowCancel={false} ConfirmText={'Add'} CallBack={(conf, isBtn) => { if (conf) - dispatch(ScheduledEmailTypeSlice.DBAction({ verb: "POST", record: newEmail })).then(() => setRefreshTrigger((val) => !val)) + scheduledEmailTypeController.DBAction("POST", newEmail).then(() => setRefreshTrigger((val) => !val)) setShowModal(false); }} DisableConfirm={errors.length > 0} From edcf35dd304df37babd4172073d36e1ed2b9c97c Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 13 Jul 2026 15:16:20 -0400 Subject: [PATCH 02/35] move cell carrier away from slices --- .../Scripts/TSX/CellCarrier/ByCellCarrier.tsx | 61 +++++++++++++------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/CellCarrier/ByCellCarrier.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/CellCarrier/ByCellCarrier.tsx index 039d8c115..768d0ea40 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/CellCarrier/ByCellCarrier.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/CellCarrier/ByCellCarrier.tsx @@ -22,16 +22,13 @@ //****************************************************************************************************** import * as React from 'react'; -import { LoadingScreen, Modal, Search, SearchBar } from '@gpa-gemstone/react-interactive' +import { LoadingScreen, Modal, Search, SearchBar, GenericController } from '@gpa-gemstone/react-interactive' import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { Application } from '@gpa-gemstone/application-typings'; import { Table, Column, Paging } from '@gpa-gemstone/react-table'; -import moment from 'moment'; import { ICellCarrier } from '../global'; import { CellCarrierSlice } from '../Store'; -import { useAppDispatch, useAppSelector } from '../hooks'; import { Input } from '@gpa-gemstone/react-forms'; -import { castArray } from 'lodash'; declare var homePath; @@ -46,30 +43,54 @@ const searchFields: Search.IField[] = [ interface IProps {} const ByCellCarrier = (props: IProps) => { - const dispatch = useAppDispatch(); - - const searchStatus: Application.Types.Status = useAppSelector(CellCarrierSlice.SearchStatus); - const status: Application.Types.Status = useAppSelector(CellCarrierSlice.Status); - const data: ICellCarrier[] = useAppSelector(CellCarrierSlice.SearchResults); - const allData: ICellCarrier[] = useAppSelector(CellCarrierSlice.Data); + const [searchStatus, setSearchStatus] = React.useState('uninitiated'); + const [fetchStatus, setFetchStatus] = React.useState('uninitiated'); + const [status, setStatus] = React.useState('uninitiated'); + const [data, setData] = React.useState([]); + const [allData, setAllData] = React.useState([]); const [sortField, setSortField] = React.useState('Name'); const [ascending, setAscending] = React.useState(true); const [filters, setFilters] = React.useState[]>([]); const [showModal, setShowModal] = React.useState<'New' | 'Edit' | 'Hide'>('Hide'); const [carrier, setCarrier] = React.useState(emptyCarrier); const [page, setPage] = React.useState(0); - const totalPages = useAppSelector(CellCarrierSlice.TotalPages) - const recordsPerPage = useAppSelector(CellCarrierSlice.RecordsPerPage); - const totalRecords = useAppSelector(CellCarrierSlice.TotalRecords); + const [totalPages, setTotalPages] = React.useState(0); + const [recordsPerPage, setRecordsPerPage] = React.useState(0); + const [totalRecords, setTotalRecords] = React.useState(0); const [refreshTrigger, setRefreshTrigger] = React.useState(false); + const cellCarrierController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/CellCarrier`, "Name", true),[]) + React.useEffect(() => { - dispatch(CellCarrierSlice.PagedSearch({ filter: filters, sortField, ascending: ascending, page: page })); - }, [page, filters, sortField, ascending, refreshTrigger]) + setStatus('uninitiated') + const h = cellCarrierController.PagedSearch(filters, sortField, ascending, page); + h.done((d) => { + setData(JSON.parse(d.Data as unknown as string)); + setTotalPages(d.NumberOfPages); + setTotalRecords(d.TotalRecords); + setRecordsPerPage(d.RecordsPerPage); + setStatus('idle'); + }) + h.fail(() => setStatus('error')) + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + }, [page, filters, sortField, ascending, refreshTrigger, cellCarrierController.PagedSearch]) React.useEffect(() => { - dispatch(CellCarrierSlice.Fetch()); - }, [refreshTrigger]) + setFetchStatus('uninitiated') + const h = cellCarrierController.Fetch(); + h.done((d) => { + setAllData(d) + setFetchStatus('idle') + }) + h.fail(() => setStatus('error')) + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + }, [refreshTrigger, cellCarrierController.Fetch]) return (
@@ -161,11 +182,11 @@ const ByCellCarrier = (props: IProps) => { } ConfirmBtnClass={'btn-primary'} CallBack={(c, b) => { if (showModal == 'New' && c) - dispatch(CellCarrierSlice.DBAction({ verb: 'POST', record: carrier })).then(() => setRefreshTrigger((val) => !val)); + cellCarrierController.DBAction('POST', carrier).then(() => setRefreshTrigger((val) => !val)); if (showModal == 'Edit' && c) - dispatch(CellCarrierSlice.DBAction({ verb: 'PATCH', record: carrier })).then(() => setRefreshTrigger((val) => !val)); + cellCarrierController.DBAction('PATCH', carrier).then(() => setRefreshTrigger((val) => !val)); if (showModal == 'Edit' && b && !c) - dispatch(CellCarrierSlice.DBAction({ verb: 'DELETE', record: carrier })).then(() => setRefreshTrigger((val) => !val)); + cellCarrierController.DBAction('DELETE', carrier).then(() => setRefreshTrigger((val) => !val)); setShowModal('Hide'); }} From 2704a4aed1e1b1a0a019c57b1061016a1351a479 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 13 Jul 2026 15:47:38 -0400 Subject: [PATCH 03/35] remove cell carrier slice --- .../Scripts/TSX/CellCarrier/ByCellCarrier.tsx | 1 - .../Scripts/TSX/Store.tsx | 4 ---- .../TSX/Subscriptions/ConfirmCarrier.tsx | 22 ++++++++++++++---- .../TSX/UserInformation/ByUserInformation.tsx | 23 +++++++++++++------ 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/CellCarrier/ByCellCarrier.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/CellCarrier/ByCellCarrier.tsx index 768d0ea40..27c05ec88 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/CellCarrier/ByCellCarrier.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/CellCarrier/ByCellCarrier.tsx @@ -27,7 +27,6 @@ import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { Application } from '@gpa-gemstone/application-typings'; import { Table, Column, Paging } from '@gpa-gemstone/react-table'; import { ICellCarrier } from '../global'; -import { CellCarrierSlice } from '../Store'; import { Input } from '@gpa-gemstone/react-forms'; diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/Store.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/Store.tsx index 6a9a49902..5a633a1d7 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/Store.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/Store.tsx @@ -67,9 +67,6 @@ export const ScheduledDataSourceSlice = new GenericSlice(" export const ScheduledEmailDataSourceSlice = new GenericSlice("ScheduledEmailDataSourceEmailType", `${homePath}api/OpenXDA/ScheduledEmailDataSourceEmailType`, "ScheduledEmailDataSourceName", false); export const ScheduledDataSourceSettingSlice = new GenericSlice("ScheduledDataSourceSetting", `${homePath}api/OpenXDA/ScheduledEmailDataSourceSetting`, "Name", false); - -export const CellCarrierSlice = new GenericSlice("CellCarrier", `${homePath}api/OpenXDA/CellCarrier`, "Name", true); - const reducer = { EmailCategory: EmailCategorySlice.Reducer, EmailType: EmailTypeSlice.Reducer, @@ -87,7 +84,6 @@ const reducer = { TriggeredEmailDataSource: TriggeredEmailDataSourceSlice.Reducer, TriggeredDataSource: TriggeredDataSourceSlice.Reducer, UserAccount: UserAccountSlice.Reducer, - CellCarrier: CellCarrierSlice.Reducer, ScheduledEmailType: ScheduledEmailTypeSlice.Reducer, ActiveReportSubscription: ActiveReportSubscriptionSlice.Reducer, ReportSubscription: ReportSubscriptionSlice.Reducer, diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/Subscriptions/ConfirmCarrier.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/Subscriptions/ConfirmCarrier.tsx index 6464c135a..521d29409 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/Subscriptions/ConfirmCarrier.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/Subscriptions/ConfirmCarrier.tsx @@ -22,9 +22,11 @@ //****************************************************************************************************** import * as React from 'react'; -import { CellCarrierSlice, UserInfoSlice } from '../Store'; +import { UserInfoSlice } from '../Store'; import { useAppDispatch, useAppSelector } from '../hooks'; +import { Application } from '@gpa-gemstone/application-typings'; import { Select } from '@gpa-gemstone/react-forms'; +import { GenericController } from '@gpa-gemstone/react-interactive'; import { ICellCarrier } from '../global'; const emptyCarrier: ICellCarrier = { @@ -41,12 +43,22 @@ const ConfirmPhoneCarrier = (props: IProps) => { const [currentCarrier, setCurrentCarrier] = React.useState(emptyCarrier); const userCarrier = useAppSelector(UserInfoSlice.CellCarrierID); - const carriers = useAppSelector(CellCarrierSlice.Data); - const carrierStatus = useAppSelector(CellCarrierSlice.Status); + const [carriers, setCarriers] = React.useState([]); + const [carrierStatus, setCarrierStatus] = React.useState('uninitiated'); + + const cellCarrierController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/CellCarrier`, "Name", true), []) + React.useEffect(() => { - if (carrierStatus == 'uninitiated' || carrierStatus == 'changed') - dispatch(CellCarrierSlice.Fetch()); + setCarrierStatus('loading'); + const h = cellCarrierController.Fetch(); + h.done((d) => { + setCarrierStatus('idle'); + setCarriers(d); + }) + h.fail(() => { + setCarrierStatus('error'); + }) }, [carrierStatus]); React.useEffect(() => { diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/UserInformation/ByUserInformation.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/UserInformation/ByUserInformation.tsx index 9da01348d..075064dfc 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/UserInformation/ByUserInformation.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/UserInformation/ByUserInformation.tsx @@ -24,11 +24,13 @@ import * as React from 'react'; import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { useAppDispatch, useAppSelector } from '../hooks'; -import { CellCarrierSlice, UserInfoSlice } from '../Store'; +import { UserInfoSlice } from '../Store'; import { IsInteger } from '@gpa-gemstone/helper-functions'; +import { Application } from '@gpa-gemstone/application-typings'; import EmailConfirm from '../Subscriptions/ConfirmEmail'; import { ICellCarrier } from '../global'; import { Select, Input, ToolTip } from '@gpa-gemstone/react-forms'; +import { GenericController } from '@gpa-gemstone/react-interactive'; declare var homePath; declare var version; @@ -44,18 +46,25 @@ const ByUserInformation = (props: IProps) => { const [hover, setHover] = React.useState<('submit' | 'clear' | 'none')>('none'); const [validPhone, setValidPhone] = React.useState(false); - - const carriers = useAppSelector(CellCarrierSlice.Data); - const carrierStatus = useAppSelector(CellCarrierSlice.Status); + + const [carriers, setCarriers] = React.useState([]); + const [carrierStatus, setCarrierStatus] = React.useState('uninitiated'); const userPhone = useAppSelector(UserInfoSlice.CellPhone); const userCarrier = useAppSelector(UserInfoSlice.CellCarrierID); const emailConfirmed = useAppSelector(UserInfoSlice.ConfirmedEmail); - + const cellCarrierController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/CellCarrier`, "Name", true), []) React.useEffect(() => { - if (carrierStatus == 'uninitiated' || carrierStatus == 'changed') - dispatch(CellCarrierSlice.Fetch()); + setCarrierStatus('loading'); + const h = cellCarrierController.Fetch(); + h.done((d) => { + setCarrierStatus('idle'); + setCarriers(d); + }) + h.fail(() => { + setCarrierStatus('error'); + }) }, [carrierStatus]); React.useEffect(() => { From 88409f903f70608795c1f08a46ba6f146723a0db Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 13 Jul 2026 15:59:53 -0400 Subject: [PATCH 04/35] remove email category slice --- .../TSX/EmailCategory/ByEmailCategory.tsx | 54 +++++++++++++------ .../TSX/EmailCategory/EmailCategoryForm.tsx | 28 +++++++--- .../TSX/EmailCategory/EmailCategoryPage.tsx | 43 ++++++++++----- .../TSX/EmailCategory/EmailCategoryWindow.tsx | 30 ++++++++--- .../Scripts/TSX/EmailTypes/ByEmailType.tsx | 26 ++++++--- .../Scripts/TSX/EmailTypes/EmailForm.tsx | 28 +++++++--- .../Scripts/TSX/Report/ReportForm.tsx | 30 ++++++++--- .../Scripts/TSX/Store.tsx | 6 +-- 8 files changed, 177 insertions(+), 68 deletions(-) diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/ByEmailCategory.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/ByEmailCategory.tsx index 8aa58fdc0..7b37f3b4f 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/ByEmailCategory.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/ByEmailCategory.tsx @@ -21,13 +21,11 @@ // //****************************************************************************************************** -import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; -import { LoadingScreen, Modal, Search, SearchBar } from '@gpa-gemstone/react-interactive' +import { LoadingScreen, Modal, Search, SearchBar, GenericController } from '@gpa-gemstone/react-interactive' import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { Application } from '@gpa-gemstone/application-typings'; import { EmailCategory } from '../global'; -import { EmailCategorySlice } from '../Store'; import { Table, Column, Paging } from '@gpa-gemstone/react-table'; import EmailCategoryForm from './EmailCategoryForm'; import { useNavigate } from 'react-router-dom'; @@ -37,31 +35,55 @@ interface IProps { } const ByEmailCategory = (props: IProps) => { const navigate = useNavigate(); - const dispatch = useAppDispatch(); const [search, setSearch] = React.useState[]>([]); - const status: Application.Types.Status = useAppSelector(EmailCategorySlice.Status); - const searchStatus: Application.Types.Status = useAppSelector(EmailCategorySlice.SearchStatus); - const data: EmailCategory[] = useAppSelector(EmailCategorySlice.SearchResults); - const allData: EmailCategory[] = useAppSelector(EmailCategorySlice.Data); + const [status, setStatus] = React.useState('uninitiated'); + const [searchStatus, setSearchStatus] = React.useState('uninitiated'); + const [data, setData] = React.useState([]); + const [allData, setAllData] = React.useState([]); const [showModal, setShowModal] = React.useState(false); const [errors, setErrors] = React.useState([]); const [newEmailCategory, setNewEmailCategory] = React.useState({ ID: -1, Name: '', SelfSubscribe: true }); const [sortField, setSortField] = React.useState('Name'); const [asc, setAsc] = React.useState(true); const [page, setPage] = React.useState(0); - const totalPages: number = useAppSelector(EmailCategorySlice.TotalPages); - const totalRecords: number = useAppSelector(EmailCategorySlice.TotalRecords); - const recordsPerPage: number = useAppSelector(EmailCategorySlice.RecordsPerPage); + const [totalPages, setTotalPages] = React.useState(0); + const [recordsPerPage, setRecordsPerPage] = React.useState(0); + const [totalRecords, setTotalRecords] = React.useState(0); const [refreshTrigger, setRefreshTrigger] = React.useState(false) + const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []); + React.useEffect(() => { - dispatch(EmailCategorySlice.Fetch()); - }, [refreshTrigger]); + setStatus('uninitiated') + const h = emailCategoryController.Fetch(); + h.done((d) => { + setAllData(d) + setStatus('idle') + }) + h.fail(() => setStatus('error')) + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + }, [refreshTrigger, emailCategoryController.Fetch]); React.useEffect(() => { - dispatch(EmailCategorySlice.PagedSearch({ filter: search, sortField, ascending: asc, page: page })); - }, [search, sortField, asc, page, refreshTrigger]) + setStatus('uninitiated') + const h = emailCategoryController.PagedSearch(search, sortField, asc, page); + h.done((d) => { + setData(JSON.parse(d.Data as unknown as string)); + setTotalPages(d.NumberOfPages); + setTotalRecords(d.TotalRecords); + setRecordsPerPage(d.RecordsPerPage); + setStatus('idle'); + }) + h.fail(() => setStatus('error')) + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + }, [search, sortField, asc, page, refreshTrigger, emailCategoryController.PagedSearch]) React.useEffect(() => { let e = []; @@ -159,7 +181,7 @@ const ByEmailCategory = (props: IProps) => { Show={showModal} ShowX={true} Size={'lg'} ShowCancel={false} ConfirmText={'Add'} CallBack={(conf) => { if (conf) - dispatch(EmailCategorySlice.DBAction({ verb: "POST", record: newEmailCategory })).then(()=>setRefreshTrigger((val) => !val)); + emailCategoryController.DBAction("POST",newEmailCategory).then(()=>setRefreshTrigger((val) => !val)); setShowModal(false); }} DisableConfirm={errors.length > 0} diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryForm.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryForm.tsx index 32524c793..08169808b 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryForm.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryForm.tsx @@ -21,24 +21,36 @@ // //****************************************************************************************************** -import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; import { EmailCategory } from '../global'; -import { EmailCategorySlice } from '../Store'; import { CheckBox, Input } from '@gpa-gemstone/react-forms'; +import { GenericController } from '@gpa-gemstone/react-interactive'; +import { Application } from '@gpa-gemstone/application-typings'; interface IProps { record: EmailCategory, setRecord: (d: EmailCategory) => void } const EmailCategoryForm = (props: IProps) => { - const dispatch = useAppDispatch(); - const emailCategories = useAppSelector(EmailCategorySlice.Data); - const status = useAppSelector(EmailCategorySlice.Status); + const [emailCategories, setEmailCategories] = React.useState([]); + const [status, setStatus] = React.useState('uninitiated'); + + const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []) React.useEffect(() => { - if (status == 'uninitiated' || status == 'changed') - dispatch(EmailCategorySlice.Fetch()); - }, [status]); + setStatus('loading') + const h = emailCategoryController.Fetch(); + h.done((d) => { + setEmailCategories(d) + setStatus('idle') + }); + h.fail(() => setStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [emailCategoryController.Fetch]); return (
diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryPage.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryPage.tsx index ae2f3674e..ec48a71ff 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryPage.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryPage.tsx @@ -21,12 +21,12 @@ // //****************************************************************************************************** -import { useAppDispatch, useAppSelector } from '../hooks'; +import * as $ from 'jquery' import * as React from 'react'; -import { LoadingScreen, TabSelector, Warning } from '@gpa-gemstone/react-interactive'; +import { LoadingScreen, TabSelector, Warning, GenericController } from '@gpa-gemstone/react-interactive'; import { Application } from '@gpa-gemstone/application-typings'; -import { EmailCategorySlice } from '../Store'; import EmailCategoryWindow from './EmailCategoryWindow'; +import { EmailCategory } from '../global'; import EmailList from './EmailList'; interface IProps { useParams: { id: string } } @@ -39,12 +39,11 @@ const Tabs = [ const EmailCategoryPage = (props: IProps) => { - const dispatch = useAppDispatch(); - + const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []); const [showDelete, setShowDelete] = React.useState(false); - const category = useAppSelector((state) => EmailCategorySlice.Datum(state, parseInt(props.useParams.id))); - const status: Application.Types.Status = useAppSelector(EmailCategorySlice.Status); + const [category, setCategory] = React.useState(null); + const [status, setStatus] = React.useState('uninitiated'); const getTab = React.useCallback(() => { if (sessionStorage.hasOwnProperty('EmailCategory.Tab')) @@ -54,17 +53,35 @@ const EmailCategoryPage = (props: IProps) => { const [tab, setTab] = React.useState(getTab()); - React.useEffect(() => { - if (status == 'uninitiated' || status == 'changed') - dispatch(EmailCategorySlice.Fetch()); - }, [status]); - React.useEffect(() => { const saved = getTab(); if (saved !== tab) sessionStorage.setItem('EmailCategory.Tab', JSON.stringify(tab)); }, [tab]); + React.useEffect(() => { + setStatus('loading') + const h = $.ajax({ + type: "GET", + url: `${homePath}api/OpenXDA/EmailCategory/One/${props.useParams.id}`, + contentType: "application/json; charset=utf-8", + dataType: 'json', + cache: false, + async: true + }) + h.done((d) => { + setCategory(d); + setStatus('idle') + }) + h.fail(() => { + setStatus('error') + }) + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + }, [props.useParams.id]) + return (
@@ -104,7 +121,7 @@ const EmailCategoryPage = (props: IProps) => { Title={`Delete ${category?.Name ?? 'Email Category'}`} CallBack={(conf) => { if (conf) { - dispatch(EmailCategorySlice.DBAction({ verb: 'DELETE', record: category })); + emailCategoryController.DBAction('DELETE',category); window.location.href = `${homePath}/Categories`; } setShowDelete(false); diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryWindow.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryWindow.tsx index 37d69c081..7aefc7ae6 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryWindow.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailCategory/EmailCategoryWindow.tsx @@ -21,29 +21,47 @@ // //****************************************************************************************************** -import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; -import { Warning } from '@gpa-gemstone/react-interactive'; +import { Warning, GenericController } from '@gpa-gemstone/react-interactive'; import { ToolTip } from '@gpa-gemstone/react-forms'; import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { EmailCategory } from '../global'; -import { EmailCategorySlice } from '../Store'; import EmailCategoryForm from './EmailCategoryForm'; +import { Application } from '@gpa-gemstone/application-typings'; interface IProps { Category: EmailCategory } const EmailCategoryWindow = (props: IProps) => { - const dispatch = useAppDispatch(); const [category, setCategory] = React.useState(props.Category); const [hasChanged, setHasChanged] = React.useState(false); const [hover, setHover] = React.useState<('submit' | 'clear' | 'none')>('none'); - const categories = useAppSelector(EmailCategorySlice.Data); + const [categories, setCategories] = React.useState([]) + const [status, setStatus] = React.useState('uninitiated'); const [errors, setErrors] = React.useState([]); + + const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []) + + React.useEffect(() => { + setStatus('loading') + const h = emailCategoryController.Fetch(); + h.done((d) => { + setCategories(d) + setStatus('idle') + }); + h.fail(() => setStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [emailCategoryController.Fetch]); + React.useEffect(() => { let e = []; if (category.Name == undefined || category.Name.length < 1) @@ -78,7 +96,7 @@ const EmailCategoryWindow = (props: IProps) => {
diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailTypes/ByEmailType.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailTypes/ByEmailType.tsx index 438f01561..91bf81310 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailTypes/ByEmailType.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailTypes/ByEmailType.tsx @@ -23,11 +23,11 @@ import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; -import { LoadingScreen, Modal, Search, SearchBar } from '@gpa-gemstone/react-interactive' +import { LoadingScreen, Modal, Search, SearchBar, GenericController } from '@gpa-gemstone/react-interactive' import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { Application } from '@gpa-gemstone/application-typings'; -import { EmailType } from '../global'; -import { EmailCategorySlice, EmailTypeSlice } from '../Store'; +import { EmailType, EmailCategory } from '../global'; +import { EmailTypeSlice } from '../Store'; import { Table, Column, Paging } from '@gpa-gemstone/react-table'; import EmailForm from './EmailForm'; import { IsNumber } from '@gpa-gemstone/helper-functions'; @@ -62,7 +62,8 @@ const ByEmailType = (props: IProps) => { const searchStatus: Application.Types.Status = useAppSelector(EmailTypeSlice.SearchStatus); const data: EmailType[] = useAppSelector(EmailTypeSlice.SearchResults); const allData: EmailType[] = useAppSelector(EmailTypeSlice.Data); - const categories = useAppSelector(EmailCategorySlice.Data); + const [categoryStatus, setCategoryStatus] = React.useState('uninitiated'); + const [categories, setCategories] = React.useState([]); const parentID = useAppSelector(EmailTypeSlice.ParentID); const [showModal, setShowModal] = React.useState(false); @@ -78,10 +79,23 @@ const ByEmailType = (props: IProps) => { const [refreshTrigger, setRefreshTrigger] = React.useState(false) + const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []) React.useEffect(() => { - dispatch(EmailCategorySlice.Fetch()); - }, [refreshTrigger]); + setCategoryStatus('loading') + const h = emailCategoryController.Fetch(); + h.done((d) => { + setCategories(d) + setCategoryStatus('idle') + }); + h.fail(() => setCategoryStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [emailCategoryController.Fetch]); React.useEffect(() => { dispatch(EmailTypeSlice.Fetch()); diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailTypes/EmailForm.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailTypes/EmailForm.tsx index 2bfbb6d66..5064f2f52 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailTypes/EmailForm.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/EmailTypes/EmailForm.tsx @@ -24,9 +24,11 @@ import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; import { EmailCategory, EmailType } from '../global'; -import { EmailCategorySlice, EmailTypeSlice } from '../Store'; +import { EmailTypeSlice } from '../Store'; import { CheckBox, Input, Select } from '@gpa-gemstone/react-forms'; -import { IsNumber } from '@gpa-gemstone/helper-functions' +import { IsNumber } from '@gpa-gemstone/helper-functions'; +import { Application } from '@gpa-gemstone/application-typings'; +import { GenericController } from '@gpa-gemstone/react-interactive'; interface IProps { record: EmailType, setRecord: (d: EmailType) => void } @@ -35,14 +37,26 @@ const EmailForm = (props: IProps) => { const emails = useAppSelector(EmailTypeSlice.Data); const status = useAppSelector(EmailTypeSlice.Status); - const categoryStatus = useAppSelector(EmailCategorySlice.Status); - const categories = useAppSelector(EmailCategorySlice.Data); + const [categoryStatus, setCategoryStatus] = React.useState('uninitiated'); + const [categories, setCategories] = React.useState([]); + const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []) React.useEffect(() => { - if (categoryStatus == 'uninitiated' || categoryStatus == 'changed') - dispatch(EmailCategorySlice.Fetch()); - }, [categoryStatus]); + setCategoryStatus('loading') + const h = emailCategoryController.Fetch(); + h.done((d) => { + setCategories(d) + setCategoryStatus('idle') + }); + h.fail(() => setCategoryStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [emailCategoryController.Fetch]); React.useEffect(() => { diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportForm.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportForm.tsx index acdcec636..57f4abcb7 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportForm.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportForm.tsx @@ -23,10 +23,12 @@ import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; -import { ScheduledEmailType } from '../global'; -import { EmailCategorySlice, ScheduledEmailTypeSlice } from '../Store'; +import { ScheduledEmailType, EmailCategory } from '../global'; +import { ScheduledEmailTypeSlice } from '../Store'; import { CheckBox, Input, Select } from '@gpa-gemstone/react-forms'; -import { IsCron } from '@gpa-gemstone/helper-functions' +import { IsCron } from '@gpa-gemstone/helper-functions'; +import { Application } from '@gpa-gemstone/application-typings'; +import { GenericController } from '@gpa-gemstone/react-interactive'; interface IProps { record: ScheduledEmailType, setRecord: (d: ScheduledEmailType) => void } @@ -35,14 +37,26 @@ const ReportForm = (props: IProps) => { const emails = useAppSelector(ScheduledEmailTypeSlice.Data); const status = useAppSelector(ScheduledEmailTypeSlice.Status); - const categoryStatus = useAppSelector(EmailCategorySlice.Status); - const categories = useAppSelector(EmailCategorySlice.Data); + const [categoryStatus, setCategoryStatus] = React.useState('uninitiated'); + const [categories, setCategories] = React.useState([]); + const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []) React.useEffect(() => { - if (categoryStatus == 'uninitiated' || categoryStatus == 'changed') - dispatch(EmailCategorySlice.Fetch()); - }, [categoryStatus]); + setCategoryStatus('loading') + const h = emailCategoryController.Fetch(); + h.done((d) => { + setCategories(d) + setCategoryStatus('idle') + }); + h.fail(() => setCategoryStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [emailCategoryController.Fetch]); React.useEffect(() => { diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/Store.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/Store.tsx index 5a633a1d7..f5e2072f4 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/Store.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/Store.tsx @@ -23,10 +23,10 @@ import { configureStore } from '@reduxjs/toolkit'; import { - ActiveSubscription, EmailCategory, EmailType, + ActiveSubscription, EmailType, IDataSourceTriggeredEmailType, ITriggeredDataSource, ITriggeredEmailDataSourceSetting, SubscribeEmails, - ICellCarrier, ScheduledEmailType, ActiveReportSubscription, + ScheduledEmailType, ActiveReportSubscription, IScheduledDataSource, IScheduledEmailDataSourceSetting, IDataSourceScheduledEmailType, SubscribeScheduledEmails } from './global'; @@ -40,7 +40,6 @@ declare var homePath: string; export type AppDispatch = typeof store.dispatch; export type RootState = ReturnType -export const EmailCategorySlice = new GenericSlice("EmailCategory", `${homePath}api/OpenXDA/EmailCategory`, "Name", true); export const EmailTypeSlice = new GenericSlice("EmailType", `${homePath}api/OpenXDA/EmailType`, "Name", true); export const ScheduledEmailTypeSlice = new GenericSlice("ScheduledEmailType", `${homePath}api/OpenXDA/ScheduledEmailType`, "Name", true); export const AssetGroupSlice = new GenericSlice("AssetGroup", `${homePath}api/OpenXDA/AssetGroup`, "Name", true); @@ -68,7 +67,6 @@ export const ScheduledEmailDataSourceSlice = new GenericSlice("ScheduledDataSourceSetting", `${homePath}api/OpenXDA/ScheduledEmailDataSourceSetting`, "Name", false); const reducer = { - EmailCategory: EmailCategorySlice.Reducer, EmailType: EmailTypeSlice.Reducer, AssetGroup: AssetGroupSlice.Reducer, Setting: SettingSlice.Reducer, From 4cb451aef5da0ffd03e89a0546554c0d4995ee32 Mon Sep 17 00:00:00 2001 From: natalie beatty Date: Mon, 13 Jul 2026 16:22:19 -0400 Subject: [PATCH 05/35] remove scheduledEmailType slice --- .../Scripts/TSX/Report/GeneralInfo.tsx | 30 +++++++-- .../Scripts/TSX/Report/ReportForm.tsx | 27 +++++--- .../Scripts/TSX/Report/ReportPage.tsx | 61 ++++++++++++------- .../Scripts/TSX/Report/Template.tsx | 8 +-- .../Scripts/TSX/Report/TriggerWindow.tsx | 6 +- .../Scripts/TSX/Store.tsx | 4 +- .../TSX/Subscriptions/Report/ReportSelect.tsx | 37 +++++++---- .../TSX/Subscriptions/Report/Success.tsx | 31 +++++++++- 8 files changed, 144 insertions(+), 60 deletions(-) diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/GeneralInfo.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/GeneralInfo.tsx index 529d6f7b3..5b68b50c2 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/GeneralInfo.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/GeneralInfo.tsx @@ -21,14 +21,14 @@ // //****************************************************************************************************** -import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; import { ToolTip } from '@gpa-gemstone/react-forms'; import { ReactIcons } from '@gpa-gemstone/gpa-symbols'; import { ScheduledEmailType } from '../global'; -import { ScheduledEmailTypeSlice } from '../Store'; import { IsCron } from '@gpa-gemstone/helper-functions'; import ReportForm from './ReportForm'; +import { GenericController } from '@gpa-gemstone/react-interactive'; +import { Application } from '@gpa-gemstone/application-typings'; declare var homePath; declare var version; @@ -37,21 +37,39 @@ interface IProps { Record: ScheduledEmailType } const GeneralInfo = (props: IProps) => { - const dispatch = useAppDispatch(); const [email, setEmail] = React.useState(props.Record); const [hasChanged, setHasChanged] = React.useState(false); const [hover, setHover] = React.useState<('submit' | 'clear' | 'none')>('none'); - const allEmails = useAppSelector(ScheduledEmailTypeSlice.Data); + const [scheduledEmails, setScheduledEmails] = React.useState([]); + const [scheduledEmailStatus, setScheduledEmailStatus] = React.useState('uninitiated'); const [errors, setErrors] = React.useState([]); + const scheduledEmailTypeController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/ScheduledEmailType`, "Name", true), []) + + React.useEffect(() => { + setScheduledEmailStatus('loading') + const h = scheduledEmailTypeController.Fetch(); + h.done((d) => { + setScheduledEmails(d) + setScheduledEmailStatus('idle') + }); + h.fail(() => setScheduledEmailStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [scheduledEmailTypeController.Fetch]); + React.useEffect(() => { let e = []; if (email.Name == undefined || email.Name.length < 1) e.push('A Name is required'); - if (allEmails.findIndex(s => s.Name === email.Name && s.ID !== email.ID) >= 0) + if (scheduledEmails.findIndex(s => s.Name === email.Name && s.ID !== email.ID) >= 0) e.push('An Email with this Name already exists'); if (email.EmailCategoryID < 0) e.push('A Category must be selected.'); @@ -98,7 +116,7 @@ const GeneralInfo = (props: IProps) => { diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportForm.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportForm.tsx index 57f4abcb7..2e858bf3a 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportForm.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportForm.tsx @@ -24,7 +24,6 @@ import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; import { ScheduledEmailType, EmailCategory } from '../global'; -import { ScheduledEmailTypeSlice } from '../Store'; import { CheckBox, Input, Select } from '@gpa-gemstone/react-forms'; import { IsCron } from '@gpa-gemstone/helper-functions'; import { Application } from '@gpa-gemstone/application-typings'; @@ -33,13 +32,13 @@ import { GenericController } from '@gpa-gemstone/react-interactive'; interface IProps { record: ScheduledEmailType, setRecord: (d: ScheduledEmailType) => void } const ReportForm = (props: IProps) => { - const dispatch = useAppDispatch(); - const emails = useAppSelector(ScheduledEmailTypeSlice.Data); - const status = useAppSelector(ScheduledEmailTypeSlice.Status); + const [scheduledEmails, setScheduledEmails] = React.useState([]); + const [scheduledEmailStatus, setScheduledEmailStatus] = React.useState('uninitiated'); const [categoryStatus, setCategoryStatus] = React.useState('uninitiated'); const [categories, setCategories] = React.useState([]); + const scheduledEmailTypeController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/ScheduledEmailType`, "Name", true), []) const emailCategoryController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/EmailCategory`, "Name", true), []) React.useEffect(() => { @@ -58,15 +57,25 @@ const ReportForm = (props: IProps) => { }, [emailCategoryController.Fetch]); - React.useEffect(() => { - if (status == 'uninitiated' || status == 'changed') - dispatch(ScheduledEmailTypeSlice.Fetch()); - }, [status]); + setScheduledEmailStatus('loading') + const h = scheduledEmailTypeController.Fetch(); + h.done((d) => { + setScheduledEmails(d) + setScheduledEmailStatus('idle') + }); + h.fail(() => setScheduledEmailStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [scheduledEmailTypeController.Fetch]); function Valid(field: keyof ScheduledEmailType) { if (field == 'Name') - return props.record.Name != null && props.record.Name.length != 0 && emails.findIndex(e => e.Name == props.record.Name && props.record.ID != e.ID) == -1; + return props.record.Name != null && props.record.Name.length != 0 && scheduledEmails.findIndex(e => e.Name == props.record.Name && props.record.ID != e.ID) == -1; if (field == 'Schedule') return props.record.Schedule != null && IsCron(props.record.Schedule); diff --git a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportPage.tsx b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportPage.tsx index 1c0b563b9..aea1ce210 100644 --- a/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportPage.tsx +++ b/Source/Applications/SystemCenterNotification/Scripts/TSX/Report/ReportPage.tsx @@ -21,11 +21,11 @@ // //****************************************************************************************************** -import { useAppDispatch, useAppSelector } from '../hooks'; import * as React from 'react'; -import { TabSelector, Warning, LoadingScreen, ServerErrorIcon, Modal } from '@gpa-gemstone/react-interactive' +import * as $ from 'jquery' +import { TabSelector, Warning, LoadingScreen, ServerErrorIcon, GenericController } from '@gpa-gemstone/react-interactive'; +import { ScheduledEmailType } from '../global'; import { Application } from '@gpa-gemstone/application-typings'; -import { ScheduledEmailTypeSlice } from '../Store'; import GeneralInfo from './GeneralInfo'; import Subscriptions from './Subscriptions'; import TriggerWindow from './TriggerWindow'; @@ -49,13 +49,14 @@ const Tabs = [ const EmailPage = (props: IProps) => { - const dispatch = useAppDispatch(); const [showDelete, setShowDelete] = React.useState(false); const [showTest, setShowTest] = React.useState(false); - const email = useAppSelector((state) => ScheduledEmailTypeSlice.Datum(state, parseInt(props.useParams.id))); - const status: Application.Types.Status = useAppSelector(ScheduledEmailTypeSlice.Status); + const [scheduledEmail, setScheduledEmail] = React.useState(null); + const [scheduledEmailStatus, setScheduledEmailStatus] = React.useState('uninitiated'); + + const scheduledEmailTypeController = React.useMemo(() => new GenericController(`${homePath}api/OpenXDA/ScheduledEmailType`, "Name", true), []) const getTab = React.useCallback(() => { if (sessionStorage.hasOwnProperty('ReportPage.Tab')) @@ -66,9 +67,27 @@ const EmailPage = (props: IProps) => { const [tab, setTab] = React.useState(getTab()); React.useEffect(() => { - if (status == 'uninitiated' || status == 'changed') - dispatch(ScheduledEmailTypeSlice.Fetch()); - }, [status]); + setScheduledEmailStatus('loading') + const h = $.ajax({ + type: "GET", + url: `${homePath}api/OpenXDA/ScheduledEmailType/One/${props.useParams.id}`, + contentType: "application/json; charset=utf-8", + dataType: 'json', + cache: false, + async: true + }) + h.done((d) => { + setScheduledEmail(d) + setScheduledEmailStatus('idle') + }); + h.fail(() => setScheduledEmailStatus('error')); + + return function cleanup() { + if (h != null && h.abort != null) + h.abort(); + } + + }, [props.useParams.id]) React.useEffect(() => { const saved = getTab(); @@ -79,12 +98,12 @@ const EmailPage = (props: IProps) => { return (
- - - {!email ? <> : <> + + + {!scheduledEmail ? <> : <>
-

{email != null ? email.Name : ''}

+

{scheduledEmail != null ? scheduledEmail.Name : ''}

@@ -99,37 +118,37 @@ const EmailPage = (props: IProps) => {
{tab == "settings" ?
- +
: <>} {tab == "template" ?
-