diff --git a/src/components/Routes/Routes.test.tsx b/src/components/Routes/Routes.test.tsx
index c10c7e81..7f29bc25 100644
--- a/src/components/Routes/Routes.test.tsx
+++ b/src/components/Routes/Routes.test.tsx
@@ -16,14 +16,9 @@ jest.mock('react-router-dom', () => ({
useParams: jest.fn(),
}))
-jest.mock('pages/JobIndex/jobIndexHelpers', () => ({
- getFormattedTable: jest.fn(),
-}))
-
describe('Routes', () => {
afterAll(() => {
jest.unmock('react-router-dom')
- jest.unmock('pages/JobIndex/jobIndexHelpers')
jest.clearAllMocks()
})
diff --git a/src/components/SyncUserModal.test.tsx b/src/components/SyncUserModal.test.tsx
index 6b8b7640..4c2bdf34 100644
--- a/src/components/SyncUserModal.test.tsx
+++ b/src/components/SyncUserModal.test.tsx
@@ -53,7 +53,7 @@ describe('SyncUser Modal', () => {
)
await waitFor(() => {
expect(
- screen.getByText('ERROR: Error: Request failed with status code 404'),
+ screen.getByText('ERROR: Failure to return gardens'),
).toBeInTheDocument()
})
mockAxios.onGet('/api/v1/gardens').reply(200, [TGarden])
@@ -71,7 +71,7 @@ describe('SyncUser Modal', () => {
fireEvent.click(screen.getByRole('button', { name: 'Submit' }))
await waitFor(() => {
expect(
- screen.getByText('ERROR: Error: Request failed with status code 404'),
+ screen.getByText('ERROR: Failure to sync users'),
).toBeInTheDocument()
})
})
diff --git a/src/components/SyncUserModal.tsx b/src/components/SyncUserModal.tsx
index 3b90ef5d..4ce535bc 100644
--- a/src/components/SyncUserModal.tsx
+++ b/src/components/SyncUserModal.tsx
@@ -115,7 +115,7 @@ const SyncUserModal = ({ open, setOpen }: ModalProps) => {
.catch((e) => {
setAlert({
severity: 'error',
- message: e,
+ message: e.response.data.message || e,
doNotAutoDismiss: true,
})
})
@@ -146,7 +146,7 @@ const SyncUserModal = ({ open, setOpen }: ModalProps) => {
.catch((e) => {
setAlert({
severity: 'error',
- message: e,
+ message: e.response.data.message || e,
doNotAutoDismiss: true,
})
})
diff --git a/src/components/table.tsx b/src/components/table.tsx
deleted file mode 100644
index 25e32eda..00000000
--- a/src/components/table.tsx
+++ /dev/null
@@ -1,393 +0,0 @@
-import {
- FirstPage as FirstPageIcon,
- KeyboardArrowLeft,
- KeyboardArrowRight,
- LastPage as LastPageIcon,
-} from '@mui/icons-material'
-import {
- Box,
- CircularProgress,
- IconButton,
- Table,
- TableBody,
- TableCell,
- TableContainer,
- TableFooter,
- TableHead,
- TablePagination,
- TableRow,
- TextField,
- Typography,
-} from '@mui/material'
-import { useTheme } from '@mui/material/styles'
-import { AxiosResponse } from 'axios'
-import PropTypes from 'prop-types'
-import { BaseSyntheticEvent, useState } from 'react'
-import CacheService from 'services/cache_service'
-import { TableInterface } from 'types/custom-types'
-
-const tableCellStyle = {
- borderWidth: 0.5,
- borderColor: 'lightgrey',
- borderStyle: 'solid',
-}
-
-function TablePaginationActions(props: {
- count: number
- page: number
- rowsPerPage: number
- onPageChange(event: BaseSyntheticEvent | null, value: number): void
-}) {
- const theme = useTheme()
- const { count, page, rowsPerPage, onPageChange } = props
-
- const handleFirstPageButtonClick = (event: BaseSyntheticEvent) => {
- onPageChange(event, 0)
- }
-
- const handleBackButtonClick = (event: BaseSyntheticEvent) => {
- onPageChange(event, page - 1)
- }
-
- const handleNextButtonClick = (event: BaseSyntheticEvent) => {
- onPageChange(event, page + 1)
- }
-
- const handleLastPageButtonClick = (event: BaseSyntheticEvent) => {
- onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1))
- }
-
- return (
-
-
- {theme.direction === 'rtl' ? : }
-
-
- {theme.direction === 'rtl' ? (
-
- ) : (
-
- )}
-
- = Math.ceil(count / rowsPerPage) - 1}
- aria-label="next page"
- >
- {theme.direction === 'rtl' ? (
-
- ) : (
-
- )}
-
- = Math.ceil(count / rowsPerPage) - 1}
- aria-label="last page"
- >
- {theme.direction === 'rtl' ? : }
-
-
- )
-}
-
-TablePaginationActions.propTypes = {
- count: PropTypes.number.isRequired,
- onPageChange: PropTypes.func.isRequired,
- page: PropTypes.number.isRequired,
- rowsPerPage: PropTypes.number.isRequired,
-}
-
-const MyTable = ({ parentState }: TableInterface) => {
- let cachedState: { rowsPerPage: number } = { rowsPerPage: 5 }
-
- if (parentState.cacheKey) {
- const newCachedState = CacheService.getIndexLastState(parentState.cacheKey)
-
- if (
- 'rowsPerPage' in newCachedState &&
- typeof newCachedState['rowsPerPage'] === 'string'
- ) {
- newCachedState['rowsPerPage'] = parseInt(newCachedState['rowsPerPage'])
- }
- cachedState = newCachedState
- }
-
- const [data, setData] = useState<
- (string | JSX.Element | number | null | undefined)[][]
- >([])
- const [completeDataSet, setCompleteDataSet] = useState(
- parentState.completeDataSet,
- )
- const [isLoading, setLoading] = useState(true)
- const [page, setPage] = useState(0)
- const [rowsPerPage, setRowsPerPage] = useState(
- cachedState.rowsPerPage,
- )
- const [totalItemsFiltered, setTotalItemsFiltered] = useState('0')
- const [totalItems, setTotalItems] = useState('0')
- const [includeChildren, setIncludeChildren] = useState(
- parentState.includeChildren,
- )
-
- function handleChangePage(event: BaseSyntheticEvent | null, newPage: number) {
- if (parentState.setSearchApi) {
- parentState.setSearchApi('' + newPage * rowsPerPage, 'start')
- }
- setPage(newPage)
- setLoading(true)
- }
-
- const onChange = (event: BaseSyntheticEvent) => {
- if (parentState.setSearchApi) {
- parentState.setSearchApi(event.target.value, event.target.id)
- }
- setPage(0)
- setLoading(true)
- }
-
- const onChangeEnd = (event: BaseSyntheticEvent) => {
- if (parentState.setSearchApi) {
- parentState.setSearchApi(event.target.value, event.target.id, true)
- }
- setPage(0)
- setLoading(true)
- }
-
- const handleChangeRowsPerPage = (event: BaseSyntheticEvent) => {
- setRowsPerPage(parseInt(event.target.value, 10))
- setPage(0)
- if (parentState.setSearchApi) {
- parentState.setSearchApi('0', 'start')
- }
- setLoading(true)
- if (parentState.cacheKey) {
- CacheService.setItemInCache(
- {
- rowsPerPage: event.target.value,
- },
- parentState.cacheKey,
- )
- }
- }
-
- function formatTextField(index: number) {
- if (!parentState.disableSearch) {
- if (parentState.tableHeads[index] === '') {
- return
- } else if (['Created'].includes(parentState.tableHeads[index])) {
- return (
-
-
-
-
-
-
-
-
- )
- } else {
- return (
-
- )
- }
- }
- }
-
- function pageNav() {
- if (parentState.includePageNav) {
- let count: string = totalItemsFiltered
- if (totalItemsFiltered === '0' || !totalItemsFiltered) {
- count = totalItems
- }
- // Can't use getRowPageOptions here as can't call useEffect
- return (
-
- )
- }
- }
-
- function getTableHeader() {
- if (parentState.tableHeads) {
- return (
-
-
- {parentState.tableHeads.map((tableHead: string, index: number) => (
-
- {tableHead}
-
- {formatTextField(index)}
-
- ))}
-
-
- )
- }
- }
-
- function updateData() {
- if (!isLoading) {
- setLoading(true)
- }
- if (parentState.apiDataCall) {
- if (parentState.setSearchApi) {
- parentState.setSearchApi('' + rowsPerPage, 'length')
- }
-
- parentState.apiDataCall(page, rowsPerPage, successCallback)
- setLoading(false)
- } else {
- if (parentState.completeDataSet && parentState.formatData) {
- setLoading(false)
- setData(
- parentState.formatData(
- parentState.completeDataSet.slice(
- page * rowsPerPage,
- page * rowsPerPage + rowsPerPage,
- ),
- ),
- )
- setTotalItems('' + parentState.completeDataSet.length)
- } else if (parentState.formatData) {
- setLoading(false)
- setData(parentState.formatData())
- }
- }
- }
-
- function successCallback(response: AxiosResponse) {
- setLoading(false)
- if (parentState.formatData) {
- setData(parentState.formatData(response.data))
- }
- setTotalItems(response.headers.recordstotal)
- setTotalItemsFiltered(response.headers.recordsfiltered)
- }
-
- if (
- isLoading ||
- parentState.includeChildren !== includeChildren ||
- parentState.completeDataSet !== completeDataSet
- ) {
- if (parentState.includeChildren !== includeChildren) {
- setIncludeChildren(parentState.includeChildren)
- setPage(0)
- }
- if (parentState.completeDataSet) {
- setCompleteDataSet(parentState.completeDataSet)
- }
- updateData()
- }
-
- function getCircularProgress() {
- if (isLoading) {
- return
- }
- }
-
- return (
-
-
-
- {getTableHeader()}
-
- {data.map((items, index: number) => (
-
- {items.map((item, itemIndex: number) => (
-
- {typeof item === 'string' || typeof item === 'number' ? (
- {item}
- ) : (
- item
- )}
-
- ))}
-
- ))}
-
-
-
-
- {getCircularProgress()}
- {pageNav()}
-
-
- )
-}
-export default MyTable
diff --git a/src/hooks/useJobs.tsx b/src/hooks/useJobs.tsx
index 3ba0e807..cd71dbc5 100644
--- a/src/hooks/useJobs.tsx
+++ b/src/hooks/useJobs.tsx
@@ -1,4 +1,4 @@
-import { AxiosRequestConfig } from 'axios'
+import { AxiosPromise, AxiosRequestConfig } from 'axios'
import useAxios from 'axios-hooks'
import { ServerConfigContainer } from 'containers/ConfigContainer'
import { useMyAxios } from 'hooks/useMyAxios'
@@ -11,8 +11,8 @@ const useJobs = () => {
const { axiosManualOptions } = useMyAxios()
const [, execute] = useAxios({}, axiosManualOptions)
- const getJobs = () => {
- const config: AxiosRequestConfig = {
+ const getJobs = (): AxiosPromise => {
+ const config: AxiosRequestConfig = {
url: JOBS_URL,
method: 'get',
withCredentials: authEnabled,
@@ -20,8 +20,8 @@ const useJobs = () => {
return execute(config)
}
- const getJob = (id: string) => {
- const config: AxiosRequestConfig = {
+ const getJob = (id: string): AxiosPromise => {
+ const config: AxiosRequestConfig = {
url: `${JOBS_URL}/${id}`,
method: 'get',
withCredentials: authEnabled,
diff --git a/src/pages/JobIndex/JobIndex.test.tsx b/src/pages/JobIndex/JobIndex.test.tsx
index eeaca683..c84759c4 100644
--- a/src/pages/JobIndex/JobIndex.test.tsx
+++ b/src/pages/JobIndex/JobIndex.test.tsx
@@ -1,19 +1,60 @@
import { render, screen, waitFor } from '@testing-library/react'
import { mockAxios, regexUsers } from 'test/axios-mock'
-import { TServerAuthConfig } from 'test/test-values'
-import { LoggedInProviders } from 'test/testMocks'
+import { TJob, TServerAuthConfig } from 'test/test-values'
+import { AllProviders, LoggedInProviders } from 'test/testMocks'
import { TAdmin, TUser } from 'test/user-test-values'
import { JobIndex } from './JobIndex'
-jest.mock('pages/JobIndex/jobIndexHelpers', () => ({
- getFormattedTable: jest.fn(),
-}))
-
describe('JobIndex', () => {
- afterAll(() => {
- jest.unmock('pages/JobIndex/jobIndexHelpers')
- jest.clearAllMocks()
+ test('displays table with job data', async () => {
+ render(
+
+
+ ,
+ )
+ await waitFor(() => {
+ expect(
+ screen.getByRole('heading', { name: 'Request Scheduler' }),
+ ).toBeInTheDocument()
+ })
+ expect(screen.getByText(TJob.name)).toBeInTheDocument()
+ expect(screen.getByText(TJob.request_template.system)).toBeInTheDocument()
+ expect(screen.getByText(TJob.request_template.command)).toBeInTheDocument()
+ expect(screen.getByText(TJob.success_count as number)).toBeInTheDocument()
+ })
+
+ test('name and system are links', async () => {
+ render(
+
+
+ ,
+ )
+ await waitFor(() => {
+ expect(screen.getByText(TJob.name)).toBeInTheDocument()
+ })
+ const links: HTMLAnchorElement[] = screen.getAllByRole('link')
+ expect(links[0].textContent).toEqual(TJob.name)
+ expect(links[0].href).toContain(`http://localhost/#/jobs/${TJob.id}`)
+ expect(links[1].textContent).toEqual(TJob.request_template.system)
+ expect(links[1].href).toContain(
+ `http://localhost/#/jobs/${TJob.request_template.namespace}/${TJob.request_template.system}`,
+ )
+ })
+
+ test('alerts on failure to get jobs', async () => {
+ mockAxios
+ .onGet('/api/v1/jobs')
+ .reply(404, { message: 'Failure to get jobs' })
+ render(
+
+
+ ,
+ )
+ await waitFor(() => {
+ expect(screen.getByText('ERROR: Failure to get jobs')).toBeInTheDocument()
+ })
+ expect(screen.queryByText(TJob.name)).not.toBeInTheDocument()
})
test('create button if permission', async () => {
diff --git a/src/pages/JobIndex/JobIndex.tsx b/src/pages/JobIndex/JobIndex.tsx
index d7656375..e1dd5a5a 100644
--- a/src/pages/JobIndex/JobIndex.tsx
+++ b/src/pages/JobIndex/JobIndex.tsx
@@ -1,45 +1,83 @@
-import { Box, Button } from '@mui/material'
-import useAxios from 'axios-hooks'
+import { Button } from '@mui/material'
import { Divider } from 'components/Divider'
import { PageHeader } from 'components/PageHeader'
-import { ServerConfigContainer } from 'containers/ConfigContainer'
+import { Snackbar } from 'components/Snackbar'
+import { Table } from 'components/Table'
import { PermissionsContainer } from 'containers/PermissionsContainer'
-import { getFormattedTable } from 'pages/JobIndex/jobIndexHelpers'
-import { useEffect, useState } from 'react'
-import { useNavigate } from 'react-router-dom'
+import { useJobs } from 'hooks/useJobs'
+import { JobTableData, useJobColumns } from 'pages/JobIndex'
+import { useEffect, useMemo, useState } from 'react'
+import { Link, useNavigate } from 'react-router-dom'
import { Job } from 'types/backend-types'
+import { SnackbarState } from 'types/custom-types'
+import { dateFormatted } from 'utils/date-formatter'
const JobIndex = () => {
- const { authEnabled } = ServerConfigContainer.useContainer()
const { hasPermission } = PermissionsContainer.useContainer()
const [jobs, setJobs] = useState([])
- const [{ data, error }] = useAxios({
- url: '/api/v1/jobs',
- method: 'get',
- withCredentials: authEnabled,
- })
+ const [alert, setAlert] = useState(undefined)
+ const { getJobs } = useJobs()
const navigate = useNavigate()
useEffect(() => {
- if (data && !error) {
- setJobs(data)
- }
- }, [data, error])
+ getJobs()
+ .then((response) => {
+ setJobs(response.data)
+ })
+ .catch((e) => {
+ setAlert({
+ severity: 'error',
+ message: e.response.data.message || e,
+ doNotAutoDismiss: true,
+ })
+ })
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [])
// temporary for demo
const createRequestOnClick = () => {
navigate('/jobs/create')
}
+ const jobData = useMemo((): JobTableData[] => {
+ return jobs.map((job: Job): JobTableData => {
+ return {
+ name: (
+
+ {job.name}
+
+ ),
+ status: job.status || '',
+ system: (
+
+ {job.request_template.system}
+
+ ),
+ instance: job.request_template.instance_name,
+ command: job.request_template.command,
+ nextRun: job.next_run_time
+ ? dateFormatted(new Date(job.next_run_time))
+ : '',
+ success: job.success_count || 0,
+ error: job.error_count || 0,
+ }
+ })
+ }, [jobs])
+
return (
-
+ <>
- {hasPermission('job:create') && (
-
- )}
- {getFormattedTable(jobs)}
-
+
+ {hasPermission('job:create') && (
+
+ )}
+
+ {alert && }
+ >
)
}
diff --git a/src/pages/JobIndex/index.ts b/src/pages/JobIndex/index.ts
index bedc98d3..557fb520 100644
--- a/src/pages/JobIndex/index.ts
+++ b/src/pages/JobIndex/index.ts
@@ -1 +1,2 @@
export { JobIndex as default } from './JobIndex'
+export * from './jobIndexHelpers'
diff --git a/src/pages/JobIndex/jobIndexHelpers.tsx b/src/pages/JobIndex/jobIndexHelpers.tsx
index 0323a9a4..79089e9f 100644
--- a/src/pages/JobIndex/jobIndexHelpers.tsx
+++ b/src/pages/JobIndex/jobIndexHelpers.tsx
@@ -1,68 +1,85 @@
-import RequestTable from 'components/table'
-import { Link as RouterLink } from 'react-router-dom'
-import { Job } from 'types/backend-types'
+import { DefaultCellRenderer } from 'components/Table/defaults'
+import { useMemo } from 'react'
+import { Column } from 'react-table'
+import { ObjectWithStringKeys } from 'types/custom-types'
-const tableHeads = [
- 'Job Name',
- 'Status',
- 'System',
- 'Instance',
- 'Command',
- 'Next Run Time',
- 'Success Count',
- 'Error Count',
-]
-const formatJobs = (jobs: Job[]) => {
- const formattedJobs: (string | JSX.Element | number | null | undefined)[][] =
- []
-
- for (const job of jobs) {
- const {
- name,
- id,
- status,
- request_template: {
- system,
- namespace,
- instance_name: instanceName,
- command,
- },
- next_run_time: nextRunTime,
- success_count: successes,
- error_count: errors,
- } = job
-
- const formattedJob = [
-
- {name}
- ,
- status as string,
- ,
- instanceName,
- command,
- new Date(nextRunTime as number).toString(),
- successes || 0,
- errors || 0,
- ]
-
- formattedJobs.push(formattedJob)
- }
- return formattedJobs
+export interface JobTableData extends ObjectWithStringKeys {
+ name: JSX.Element
+ status: string
+ system: JSX.Element
+ instance: string
+ command: string
+ nextRun: string
+ success: number
+ error: number
}
-const getFormattedTable = (jobs: Job[]) => {
- return (
-
+export const useJobColumns = () => {
+ return useMemo[]>(
+ () => [
+ {
+ Header: 'Name',
+ Cell: DefaultCellRenderer,
+ accessor: 'name',
+ filter: 'fuzzyText',
+ minWidth: 120,
+ maxWidth: 180,
+ width: 130,
+ },
+ {
+ Header: 'Status',
+ accessor: 'status',
+ minWidth: 120,
+ maxWidth: 180,
+ width: 130,
+ },
+ {
+ Header: 'System',
+ Cell: DefaultCellRenderer,
+ accessor: 'system',
+ filter: 'fuzzyText',
+ minWidth: 120,
+ maxWidth: 180,
+ width: 130,
+ },
+ {
+ Header: 'Instance',
+ accessor: 'instance',
+ filter: 'fuzzyText',
+ minWidth: 120,
+ maxWidth: 180,
+ width: 130,
+ },
+ {
+ Header: 'Command',
+ accessor: 'command',
+ filter: 'fuzzyText',
+ minWidth: 130,
+ maxWidth: 180,
+ width: 140,
+ },
+ {
+ Header: 'Next Run Time',
+ accessor: 'nextRun',
+ minWidth: 200,
+ maxWidth: 300,
+ width: 250,
+ },
+ {
+ Header: 'Success Count',
+ accessor: 'success',
+ minWidth: 120,
+ maxWidth: 180,
+ width: 145,
+ },
+ {
+ Header: 'Error Count',
+ accessor: 'error',
+ minWidth: 120,
+ maxWidth: 180,
+ width: 130,
+ },
+ ],
+ [],
)
}
-
-export { formatJobs, getFormattedTable }
diff --git a/src/pages/JobView/JobView.tsx b/src/pages/JobView/JobView.tsx
index 7fed5999..8dc3cdff 100644
--- a/src/pages/JobView/JobView.tsx
+++ b/src/pages/JobView/JobView.tsx
@@ -6,7 +6,7 @@ import {
Stack,
Typography,
} from '@mui/material'
-import { AxiosResponse } from 'axios'
+import { AxiosError, AxiosResponse } from 'axios'
import { Divider } from 'components/Divider'
import { useJobRequestCreation } from 'components/JobRequestCreation'
import { JsonCard } from 'components/JsonCard'
@@ -77,10 +77,10 @@ const JobView = () => {
)
}
- const errorHandler = (e: string) => {
+ const errorHandler = (e: AxiosError) => {
setAlert({
severity: 'error',
- message: e,
+ message: e.response?.data.message,
doNotAutoDismiss: true,
})
}
diff --git a/src/pages/RequestView/RequestViewTable.tsx b/src/pages/RequestView/RequestViewTable.tsx
index 578aaf57..249e9699 100644
--- a/src/pages/RequestView/RequestViewTable.tsx
+++ b/src/pages/RequestView/RequestViewTable.tsx
@@ -13,8 +13,7 @@ import {
} from 'pages/RequestsIndex/data'
import { useState } from 'react'
import { Request } from 'types/backend-types'
-
-import {dateFormatted} from './requestViewHelpers'
+import { dateFormatted } from 'utils/date-formatter'
interface RequestViewTableProps {
request: Request
diff --git a/src/pages/RequestView/requestViewHelpers.tsx b/src/pages/RequestView/requestViewHelpers.tsx
index 2d386ee6..fe96d97d 100644
--- a/src/pages/RequestView/requestViewHelpers.tsx
+++ b/src/pages/RequestView/requestViewHelpers.tsx
@@ -1,24 +1,10 @@
import NavigateNextIcon from '@mui/icons-material/NavigateNext'
import { Breadcrumbs, CircularProgress } from '@mui/material'
import { SupportedColorScheme } from '@mui/material/styles'
-import { DateTimeFormatOptions } from 'luxon'
import ReactJson from 'react-json-view'
import { Link as RouterLink } from 'react-router-dom'
import { Request } from 'types/backend-types'
-const dateFormatted = (date: Date) => {
- const options: DateTimeFormatOptions = {
- year: 'numeric',
- month: 'short',
- day: 'numeric',
- hour: 'numeric',
- second: 'numeric',
- minute: 'numeric',
- hour12: false
- }
- return date.toLocaleString(undefined, options)
-}
-
const outputFormatted = (
request: Request,
theme: SupportedColorScheme,
@@ -80,4 +66,4 @@ const getParentLinks = (request: Request): JSX.Element => {
)
}
-export { dateFormatted,getParentLinks, outputFormatted }
+export { getParentLinks, outputFormatted }
diff --git a/src/services/cache_service.ts b/src/services/cache_service.ts
deleted file mode 100644
index 0e459242..00000000
--- a/src/services/cache_service.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { Request } from 'types/backend-types'
-
-type CachedStates = {
- rowsPerPage?: number
- request?: Request
- requestQueue?: Request[]
- namespacesSelected?: string[]
-}
-
-function getItem(key: string): CachedStates {
- const lastKnownState: string | null = window.localStorage.getItem(key)
- let parsedState: CachedStates = {}
- if (lastKnownState) {
- parsedState = JSON.parse(lastKnownState)
- }
- return parsedState
-}
-
-const CacheService = {
- getIndexLastState(key: string): { rowsPerPage: number } {
- const item = getItem(key)
- return { rowsPerPage: item.rowsPerPage || 5 }
- },
-
- getNamespacesSelected(
- key: string,
- defaultValue: string[] = [],
- ): { namespacesSelected: string[] } {
- const item = getItem(key)
- return {
- namespacesSelected: item.namespacesSelected || defaultValue,
- }
- },
-
- popQueue(key: string): Request | undefined | void {
- const requestQueue = getItem(key).requestQueue
- if (requestQueue) {
- const request = requestQueue.pop()
- this.setItemInCache({ requestQueue: requestQueue }, key)
- return request
- }
- },
-
- pushQueue(item: Request, key: string): void {
- const requestQueue: Request[] = getItem(key).requestQueue || []
- if (requestQueue) {
- requestQueue.push(item)
- this.setItemInCache({ requestQueue: requestQueue }, key)
- }
- },
-
- setItemInCache(item: unknown, key: string): void {
- window.localStorage.setItem(key, JSON.stringify(item))
- },
-}
-
-export default CacheService
diff --git a/src/test/test-values.ts b/src/test/test-values.ts
index c3e9d716..ccfdb82a 100644
--- a/src/test/test-values.ts
+++ b/src/test/test-values.ts
@@ -112,6 +112,8 @@ export const TJob: Job = {
request_template: {
namespace: TSystem.namespace,
system: TSystem.name,
+ command: TCommand.name,
+ instance_name: TInstance.name,
system_version: TSystem.version,
} as RequestTemplate,
status: 'RUNNING',
diff --git a/src/test/testMocks.tsx b/src/test/testMocks.tsx
index 4d23d270..a69d7de4 100644
--- a/src/test/testMocks.tsx
+++ b/src/test/testMocks.tsx
@@ -49,17 +49,19 @@ export const AllProviders = ({ children }: ProviderMocks) => {
export const MemoryProvider = ({ children, startLocation }: ProviderMocks) => {
return (
-
-
-
-
-
- LOADING...>}>{children}
-
-
-
-
-
+
+
+
+
+
+
+ LOADING...>}>{children}
+
+
+
+
+
+
)
}
@@ -80,19 +82,21 @@ export const LoggedInMemory = ({
}: ProviderMocks) => {
return (
-
-
-
-
-
-
- LOADING...>}>{children}
-
-
-
-
-
-
+
+
+
+
+
+
+
+ LOADING...>}>{children}
+
+
+
+
+
+
+
)
}
diff --git a/src/types/custom-types.ts b/src/types/custom-types.ts
index 887855d3..9542070e 100644
--- a/src/types/custom-types.ts
+++ b/src/types/custom-types.ts
@@ -94,10 +94,6 @@ export interface CommandParams {
version: string
}
-export interface TableInterface {
- parentState: TableState
-}
-
export interface AugmentedCommand extends Command {
namespace: string
systemName: string
diff --git a/src/utils/date-formatter.ts b/src/utils/date-formatter.ts
new file mode 100644
index 00000000..df9ecd8c
--- /dev/null
+++ b/src/utils/date-formatter.ts
@@ -0,0 +1,14 @@
+import { DateTimeFormatOptions } from 'luxon'
+
+export const dateFormatted = (date: Date) => {
+ const options: DateTimeFormatOptions = {
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ hour: 'numeric',
+ second: 'numeric',
+ minute: 'numeric',
+ hour12: false,
+ }
+ return date.toLocaleString(undefined, options)
+}