@xyo-network/react-payload 2.26.37 → 2.26.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs.json +1 -1
- package/package.json +9 -9
- package/src/components/Details/DataDetails.tsx +65 -0
- package/src/components/Details/Details.stories.tsx +62 -0
- package/src/components/Details/Details.tsx +27 -0
- package/src/components/Details/HashSourceDetails.tsx +41 -0
- package/src/components/Details/JsonDetails.tsx +44 -0
- package/src/components/Details/MetaDetails.tsx +38 -0
- package/src/components/Details/ValidationDetails/ValidationDetails.stories.tsx +55 -0
- package/src/components/Details/ValidationDetails/ValidationDetails.tsx +42 -0
- package/src/components/Details/ValidationDetails/ValidationDetailsProps.ts +8 -0
- package/src/components/Details/ValidationDetails/index.ts +2 -0
- package/src/components/Details/index.ts +5 -0
- package/src/components/Table/PayloadTableColumnConfig.ts +28 -0
- package/src/components/Table/Table.stories.tsx +43 -0
- package/src/components/Table/Table.tsx +60 -0
- package/src/components/Table/TableRow.tsx +104 -0
- package/src/components/Table/index.ts +3 -0
- package/src/components/index.ts +2 -0
- package/src/contexts/Payload/Context.ts +5 -0
- package/src/contexts/Payload/Provider.tsx +31 -0
- package/src/contexts/Payload/State.ts +8 -0
- package/src/contexts/Payload/index.ts +4 -0
- package/src/contexts/Payload/use.ts +7 -0
- package/src/contexts/index.ts +1 -0
- package/src/hooks/ResolvePayloadArgs.ts +6 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/lib/FetchHuriHashOptions.ts +3 -0
- package/src/hooks/lib/findHuriNetwork.ts +13 -0
- package/src/hooks/lib/index.ts +2 -0
- package/src/hooks/useGetSchema.stories.tsx +70 -0
- package/src/hooks/useGetSchema.tsx +51 -0
- package/src/hooks/useHuriHash.stories.tsx +108 -0
- package/src/hooks/useHuriHash.tsx +38 -0
- package/src/hooks/useLoadPayload.stories.tsx +69 -0
- package/src/hooks/useLoadPayload.tsx +60 -0
- package/src/hooks/useResolveHuri.tsx +74 -0
- package/src/index.ts +3 -0
- package/src/types/images.d.ts +5 -0
package/dist/docs.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"fileName": "index.ts",
|
|
11
11
|
"line": 1,
|
|
12
12
|
"character": 0,
|
|
13
|
-
"url": "https://github.com/XYOracleNetwork/sdk-xyo-react-js/blob/
|
|
13
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-react-js/blob/c31a96d/packages/payload/src/index.ts#L1"
|
|
14
14
|
}
|
|
15
15
|
]
|
|
16
16
|
}
|
package/package.json
CHANGED
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
"@xyo-network/api": "^2.22.15",
|
|
22
22
|
"@xyo-network/network": "^2.22.15",
|
|
23
23
|
"@xyo-network/payload": "^2.22.15",
|
|
24
|
-
"@xyo-network/react-archive": "^2.26.
|
|
25
|
-
"@xyo-network/react-archivist": "^2.26.
|
|
26
|
-
"@xyo-network/react-archivist-api": "^2.26.
|
|
27
|
-
"@xyo-network/react-auth-service": "^2.26.
|
|
28
|
-
"@xyo-network/react-network": "^2.26.
|
|
29
|
-
"@xyo-network/react-property": "^2.26.
|
|
30
|
-
"@xyo-network/react-schema": "^2.26.
|
|
31
|
-
"@xyo-network/react-shared": "^2.26.
|
|
24
|
+
"@xyo-network/react-archive": "^2.26.38",
|
|
25
|
+
"@xyo-network/react-archivist": "^2.26.38",
|
|
26
|
+
"@xyo-network/react-archivist-api": "^2.26.38",
|
|
27
|
+
"@xyo-network/react-auth-service": "^2.26.38",
|
|
28
|
+
"@xyo-network/react-network": "^2.26.38",
|
|
29
|
+
"@xyo-network/react-property": "^2.26.38",
|
|
30
|
+
"@xyo-network/react-schema": "^2.26.38",
|
|
31
|
+
"@xyo-network/react-shared": "^2.26.38",
|
|
32
32
|
"@xyo-network/utils": "^2.22.15",
|
|
33
33
|
"luxon": "^3.0.1",
|
|
34
34
|
"react": "^18.2.0",
|
|
@@ -95,5 +95,5 @@
|
|
|
95
95
|
},
|
|
96
96
|
"sideEffects": false,
|
|
97
97
|
"types": "dist/esm/index.d.ts",
|
|
98
|
-
"version": "2.26.
|
|
98
|
+
"version": "2.26.38"
|
|
99
99
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import ContentCopyIcon from '@mui/icons-material/ContentCopy'
|
|
2
|
+
import VisibilityIcon from '@mui/icons-material/Visibility'
|
|
3
|
+
import { Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material'
|
|
4
|
+
import { ButtonEx } from '@xylabs/react-button'
|
|
5
|
+
import { XyoPayload, XyoPayloadWrapper } from '@xyo-network/payload'
|
|
6
|
+
import { Property, PropertyAction, PropertyProps } from '@xyo-network/react-property'
|
|
7
|
+
import { SizeProp } from '@xyo-network/react-shared'
|
|
8
|
+
import { useState } from 'react'
|
|
9
|
+
|
|
10
|
+
import { PayloadHashSourceDetails } from './HashSourceDetails'
|
|
11
|
+
|
|
12
|
+
export type PayloadDataDetailsProps = PropertyProps & {
|
|
13
|
+
payload?: XyoPayload
|
|
14
|
+
size?: SizeProp
|
|
15
|
+
badge?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const PayloadDataDetails: React.FC<PayloadDataDetailsProps> = ({ size, badge, payload, ...props }) => {
|
|
19
|
+
const wrapper = payload ? new XyoPayloadWrapper(payload) : undefined
|
|
20
|
+
|
|
21
|
+
const [viewSourceOpen, setViewSourceOpen] = useState(false)
|
|
22
|
+
const hash = wrapper?.hash
|
|
23
|
+
|
|
24
|
+
let elevation = 2
|
|
25
|
+
if (props.paper) {
|
|
26
|
+
elevation += props.elevation ?? 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const actions: PropertyAction[] = [
|
|
30
|
+
{
|
|
31
|
+
icon: <VisibilityIcon />,
|
|
32
|
+
name: 'View',
|
|
33
|
+
onClick: () => setViewSourceOpen(true),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
icon: <ContentCopyIcon />,
|
|
37
|
+
name: 'Copy',
|
|
38
|
+
onClick: async () => await navigator.clipboard.writeText(wrapper?.hash ?? ''),
|
|
39
|
+
},
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
const onCopy = async () => {
|
|
43
|
+
await navigator.clipboard.writeText(wrapper?.stringified ?? '')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<>
|
|
48
|
+
<Property titleProps={{ elevation }} badge={badge} size={size} actions={actions} title="Payload Hash" value={hash ?? '<Unknown>'} tip="This is the payload hash" {...props} />
|
|
49
|
+
<Dialog open={viewSourceOpen} onClose={() => setViewSourceOpen(false)}>
|
|
50
|
+
<DialogTitle>Hash Source</DialogTitle>
|
|
51
|
+
<DialogContent>
|
|
52
|
+
<PayloadHashSourceDetails noTitle payload={payload} />
|
|
53
|
+
</DialogContent>
|
|
54
|
+
<DialogActions>
|
|
55
|
+
<ButtonEx color="secondary" onClick={onCopy}>
|
|
56
|
+
Copy
|
|
57
|
+
</ButtonEx>
|
|
58
|
+
<ButtonEx color="secondary" onClick={() => setViewSourceOpen(false)}>
|
|
59
|
+
Close
|
|
60
|
+
</ButtonEx>
|
|
61
|
+
</DialogActions>
|
|
62
|
+
</Dialog>
|
|
63
|
+
</>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ComponentMeta, ComponentStory } from '@storybook/react'
|
|
2
|
+
import { BrowserRouter, Route, Routes } from 'react-router-dom'
|
|
3
|
+
|
|
4
|
+
import { appThemeDecorator, samplePayload, samplePayloadFromBuilder } from '../../../../../.storybook'
|
|
5
|
+
import { PayloadDetails } from './Details'
|
|
6
|
+
|
|
7
|
+
const StorybookEntry = {
|
|
8
|
+
argTypes: {},
|
|
9
|
+
component: PayloadDetails,
|
|
10
|
+
parameters: {
|
|
11
|
+
docs: {
|
|
12
|
+
page: null,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
title: 'payload/Details',
|
|
16
|
+
} as ComponentMeta<typeof PayloadDetails>
|
|
17
|
+
|
|
18
|
+
const Template: ComponentStory<typeof PayloadDetails> = (args) => (
|
|
19
|
+
<BrowserRouter>
|
|
20
|
+
<Routes>
|
|
21
|
+
<Route path="temp" element={<h1>Successfully navigated to archivePath</h1>} />
|
|
22
|
+
<Route path="*" element={<PayloadDetails {...args}></PayloadDetails>}></Route>
|
|
23
|
+
</Routes>
|
|
24
|
+
</BrowserRouter>
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
const Default = Template.bind({})
|
|
28
|
+
Default.args = {}
|
|
29
|
+
Default.decorators = [appThemeDecorator]
|
|
30
|
+
|
|
31
|
+
const WithSample = Template.bind({})
|
|
32
|
+
WithSample.args = { payload: samplePayload }
|
|
33
|
+
WithSample.decorators = [appThemeDecorator]
|
|
34
|
+
|
|
35
|
+
const WithBuilderSample = Template.bind({})
|
|
36
|
+
WithBuilderSample.args = { payload: samplePayloadFromBuilder }
|
|
37
|
+
WithBuilderSample.decorators = [appThemeDecorator]
|
|
38
|
+
|
|
39
|
+
const WithArchiveLink = Template.bind({})
|
|
40
|
+
WithArchiveLink.args = { archivePath: 'temp', payload: samplePayloadFromBuilder }
|
|
41
|
+
WithArchiveLink.decorators = [appThemeDecorator]
|
|
42
|
+
|
|
43
|
+
const DefaultPaper = Template.bind({})
|
|
44
|
+
DefaultPaper.args = { paper: true }
|
|
45
|
+
DefaultPaper.decorators = [appThemeDecorator]
|
|
46
|
+
|
|
47
|
+
const WithSamplePaper = Template.bind({})
|
|
48
|
+
WithSamplePaper.args = { paper: true, payload: samplePayload }
|
|
49
|
+
WithSamplePaper.decorators = [appThemeDecorator]
|
|
50
|
+
|
|
51
|
+
const WithBuilderSamplePaper = Template.bind({})
|
|
52
|
+
WithBuilderSamplePaper.args = { paper: true, payload: samplePayloadFromBuilder }
|
|
53
|
+
WithBuilderSamplePaper.decorators = [appThemeDecorator]
|
|
54
|
+
|
|
55
|
+
const WithArchiveLinkPaper = Template.bind({})
|
|
56
|
+
WithArchiveLinkPaper.args = { archivePath: 'temp', paper: true, payload: samplePayloadFromBuilder }
|
|
57
|
+
WithArchiveLinkPaper.decorators = [appThemeDecorator]
|
|
58
|
+
|
|
59
|
+
export { Default, DefaultPaper, WithArchiveLink, WithArchiveLinkPaper, WithBuilderSample, WithBuilderSamplePaper, WithSample, WithSamplePaper }
|
|
60
|
+
|
|
61
|
+
// eslint-disable-next-line import/no-default-export
|
|
62
|
+
export default StorybookEntry
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FlexBoxProps, FlexCol } from '@xylabs/react-flexbox'
|
|
2
|
+
import { XyoPayload } from '@xyo-network/payload'
|
|
3
|
+
|
|
4
|
+
import { PayloadDataDetails } from './DataDetails'
|
|
5
|
+
import { PayloadJsonDetails } from './JsonDetails'
|
|
6
|
+
import { PayloadMetaDetails } from './MetaDetails'
|
|
7
|
+
import { PayloadValidationDetails } from './ValidationDetails'
|
|
8
|
+
|
|
9
|
+
export type WithPaper<T> = T & { paper: true }
|
|
10
|
+
export type WithoutPaper<T> = T & { paper?: false }
|
|
11
|
+
|
|
12
|
+
export type PayloadDetailsProps = FlexBoxProps & {
|
|
13
|
+
payload?: XyoPayload
|
|
14
|
+
paper?: boolean
|
|
15
|
+
archivePath?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const PayloadDetails: React.FC<PayloadDetailsProps> = ({ archivePath, paper, payload, ...props }) => {
|
|
19
|
+
return (
|
|
20
|
+
<FlexCol gap={1} justifyContent="flex-start" alignItems="stretch" marginTop={2} marginBottom={8} {...props}>
|
|
21
|
+
<PayloadDataDetails paper={paper} size="large" badge payload={payload} />
|
|
22
|
+
<PayloadMetaDetails archivePath={archivePath} paper={paper ? true : false} value={payload} />
|
|
23
|
+
<PayloadValidationDetails paper={paper} value={payload} />
|
|
24
|
+
<PayloadJsonDetails paper={paper} payload={payload} />
|
|
25
|
+
</FlexCol>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import ContentCopyIcon from '@mui/icons-material/ContentCopy'
|
|
2
|
+
import { IconButton, Typography, useTheme } from '@mui/material'
|
|
3
|
+
import { FlexBoxProps, FlexCol, FlexGrowRow, FlexRow } from '@xylabs/react-flexbox'
|
|
4
|
+
import { QuickTipButton } from '@xylabs/react-quick-tip-button'
|
|
5
|
+
import { XyoPayload, XyoPayloadWrapper } from '@xyo-network/payload'
|
|
6
|
+
|
|
7
|
+
export interface PayloadHashSourceDetailsProps extends FlexBoxProps {
|
|
8
|
+
noTitle?: boolean
|
|
9
|
+
payload?: XyoPayload
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const PayloadHashSourceDetails: React.FC<PayloadHashSourceDetailsProps> = ({ noTitle = false, payload, ...props }) => {
|
|
13
|
+
const theme = useTheme()
|
|
14
|
+
const payloadWrapper = payload ? new XyoPayloadWrapper(payload) : null
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<FlexCol alignItems="stretch" {...props}>
|
|
18
|
+
{noTitle ? null : (
|
|
19
|
+
<FlexRow margin={1} justifyContent="flex-start">
|
|
20
|
+
<Typography>Hash Source</Typography>
|
|
21
|
+
<QuickTipButton title="Hash Source">The actual string used to generate the hash (SHA256)</QuickTipButton>
|
|
22
|
+
</FlexRow>
|
|
23
|
+
)}
|
|
24
|
+
<FlexRow>
|
|
25
|
+
<FlexGrowRow background border={1} borderColor={theme.palette.divider} justifyContent="start">
|
|
26
|
+
<Typography padding={2} fontFamily="monospace" variant="body1" sx={{ overflowWrap: 'break-word', wordBreak: 'break-all' }}>
|
|
27
|
+
{payloadWrapper?.stringified ?? ''}
|
|
28
|
+
</Typography>
|
|
29
|
+
</FlexGrowRow>
|
|
30
|
+
<IconButton>
|
|
31
|
+
<ContentCopyIcon />
|
|
32
|
+
</IconButton>
|
|
33
|
+
</FlexRow>
|
|
34
|
+
{noTitle ? (
|
|
35
|
+
<FlexRow margin={1} justifyContent="flex-start">
|
|
36
|
+
<Typography variant="body2">The actual string used to generate the hash (SHA256). This can be used to validate the hash manually.</Typography>
|
|
37
|
+
</FlexRow>
|
|
38
|
+
) : null}
|
|
39
|
+
</FlexCol>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Paper, useMediaQuery, useTheme } from '@mui/material'
|
|
2
|
+
import { FlexGrowRow } from '@xylabs/react-flexbox'
|
|
3
|
+
import { XyoPayload } from '@xyo-network/payload'
|
|
4
|
+
import { PropertyGroup, PropertyGroupProps } from '@xyo-network/react-property'
|
|
5
|
+
import { lazy, Suspense } from 'react'
|
|
6
|
+
import { ReactJsonViewProps } from 'react-json-view'
|
|
7
|
+
|
|
8
|
+
const JsonView = lazy(() => import(/* webpackChunkName: "jsonView" */ 'react-json-view'))
|
|
9
|
+
|
|
10
|
+
export type PayloadJsonDetailsProps = PropertyGroupProps & {
|
|
11
|
+
payload?: XyoPayload
|
|
12
|
+
jsonViewProps?: ReactJsonViewProps
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const PayloadJsonDetails: React.FC<PayloadJsonDetailsProps> = ({ jsonViewProps, payload = {}, ...props }) => {
|
|
16
|
+
const { breakpoints, palette } = useTheme()
|
|
17
|
+
const belowSm = useMediaQuery(breakpoints.down('sm'))
|
|
18
|
+
|
|
19
|
+
let elevation = 2
|
|
20
|
+
if (props.paper) {
|
|
21
|
+
elevation += props.elevation ?? 0
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const jsonTheme = palette.mode === 'dark' ? 'shapeshifter' : undefined
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<PropertyGroup titleProps={{ elevation }} title="JSON" tip="The raw JSON of the payload" {...props}>
|
|
28
|
+
<Paper square variant="elevation" style={{ overflow: 'hidden', padding: '16px', width: '100%' }}>
|
|
29
|
+
<Suspense fallback={<FlexGrowRow />}>
|
|
30
|
+
<JsonView
|
|
31
|
+
groupArraysAfterLength={5}
|
|
32
|
+
shouldCollapse={(props) => props.name !== 'root'}
|
|
33
|
+
style={{ backgroundColor: undefined, overflow: 'hidden' }}
|
|
34
|
+
src={payload}
|
|
35
|
+
enableClipboard
|
|
36
|
+
theme={jsonTheme}
|
|
37
|
+
collapseStringsAfterLength={belowSm ? 24 : 32}
|
|
38
|
+
{...jsonViewProps}
|
|
39
|
+
/>
|
|
40
|
+
</Suspense>
|
|
41
|
+
</Paper>
|
|
42
|
+
</PropertyGroup>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { XyoPayloadWithPartialMeta } from '@xyo-network/payload'
|
|
2
|
+
import { ArchiveProperty } from '@xyo-network/react-archive'
|
|
3
|
+
import { Property, PropertyGroup, PropertyGroupProps } from '@xyo-network/react-property'
|
|
4
|
+
|
|
5
|
+
export type PayloadMetaDetailsProps = PropertyGroupProps & {
|
|
6
|
+
value?: XyoPayloadWithPartialMeta
|
|
7
|
+
archivePath?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const PayloadMetaDetails: React.FC<PayloadMetaDetailsProps> = ({ archivePath, value, ...props }) => {
|
|
11
|
+
let elevation = 2
|
|
12
|
+
if (props.paper) {
|
|
13
|
+
elevation += props.elevation ?? 0
|
|
14
|
+
}
|
|
15
|
+
return (
|
|
16
|
+
<PropertyGroup titleProps={{ elevation }} title="Meta" tip="The meta fields added to the record by the archivist" {...props}>
|
|
17
|
+
{value?._client ? (
|
|
18
|
+
<Property titleProps={{ elevation }} flexGrow={1} title="Client" value={value?._client ?? '<Unknown>'} tip="This client used to create this payload" />
|
|
19
|
+
) : null}
|
|
20
|
+
{value?._archive ? <ArchiveProperty titleProps={{ elevation }} flexGrow={1} payload={value} path={archivePath} /> : null}
|
|
21
|
+
{value?._reportedHash ? (
|
|
22
|
+
<Property titleProps={{ elevation }} flexGrow={1} title="Reported Hash" value={value?._reportedHash ?? '<Unknown>'} tip="The has reported by the payload" />
|
|
23
|
+
) : null}
|
|
24
|
+
{value?._timestamp ? (
|
|
25
|
+
<Property titleProps={{ elevation }} flexGrow={1} title="Timestamp" value={value?._timestamp ?? '<Unknown>'} tip="This timestamp of the payload" />
|
|
26
|
+
) : null}
|
|
27
|
+
{value?._observeDuration ? (
|
|
28
|
+
<Property
|
|
29
|
+
titleProps={{ elevation }}
|
|
30
|
+
flexGrow={1}
|
|
31
|
+
title="Observation Duration"
|
|
32
|
+
value={value?._observeDuration ?? '<Unknown>'}
|
|
33
|
+
tip="This duration of time observed by the witness"
|
|
34
|
+
/>
|
|
35
|
+
) : null}
|
|
36
|
+
</PropertyGroup>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ComponentStory, Meta } from '@storybook/react'
|
|
2
|
+
import { BrowserRouter } from 'react-router-dom'
|
|
3
|
+
|
|
4
|
+
import { appThemeDecorator, samplePayload } from '../../../../../../.storybook'
|
|
5
|
+
import { PayloadDetails } from '../Details'
|
|
6
|
+
import { PayloadValidationDetails } from './ValidationDetails'
|
|
7
|
+
|
|
8
|
+
const StorybookEntry: Meta = {
|
|
9
|
+
argTypes: {},
|
|
10
|
+
args: {
|
|
11
|
+
value: {
|
|
12
|
+
schema: 'network.xyo.schema',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
component: PayloadDetails,
|
|
16
|
+
decorators: [appThemeDecorator],
|
|
17
|
+
parameters: {
|
|
18
|
+
docs: {
|
|
19
|
+
page: null,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
title: 'payload/ValidationDetails',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const Template: ComponentStory<typeof PayloadValidationDetails> = (args) => (
|
|
26
|
+
<BrowserRouter>
|
|
27
|
+
<PayloadValidationDetails {...args} />
|
|
28
|
+
</BrowserRouter>
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
const Default = Template.bind({})
|
|
32
|
+
Default.args = { skipBody: true }
|
|
33
|
+
|
|
34
|
+
const WithViewSchemaLink = Template.bind({})
|
|
35
|
+
WithViewSchemaLink.args = { viewSchemaUrl: 'http://beta.explore.xyo.network/6fe3f745b1179fefa74cc3c7eab58321bee1c9ca9e34d9585467364cc5d3bbe2/?huri=huri' }
|
|
36
|
+
|
|
37
|
+
const WithErrorsInToolTip = Template.bind({})
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
WithErrorsInToolTip.args = { value: { ...samplePayload, ...{ _hash: '6fe3f745b1179fefa74cc3c7eab58321bee1c9ca9e34d9585467364cc5d3bbe2' } } }
|
|
41
|
+
|
|
42
|
+
const SkipBody = Template.bind({})
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
SkipBody.args = { skipBody: true, value: { _hash: '44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a', _timestamp: new Date().getTime() } }
|
|
46
|
+
|
|
47
|
+
const SkipMeta = Template.bind({})
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
SkipMeta.args = { skipMeta: true, value: { _hash: null, schema: 'network.xyo.schema' } }
|
|
51
|
+
|
|
52
|
+
export { Default, SkipBody, SkipMeta, WithErrorsInToolTip, WithViewSchemaLink }
|
|
53
|
+
|
|
54
|
+
// eslint-disable-next-line import/no-default-export
|
|
55
|
+
export default StorybookEntry
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Typography } from '@mui/material'
|
|
2
|
+
import { FlexCol } from '@xylabs/react-flexbox'
|
|
3
|
+
import { XyoPayloadValidator, XyoPayloadWithMeta } from '@xyo-network/payload'
|
|
4
|
+
import { Property, PropertyGroup } from '@xyo-network/react-property'
|
|
5
|
+
import { SchemaProperty } from '@xyo-network/react-schema'
|
|
6
|
+
|
|
7
|
+
import { PayloadValidationDetailsProps } from './ValidationDetailsProps'
|
|
8
|
+
|
|
9
|
+
export const PayloadValidationDetails: React.FC<PayloadValidationDetailsProps> = ({ viewSchemaUrl, skipBody = false, value, ...props }) => {
|
|
10
|
+
const validator = value ? new XyoPayloadValidator(value as XyoPayloadWithMeta) : undefined
|
|
11
|
+
|
|
12
|
+
const bodyErrors = skipBody ? [] : validator?.body.validate() ?? []
|
|
13
|
+
const errors: Error[] = [...bodyErrors]
|
|
14
|
+
|
|
15
|
+
let elevation = 2
|
|
16
|
+
if (props.paper) {
|
|
17
|
+
elevation += props.elevation ?? 0
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<PropertyGroup titleProps={{ elevation }} title="Validation" tip="The results from validating the payload" {...props}>
|
|
22
|
+
<Property
|
|
23
|
+
titleProps={{ elevation }}
|
|
24
|
+
flexGrow={1}
|
|
25
|
+
title="Valid"
|
|
26
|
+
value={errors.length === 0 ? 'True' : 'False'}
|
|
27
|
+
tip={
|
|
28
|
+
errors.length > 0 ? (
|
|
29
|
+
<FlexCol>
|
|
30
|
+
{errors.map((error, index) => {
|
|
31
|
+
return <Typography key={index}>{error.toString()}</Typography>
|
|
32
|
+
})}
|
|
33
|
+
</FlexCol>
|
|
34
|
+
) : (
|
|
35
|
+
<Typography>No Errors</Typography>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
/>
|
|
39
|
+
{value?.schema && <SchemaProperty flexGrow={1} titleProps={{ elevation }} value={value.schema} viewSchemaUrl={viewSchemaUrl} />}
|
|
40
|
+
</PropertyGroup>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { XyoPayloadWithPartialMeta } from '@xyo-network/payload'
|
|
2
|
+
import { PropertyGroupProps } from '@xyo-network/react-property'
|
|
3
|
+
|
|
4
|
+
export type PayloadValidationDetailsProps = PropertyGroupProps & {
|
|
5
|
+
skipBody?: boolean
|
|
6
|
+
value?: XyoPayloadWithPartialMeta
|
|
7
|
+
viewSchemaUrl?: string
|
|
8
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type PayloadTableColumnSlug = 'hash' | 'archive' | 'client' | 'date' | 'time' | 'schema' | 'valid'
|
|
2
|
+
|
|
3
|
+
export interface PayloadTableColumnConfig {
|
|
4
|
+
xs?: PayloadTableColumnSlug[]
|
|
5
|
+
sm?: PayloadTableColumnSlug[]
|
|
6
|
+
md?: PayloadTableColumnSlug[]
|
|
7
|
+
lg?: PayloadTableColumnSlug[]
|
|
8
|
+
xl?: PayloadTableColumnSlug[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const payloadColumnNames: Record<PayloadTableColumnSlug, string> = {
|
|
12
|
+
archive: 'Archive',
|
|
13
|
+
client: 'Client',
|
|
14
|
+
date: 'Date',
|
|
15
|
+
hash: 'Hash',
|
|
16
|
+
schema: 'Schema',
|
|
17
|
+
time: 'Time',
|
|
18
|
+
valid: 'Valid',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const payloadTableColumnConfigDefaults = (): PayloadTableColumnConfig => {
|
|
22
|
+
const xs: PayloadTableColumnSlug[] = ['hash', 'time', 'valid']
|
|
23
|
+
const sm: PayloadTableColumnSlug[] = ['hash', 'time', 'archive', 'valid']
|
|
24
|
+
const md: PayloadTableColumnSlug[] = ['hash', 'schema', 'archive', 'time', 'valid']
|
|
25
|
+
const lg: PayloadTableColumnSlug[] = ['hash', 'schema', 'archive', 'date', 'time', 'valid']
|
|
26
|
+
const xl: PayloadTableColumnSlug[] = ['hash', 'schema', 'archive', 'client', 'date', 'time', 'valid']
|
|
27
|
+
return { lg, md, sm, xl, xs }
|
|
28
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ComponentMeta, ComponentStory } from '@storybook/react'
|
|
2
|
+
import { BrowserRouter } from 'react-router-dom'
|
|
3
|
+
|
|
4
|
+
import { appThemeDecorator, samplePayload } from '../../../../../.storybook'
|
|
5
|
+
import { PayloadTable } from './Table'
|
|
6
|
+
|
|
7
|
+
const StorybookEntry = {
|
|
8
|
+
argTypes: {},
|
|
9
|
+
component: PayloadTable,
|
|
10
|
+
parameters: {
|
|
11
|
+
docs: {
|
|
12
|
+
page: null,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
title: 'payload/Table',
|
|
16
|
+
} as ComponentMeta<typeof PayloadTable>
|
|
17
|
+
|
|
18
|
+
const Template: ComponentStory<typeof PayloadTable> = (args) => (
|
|
19
|
+
<BrowserRouter>
|
|
20
|
+
<PayloadTable {...args}></PayloadTable>
|
|
21
|
+
</BrowserRouter>
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
const Default = Template.bind({})
|
|
25
|
+
Default.args = {}
|
|
26
|
+
Default.decorators = [appThemeDecorator]
|
|
27
|
+
|
|
28
|
+
const WithData = Template.bind({})
|
|
29
|
+
WithData.args = { payloads: [samplePayload, samplePayload] }
|
|
30
|
+
WithData.decorators = [appThemeDecorator]
|
|
31
|
+
|
|
32
|
+
const WithError = Template.bind({})
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
34
|
+
const { _hash, ...badPayload } = samplePayload
|
|
35
|
+
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
37
|
+
//@ts-ignore
|
|
38
|
+
WithError.args = { payloads: [samplePayload, badPayload] }
|
|
39
|
+
|
|
40
|
+
export { Default, WithData, WithError }
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line import/no-default-export
|
|
43
|
+
export default StorybookEntry
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Alert, Table, TableBody, TableCell, TableHead, TableProps, TableRow, Typography } from '@mui/material'
|
|
2
|
+
import { useBreakpoint } from '@xylabs/react-shared'
|
|
3
|
+
import { XyoPayload, XyoPayloadWithPartialMeta } from '@xyo-network/payload'
|
|
4
|
+
import { XyoApiThrownErrorBoundary } from '@xyo-network/react-auth-service'
|
|
5
|
+
|
|
6
|
+
import { payloadColumnNames, PayloadTableColumnConfig, payloadTableColumnConfigDefaults } from './PayloadTableColumnConfig'
|
|
7
|
+
import { PayloadTableRow } from './TableRow'
|
|
8
|
+
|
|
9
|
+
export interface PayloadTableProps extends TableProps {
|
|
10
|
+
exploreDomain?: string
|
|
11
|
+
onRowClick?: (value: XyoPayload) => void
|
|
12
|
+
payloads?: XyoPayloadWithPartialMeta[] | null
|
|
13
|
+
columns?: PayloadTableColumnConfig
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const PayloadTable: React.FC<PayloadTableProps> = ({ exploreDomain, onRowClick, payloads, children, columns = payloadTableColumnConfigDefaults(), ...props }) => {
|
|
17
|
+
const breakPoint = useBreakpoint()
|
|
18
|
+
return breakPoint ? (
|
|
19
|
+
<Table {...props}>
|
|
20
|
+
<TableHead>
|
|
21
|
+
<TableRow>
|
|
22
|
+
{columns[breakPoint]?.map((column, index) => {
|
|
23
|
+
return (
|
|
24
|
+
<TableCell key={index} width={index === 0 ? '100%' : undefined} align={index === 0 ? 'left' : 'center'}>
|
|
25
|
+
<Typography variant="caption" noWrap>
|
|
26
|
+
<strong>{payloadColumnNames[column]}</strong>
|
|
27
|
+
</Typography>
|
|
28
|
+
</TableCell>
|
|
29
|
+
)
|
|
30
|
+
})}
|
|
31
|
+
</TableRow>
|
|
32
|
+
</TableHead>
|
|
33
|
+
<TableBody>
|
|
34
|
+
{payloads?.map((payload, index) => (
|
|
35
|
+
<XyoApiThrownErrorBoundary
|
|
36
|
+
key={`${payload._hash}-${payload._timestamp}-${index}`}
|
|
37
|
+
errorComponent={(e) => (
|
|
38
|
+
<Alert severity="error">
|
|
39
|
+
Error Loading Payload: <Typography fontWeight="bold">{e.message}</Typography>
|
|
40
|
+
</Alert>
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
<PayloadTableRow
|
|
44
|
+
onClick={
|
|
45
|
+
onRowClick
|
|
46
|
+
? () => {
|
|
47
|
+
onRowClick(payload)
|
|
48
|
+
}
|
|
49
|
+
: undefined
|
|
50
|
+
}
|
|
51
|
+
exploreDomain={exploreDomain}
|
|
52
|
+
payload={payload}
|
|
53
|
+
/>
|
|
54
|
+
</XyoApiThrownErrorBoundary>
|
|
55
|
+
))}
|
|
56
|
+
{children}
|
|
57
|
+
</TableBody>
|
|
58
|
+
</Table>
|
|
59
|
+
) : null
|
|
60
|
+
}
|