Skip to content

Commit

Permalink
further work on status reports
Browse files Browse the repository at this point in the history
  • Loading branch information
nl0 committed Sep 2, 2022
1 parent 3ed5805 commit f575e1d
Show file tree
Hide file tree
Showing 11 changed files with 371 additions and 216 deletions.
5 changes: 4 additions & 1 deletion catalog/app/containers/Admin/Status/Canaries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import * as DG from 'components/DataGrid'
import { useDataGridStyles } from './DataGrid'
import type STATUS_QUERY from './gql/Status.generated'

type StatusResult = NonNullable<ResultOf<typeof STATUS_QUERY>['status']>
type StatusResult = Extract<
ResultOf<typeof STATUS_QUERY>['status'],
{ __typename: 'Status' }
>
type Canary = StatusResult['canaries'][number]

interface State {
Expand Down
118 changes: 87 additions & 31 deletions catalog/app/containers/Admin/Status/Reports.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as dateFns from 'date-fns'
import invariant from 'invariant'
import * as R from 'ramda'
import * as React from 'react'
import * as RRDom from 'react-router-dom'
import * as dateFns from 'date-fns'
import type * as urql from 'urql'
import type { ResultOf } from '@graphql-typed-document-node/core'
import * as M from '@material-ui/core'

Expand All @@ -15,7 +17,10 @@ import { useDataGridStyles } from './DataGrid'
import REPORTS_QUERY from './gql/Reports.generated'
import type STATUS_QUERY from './gql/Status.generated'

type StatusResult = NonNullable<ResultOf<typeof STATUS_QUERY>['status']>
type StatusResult = Extract<
ResultOf<typeof STATUS_QUERY>['status'],
{ __typename: 'Status' }
>
type StatusReport = StatusResult['reports']['page'][number]

interface ReportLinkProps {
Expand Down Expand Up @@ -45,6 +50,27 @@ function PreviewLink({ loc }: ReportLinkProps) {
)
}

interface ErrorOverlayProps {
error: urql.CombinedError
resetState: () => void
}

function ErrorOverlay({ error, resetState }: ErrorOverlayProps) {
return (
<M.Box pt={3} pb={4}>
<M.Typography variant="h6" align="center" gutterBottom>
An error occured
</M.Typography>
<M.Typography align="center">{error.message}</M.Typography>
<M.Box pt={3} display="flex" justifyContent="center">
<M.Button onClick={resetState} variant="contained" color="primary">
Reset table state
</M.Button>
</M.Box>
</M.Box>
)
}

const columns: DG.GridColumns = [
{
field: 'timestamp',
Expand Down Expand Up @@ -134,40 +160,66 @@ export default function Reports({
rowCount: total,
})

const [sortModel, setSortModel] = React.useState<DG.GridSortModel>(() => [
{
field: 'timestamp',
sort:
defaults.order === Model.GQLTypes.StatusReportListOrder.NEW_FIRST
? 'desc'
: 'asc',
},
])
const handleSortModelChange = React.useCallback((params: DG.GridSortModelParams) => {
setSortModel(params.sortModel)
const [page, setPage] = React.useState(defaults.page)
const handlePageChange = React.useCallback((params: DG.GridPageChangeParams) => {
setPage(params.page + 1)
}, [])

const [pageSize, setPageSize] = React.useState(defaults.perPage)
const handlePageSizeChange = React.useCallback(
(params: DG.GridPageChangeParams) => {
if (pageSize === params.pageSize) return
setPageSize(params.pageSize)
// reset page when changing page size
setPage(1)
},
[pageSize],
)

const initialSortModel: DG.GridSortModel = React.useMemo(
() => [
{
field: 'timestamp',
sort:
defaults.order === Model.GQLTypes.StatusReportListOrder.NEW_FIRST
? 'desc'
: 'asc',
},
],
[defaults.order],
)
const [sortModel, setSortModel] = React.useState<DG.GridSortModel>(initialSortModel)
const handleSortModelChange = React.useCallback(
(params: DG.GridSortModelParams) => {
if (R.equals(sortModel, params.sortModel)) return
setSortModel(params.sortModel)
// reset page when changing sort order
setPage(1)
},
[sortModel],
)
const order = React.useMemo(() => sortModelToOrder(sortModel), [sortModel])

const [filterModel, setFilterModel] = React.useState<DG.GridFilterModel>({ items: [] })
const initialFilterModel: DG.GridFilterModel = React.useMemo(() => ({ items: [] }), [])
const [filterModel, setFilterModel] =
React.useState<DG.GridFilterModel>(initialFilterModel)
const handleFilterModelChange = React.useCallback(
(params: DG.GridFilterModelParams) => {
if (R.equals(filterModel, params.filterModel)) return
setFilterModel(params.filterModel)
// reset page when changing filtering
setPage(1)
},
[],
[filterModel],
)
const filter = React.useMemo(() => filterModelToFilter(filterModel), [filterModel])

const [page, setPage] = React.useState(defaults.page)
const handlePageChange = React.useCallback((params: DG.GridPageChangeParams) => {
setPage(params.page + 1)
}, [])

const [pageSize, setPageSize] = React.useState(defaults.perPage)
const handlePageSizeChange = React.useCallback((params: DG.GridPageChangeParams) => {
setPageSize(params.pageSize)
// reset page when changing page size
const resetState = React.useCallback(() => {
setPage(1)
}, [])
setPageSize(defaultPerPage)
setFilterModel(initialFilterModel)
setSortModel(initialSortModel)
}, [defaultPerPage, initialFilterModel, initialSortModel])

const variables = {
page,
Expand All @@ -178,28 +230,29 @@ export default function Reports({

const pause = R.equals(defaults, variables)

const data = useQuery({
const queryResult = useQuery({
query: REPORTS_QUERY,
pause,
variables,
})

// console.log('data', data)
// TODO: handle data.error
invariant(queryResult.data?.status?.__typename !== 'Unavailable', 'Status unavalable')

const rows = (
pause ? firstPage : data.data?.status?.reports.page ?? fallbacks.rows
pause ? firstPage : queryResult.data?.status?.reports.page ?? fallbacks.rows
) as StatusReport[]
if (rows !== fallbacks.rows) fallbacks.rows = rows

const isFiltered = !R.equals(defaults.filter, variables.filter)

const rowCount = isFiltered
? data.data?.status?.reports.total ?? fallbacks.rowCount
? queryResult.data?.status?.reports.total ?? fallbacks.rowCount
: total
if (rowCount !== fallbacks.rowCount) fallbacks.rowCount = rowCount

const loading = pause ? false : data.fetching
const loading = pause ? false : queryResult.fetching
const error =
!pause && !loading && queryResult.error ? { error: queryResult.error } : null

return (
<M.Paper className={classes.root}>
Expand All @@ -212,6 +265,8 @@ export default function Reports({
columns={columns}
getRowId={(r) => (r as StatusReport).timestamp.toISOString()}
autoHeight
components={{ ErrorOverlay }}
componentsProps={{ errorOverlay: { resetState } }}
disableSelectionOnClick
disableColumnSelector
disableColumnResize
Expand Down Expand Up @@ -240,6 +295,7 @@ export default function Reports({
pageSize={pageSize}
onPageSizeChange={handlePageSizeChange}
loading={loading}
error={error}
/>
</M.Paper>
)
Expand Down
5 changes: 4 additions & 1 deletion catalog/app/containers/Admin/Status/Stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import * as Chart from 'components/EChartsChart'

import type STATUS_QUERY from './gql/Status.generated'

type StatusResult = NonNullable<ResultOf<typeof STATUS_QUERY>['status']>
type StatusResult = Extract<
ResultOf<typeof STATUS_QUERY>['status'],
{ __typename: 'Status' }
>

const CHART_COLORS = [M.colors.red[300], M.colors.lightBlue[300], M.colors.grey[400]]

Expand Down
2 changes: 1 addition & 1 deletion catalog/app/containers/Admin/Status/Status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function Status() {
return (
<M.Box my={2}>
<MetaTitle>{['Status', 'Admin']}</MetaTitle>
{status ? (
{status.__typename === 'Status' ? (
<>
<Stats
latest={status.latestStats}
Expand Down
115 changes: 67 additions & 48 deletions catalog/app/containers/Admin/Status/gql/Reports.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ export type containers_Admin_Status_gql_ReportsQueryVariables = Types.Exact<{
export type containers_Admin_Status_gql_ReportsQuery = {
readonly __typename: 'Query'
} & {
readonly status: Types.Maybe<
{ readonly __typename: 'Status' } & {
readonly reports: { readonly __typename: 'StatusReportList' } & Pick<
Types.StatusReportList,
'total'
> & {
readonly page: ReadonlyArray<
{ readonly __typename: 'StatusReport' } & Pick<
Types.StatusReport,
'timestamp' | 'renderedReportLocation'
readonly status:
| ({ readonly __typename: 'Status' } & {
readonly reports: { readonly __typename: 'StatusReportList' } & Pick<
Types.StatusReportList,
'total'
> & {
readonly page: ReadonlyArray<
{ readonly __typename: 'StatusReport' } & Pick<
Types.StatusReport,
'timestamp' | 'renderedReportLocation'
>
>
>
}
}
>
}
})
| { readonly __typename: 'Unavailable' }
}

export const containers_Admin_Status_gql_ReportsDocument = {
Expand Down Expand Up @@ -85,59 +85,78 @@ export const containers_Admin_Status_gql_ReportsDocument = {
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: '__typename' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'reports' },
arguments: [
{
kind: 'Argument',
name: { kind: 'Name', value: 'filter' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'filter' },
},
},
],
kind: 'InlineFragment',
typeCondition: {
kind: 'NamedType',
name: { kind: 'Name', value: 'Status' },
},
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'total' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'page' },
name: { kind: 'Name', value: 'reports' },
arguments: [
{
kind: 'Argument',
name: { kind: 'Name', value: 'number' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'page' },
},
},
{
kind: 'Argument',
name: { kind: 'Name', value: 'perPage' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'perPage' },
},
},
{
kind: 'Argument',
name: { kind: 'Name', value: 'order' },
name: { kind: 'Name', value: 'filter' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'order' },
name: { kind: 'Name', value: 'filter' },
},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{ kind: 'Field', name: { kind: 'Name', value: 'timestamp' } },
{ kind: 'Field', name: { kind: 'Name', value: 'total' } },
{
kind: 'Field',
name: { kind: 'Name', value: 'renderedReportLocation' },
name: { kind: 'Name', value: 'page' },
arguments: [
{
kind: 'Argument',
name: { kind: 'Name', value: 'number' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'page' },
},
},
{
kind: 'Argument',
name: { kind: 'Name', value: 'perPage' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'perPage' },
},
},
{
kind: 'Argument',
name: { kind: 'Name', value: 'order' },
value: {
kind: 'Variable',
name: { kind: 'Name', value: 'order' },
},
},
],
selectionSet: {
kind: 'SelectionSet',
selections: [
{
kind: 'Field',
name: { kind: 'Name', value: 'timestamp' },
},
{
kind: 'Field',
name: {
kind: 'Name',
value: 'renderedReportLocation',
},
},
],
},
},
],
},
Expand Down
13 changes: 8 additions & 5 deletions catalog/app/containers/Admin/Status/gql/Reports.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ query (
$order: StatusReportListOrder!,
) {
status {
reports(filter: $filter) {
total
page(number: $page, perPage: $perPage, order: $order) {
timestamp
renderedReportLocation
__typename
... on Status {
reports(filter: $filter) {
total
page(number: $page, perPage: $perPage, order: $order) {
timestamp
renderedReportLocation
}
}
}
}
Expand Down
Loading

0 comments on commit f575e1d

Please sign in to comment.