Skip to content

Commit 7c61be3

Browse files
authored
Merge pull request #1777 from oasisprotocol/mz/roflAppList
ROFL apps support
2 parents 0ddd064 + c142e59 commit 7c61be3

File tree

11 files changed

+161
-86
lines changed

11 files changed

+161
-86
lines changed

.changelog/1777.feature.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ROFL apps support
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { useTranslation } from 'react-i18next'
2+
import { StatusBadge } from '../common/StatusBadge'
3+
4+
type RoflAppInstanceStatusBadgeProps = {
5+
isActive: boolean
6+
}
7+
8+
export const RoflAppInstanceStatusBadge = ({ isActive }: RoflAppInstanceStatusBadgeProps) => {
9+
const { t } = useTranslation()
10+
11+
return (
12+
<StatusBadge
13+
label={isActive ? t('rofl.active') : t('rofl.expired')}
14+
variant={isActive ? 'success' : 'danger'}
15+
/>
16+
)
17+
}

src/app/components/RuntimeTransactionMethod/index.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ export const getRuntimeTxMethodOptions = (t: TFunction, layer: Layer): SelectOpt
7474
)
7575
}
7676

77+
export const getRuntimeRoflUpdatesMethodOptions = (t: TFunction): SelectOptionBase[] => {
78+
const options = ['rofl.Create', 'rofl.Remove', 'rofl.Update']
79+
80+
return options.map(
81+
(method): SelectOptionBase => ({
82+
value: method,
83+
label: getRuntimeTransactionLabel(t, method),
84+
}),
85+
)
86+
}
87+
7788
/**
7889
* The method call body. Defined by the runtime.
7990
*

src/app/components/Table/index.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ const SkeletonTableRows: FC<SkeletonTableRowsProps> = ({ rowsNumber, columnsNumb
3535

3636
type StyledTableRowProps = MuiTableRowProps & {
3737
highlight?: boolean
38+
backgroundColor?: string
3839
}
3940

4041
const StyledTableRow = styled(TableRow, {
41-
shouldForwardProp: prop => prop !== 'highlight',
42-
})<StyledTableRowProps>(({ highlight }) => ({
42+
shouldForwardProp: prop => prop !== 'highlight' && prop !== 'backgroundColor',
43+
})<StyledTableRowProps>(({ backgroundColor, highlight }) => ({
4344
...(highlight && backgroundColorAnimation),
45+
...(backgroundColor && { backgroundColor }),
4446
}))
4547

4648
export enum TableCellAlign {
@@ -60,6 +62,7 @@ export type TableRowProps = {
6062
key: string
6163
data: TableCellProps[]
6264
highlight?: boolean
65+
backgroundColor?: string
6366
}
6467

6568
export type TableColProps = {
@@ -147,7 +150,7 @@ export const Table: FC<TableProps> = ({
147150
<SkeletonTableRows rowsNumber={rowsNumber} columnsNumber={columns.length} />
148151
)}
149152
{rows?.map(row => (
150-
<StyledTableRow key={row.key} highlight={row.highlight}>
153+
<StyledTableRow key={row.key} highlight={row.highlight} backgroundColor={row.backgroundColor}>
151154
{row.data.map((cell, index) => {
152155
if (cell.hide) {
153156
return null

src/app/components/Transactions/RuntimeTransactionTypeFilter.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { FC } from 'react'
22
import { getRuntimeTxMethodOptions } from '../RuntimeTransactionMethod'
33
import { useTranslation } from 'react-i18next'
4-
import { Select } from '../Select'
4+
import { Select, SelectOptionBase } from '../Select'
55
import Typography from '@mui/material/Typography'
66
import { Layer } from '../../../oasis-nexus/api'
77

@@ -28,14 +28,20 @@ export const RuntimeTransactionTypeFilter: FC<{
2828
value: string
2929
setValue: (value: string) => void
3030
expand?: boolean
31-
}> = ({ layer, value, setValue, expand }) => {
31+
customOptions?: SelectOptionBase[]
32+
}> = ({ layer, value, setValue, expand, customOptions }) => {
3233
const { t } = useTranslation()
34+
const defaultOptions = [{ value: 'any', label: 'Any' }]
35+
const options = customOptions
36+
? [...defaultOptions, ...customOptions]
37+
: [...defaultOptions, ...getRuntimeTxMethodOptions(t, layer)]
38+
3339
return (
3440
<Select
3541
className={expand ? 'expand' : undefined}
3642
light={true}
3743
label={<FilterLabel />}
38-
options={[{ value: 'any', label: 'Any' }, ...getRuntimeTxMethodOptions(t, layer)]}
44+
options={options}
3945
value={value}
4046
handleChange={setValue as any}
4147
/>

src/app/pages/RoflAppDetailsPage/Enclaves.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,20 @@ export const Enclaves: FC<EnclavesProps> = ({ policy }) => {
1717

1818
return (
1919
<table>
20-
{policy.enclaves.map((enclave: string) => (
21-
<tr key={enclave}>
22-
<td>
23-
<Typography variant="mono" component="span">
24-
{enclave}
25-
</Typography>
26-
</td>
27-
<td>
28-
<CopyToClipboard value={enclave} />
29-
</td>
30-
</tr>
31-
))}
20+
<tbody>
21+
{policy.enclaves.map((enclave: string) => (
22+
<tr key={enclave}>
23+
<td>
24+
<Typography variant="mono" component="span">
25+
{enclave}
26+
</Typography>
27+
</td>
28+
<td>
29+
<CopyToClipboard value={enclave} />
30+
</td>
31+
</tr>
32+
))}
33+
</tbody>
3234
</table>
3335
)
3436
}
Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import { FC } from 'react'
2-
import { useTranslation } from 'react-i18next'
3-
import { Layer, useGetRuntimeRoflAppsIdInstances } from '../../../oasis-nexus/api'
2+
import { Layer, useGetConsensusEpochs, useGetRuntimeRoflAppsIdInstances } from '../../../oasis-nexus/api'
43
import { NUMBER_OF_ITEMS_ON_SEPARATE_PAGE as limit } from '../../config'
54
import { instancesContainerId } from '../../utils/tabAnchors'
65
import { LinkableCardLayout } from '../../components/LinkableCardLayout'
7-
import { CardEmptyState } from '../../components/CardEmptyState'
86
import { useSearchParamsPagination } from '../../components/Table/useSearchParamsPagination'
97
import { InstancesList } from './InstancesList'
108
import { RoflAppDetailsContext } from './hooks'
@@ -18,32 +16,31 @@ export const InstancesCard: FC<RoflAppDetailsContext> = context => {
1816
}
1917

2018
const InstancesView: FC<RoflAppDetailsContext> = ({ scope, id }) => {
21-
const { t } = useTranslation()
2219
const { network } = scope
2320
const pagination = useSearchParamsPagination('page')
2421
const offset = (pagination.selectedPage - 1) * limit
2522
const instancesQuery = useGetRuntimeRoflAppsIdInstances(network, Layer.sapphire, id, {
2623
limit,
2724
offset,
2825
})
29-
const { isFetched, isLoading, data } = instancesQuery
26+
const { isLoading, data } = instancesQuery
3027
const instances = data?.data.instances
28+
const { isLoading: isEpochLoading, data: epochData } = useGetConsensusEpochs(scope.network, { limit: 1 })
29+
const currentEpoch = epochData?.data.epochs[0].id
3130

3231
return (
33-
<>
34-
{isFetched && !instances?.length && <CardEmptyState label={t('rofl.emptyInstancesList')} />}
35-
<InstancesList
36-
instances={instances}
37-
isLoading={isLoading}
38-
limit={limit}
39-
pagination={{
40-
selectedPage: pagination.selectedPage,
41-
linkToPage: pagination.linkToPage,
42-
totalCount: data?.data.total_count,
43-
isTotalCountClipped: data?.data.is_total_count_clipped,
44-
rowsPerPage: limit,
45-
}}
46-
/>
47-
</>
32+
<InstancesList
33+
instances={instances}
34+
currentEpoch={currentEpoch}
35+
isLoading={isLoading || isEpochLoading}
36+
limit={limit}
37+
pagination={{
38+
selectedPage: pagination.selectedPage,
39+
linkToPage: pagination.linkToPage,
40+
totalCount: data?.data.total_count,
41+
isTotalCountClipped: data?.data.is_total_count_clipped,
42+
rowsPerPage: limit,
43+
}}
44+
/>
4845
)
4946
}

src/app/pages/RoflAppDetailsPage/InstancesList.tsx

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,69 @@ import { FC } from 'react'
22
import { useTranslation } from 'react-i18next'
33
import Typography from '@mui/material/Typography'
44
import { RoflInstance } from '../../../oasis-nexus/api'
5+
import { COLORS } from '../../../styles/theme/colors'
56
import { Table, TableCellAlign, TableColProps } from '../../components/Table'
67
import { TablePaginationProps } from '../../components/Table/TablePagination'
8+
import { RoflAppInstanceStatusBadge } from 'app/components/Rofl/RoflAppInstanceStatusBadge'
79

810
type InstancesListProps = {
11+
currentEpoch: number | undefined
912
instances: RoflInstance[] | undefined
1013
isLoading: boolean
1114
limit: number
1215
pagination: false | TablePaginationProps
1316
}
1417

15-
export const InstancesList: FC<InstancesListProps> = ({ isLoading, limit, pagination, instances }) => {
18+
export const InstancesList: FC<InstancesListProps> = ({
19+
isLoading,
20+
limit,
21+
pagination,
22+
instances,
23+
currentEpoch,
24+
}) => {
1625
const { t } = useTranslation()
1726
const tableColumns: TableColProps[] = [
1827
{ key: 'rak', content: t('rofl.rakAbbreviation') },
1928
{ key: 'node', content: t('rofl.nodeId') },
20-
{ key: 'expiration', content: t('rofl.expirationEpoch'), align: TableCellAlign.Right },
29+
{ key: 'expirationEpoch', content: t('rofl.expirationEpoch'), align: TableCellAlign.Right },
30+
{ key: 'expirationStatus', content: t('common.status'), align: TableCellAlign.Right },
2131
]
2232

23-
const tableRows = instances?.map(instance => {
24-
return {
25-
key: instance.rak,
26-
data: [
27-
{
28-
key: 'rak',
29-
content: <Typography variant="mono">{instance.rak}</Typography>,
30-
},
31-
{
32-
key: 'node',
33-
content: <Typography variant="mono">{instance.endorsing_node_id}</Typography>,
34-
},
35-
{
36-
key: 'expiration',
37-
content: instance.expiration_epoch.toLocaleString(),
38-
align: TableCellAlign.Right,
39-
},
40-
],
41-
}
42-
})
33+
const tableRows =
34+
currentEpoch !== undefined && instances
35+
? instances?.map(instance => {
36+
const isActive = instance.expiration_epoch > currentEpoch
37+
38+
return {
39+
key: instance.rak,
40+
backgroundColor: isActive ? 'transparent' : COLORS.grayLight,
41+
data: [
42+
{
43+
key: 'rak',
44+
content: <Typography variant="mono">{instance.rak}</Typography>,
45+
},
46+
{
47+
key: 'node',
48+
content: <Typography variant="mono">{instance.endorsing_node_id}</Typography>,
49+
},
50+
{
51+
key: 'expirationEpoch',
52+
content: instance.expiration_epoch.toLocaleString(),
53+
align: TableCellAlign.Right,
54+
},
55+
{
56+
key: 'expirationStatus',
57+
content: <RoflAppInstanceStatusBadge isActive={isActive} />,
58+
align: TableCellAlign.Right,
59+
},
60+
],
61+
}
62+
})
63+
: undefined
4364

4465
return (
4566
<Table
67+
emptyMessage={t('rofl.emptyInstancesList')}
4668
columns={tableColumns}
4769
rows={tableRows}
4870
rowsNumber={limit}

src/app/pages/RoflAppDetailsPage/RoflAppUpdatesCard.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
import { FC } from 'react'
2+
import { useTranslation } from 'react-i18next'
23
import Box from '@mui/material/Box'
34
import { useScreenSize } from '../../hooks/useScreensize'
45
import { NUMBER_OF_ITEMS_ON_SEPARATE_PAGE } from '../../config'
56
import { updatesContainerId } from '../../utils/tabAnchors'
67
import { LinkableCardLayout } from '../../components/LinkableCardLayout'
78
import { RuntimeTransactions } from '../../components/Transactions'
89
import { RuntimeTransactionTypeFilter } from '../../components/Transactions/RuntimeTransactionTypeFilter'
10+
import { getRuntimeRoflUpdatesMethodOptions } from '../..//components/RuntimeTransactionMethod'
911
import { RoflAppDetailsContext, useRoflAppUpdates } from './hooks'
1012

1113
export const RoflAppUpdatesCard: FC<RoflAppDetailsContext> = context => {
14+
const { t } = useTranslation()
1215
const { method, setMethod, scope } = context
13-
1416
const { isMobile } = useScreenSize()
17+
const customOptions = getRuntimeRoflUpdatesMethodOptions(t)
1518

1619
return (
1720
<LinkableCardLayout
@@ -24,13 +27,24 @@ export const RoflAppUpdatesCard: FC<RoflAppDetailsContext> = context => {
2427
}}
2528
>
2629
{!isMobile && (
27-
<RuntimeTransactionTypeFilter layer={scope.layer} value={method} setValue={setMethod} />
30+
<RuntimeTransactionTypeFilter
31+
layer={scope.layer}
32+
value={method}
33+
setValue={setMethod}
34+
customOptions={customOptions}
35+
/>
2836
)}
2937
</Box>
3038
}
3139
>
3240
{isMobile && (
33-
<RuntimeTransactionTypeFilter layer={scope.layer} value={method} setValue={setMethod} expand />
41+
<RuntimeTransactionTypeFilter
42+
layer={scope.layer}
43+
value={method}
44+
setValue={setMethod}
45+
expand
46+
customOptions={customOptions}
47+
/>
3448
)}
3549
<RoflAppUpdates {...context} />
3650
</LinkableCardLayout>
Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { FC } from 'react'
22
import { useTranslation } from 'react-i18next'
3+
import Box from '@mui/material/Box'
34
import Typography from '@mui/material/Typography'
45
import { RoflAppSecrets } from '../../../oasis-nexus/api'
6+
import { COLORS } from '../../../styles/theme/colors'
57

68
type SecretsProps = {
79
secrets: RoflAppSecrets
@@ -10,31 +12,29 @@ type SecretsProps = {
1012
export const Secrets: FC<SecretsProps> = ({ secrets }) => {
1113
const { t } = useTranslation()
1214

13-
if (!secrets || secrets.length === 0) {
15+
if (!secrets || Object.keys(secrets).length === 0) {
1416
return <>{t('common.missing')}</>
1517
}
1618

1719
return (
18-
<table>
20+
<Box>
1921
{Object.keys(secrets).map(key => (
20-
<tr key={key}>
21-
<td>
22-
<Typography
23-
variant="mono"
24-
component="span"
25-
sx={{
26-
wordWrap: 'break-word',
27-
pr: 5,
28-
}}
29-
>
30-
{key}:
31-
</Typography>
32-
</td>
33-
<td>
34-
<Typography variant="mono">{secrets[key]}</Typography>
35-
</td>
36-
</tr>
22+
<Box key={key}>
23+
<Typography
24+
variant="mono"
25+
component="span"
26+
sx={{
27+
wordWrap: 'break-word',
28+
pr: 3,
29+
}}
30+
>
31+
{key}:
32+
</Typography>
33+
<Typography variant="mono" sx={{ color: COLORS.grayMedium }}>
34+
{t('rofl.secretLength', { value: secrets[key].length })}
35+
</Typography>
36+
</Box>
3737
))}
38-
</table>
38+
</Box>
3939
)
4040
}

0 commit comments

Comments
 (0)