-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* wip - showing application * wip - show application * wip - show application global state * wip - test * fix test names * more tests * test global state * wip - boxes * wip - display boxes, the names aren't showing * Show boxes table * add tests for boxes * refactor boxes a bit * view application box page * small fix * PR feedback * update text * evict application result from cache * Switch to show dialogs for boxes * PR feedback * PR feedback
- Loading branch information
1 parent
6305ace
commit 1da3e2a
Showing
27 changed files
with
894 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
src/features/applications/components/application-box-details-dialog.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { cn } from '@/features/common/utils' | ||
import { applicationBoxNameLabel, applicationBoxValueLabel } from './labels' | ||
import { useMemo } from 'react' | ||
import { DescriptionList } from '@/features/common/components/description-list' | ||
import { ApplicationBox } from '../models' | ||
import { ApplicationId } from '../data/types' | ||
import { RenderLoadable } from '@/features/common/components/render-loadable' | ||
import { useLoadableApplicationBox } from '../data/application-boxes' | ||
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from '@/features/common/components/dialog' | ||
|
||
type Props = { applicationId: ApplicationId; boxName: string } | ||
|
||
const dialogTitle = 'Application Box' | ||
export function ApplicationBoxDetailsDialog({ applicationId, boxName }: Props) { | ||
return ( | ||
<Dialog> | ||
<DialogTrigger> | ||
<label className={cn('text-primary underline')}>{boxName}</label> | ||
</DialogTrigger> | ||
<DialogContent className="w-[800px]"> | ||
<DialogHeader> | ||
<h1 className={cn('text-2xl text-primary font-bold')}>{dialogTitle}</h1> | ||
</DialogHeader> | ||
<InternalDialogContent applicationId={applicationId} boxName={boxName} /> | ||
</DialogContent> | ||
</Dialog> | ||
) | ||
} | ||
|
||
function InternalDialogContent({ applicationId, boxName }: Props) { | ||
const loadableApplicationBox = useLoadableApplicationBox(applicationId, boxName) | ||
|
||
return ( | ||
<RenderLoadable loadable={loadableApplicationBox}> | ||
{(applicationBox) => <ApplicationBoxDetails applicationBox={applicationBox} />} | ||
</RenderLoadable> | ||
) | ||
} | ||
|
||
function ApplicationBoxDetails({ applicationBox }: { applicationBox: ApplicationBox }) { | ||
const items = useMemo( | ||
() => [ | ||
{ | ||
dt: applicationBoxNameLabel, | ||
dd: applicationBox.name, | ||
}, | ||
{ | ||
dt: applicationBoxValueLabel, | ||
dd: ( | ||
<div className="grid"> | ||
<div className="overflow-y-auto break-words"> {applicationBox.value}</div> | ||
</div> | ||
), | ||
}, | ||
], | ||
[applicationBox.name, applicationBox.value] | ||
) | ||
|
||
return <DescriptionList items={items} /> | ||
} |
29 changes: 29 additions & 0 deletions
29
src/features/applications/components/application-boxes.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { LazyLoadDataTable } from '@/features/common/components/lazy-load-data-table' | ||
import { useFetchNextApplicationBoxPage } from '../data/application-boxes' | ||
import { ApplicationId } from '../data/types' | ||
import { ColumnDef } from '@tanstack/react-table' | ||
import { ApplicationBoxSummary } from '../models' | ||
import { useMemo } from 'react' | ||
import { ApplicationBoxDetailsDialog } from './application-box-details-dialog' | ||
|
||
type Props = { | ||
applicationId: ApplicationId | ||
} | ||
|
||
export function ApplicationBoxes({ applicationId }: Props) { | ||
const fetchNextPage = useFetchNextApplicationBoxPage(applicationId) | ||
const tableColumns = useMemo(() => createTableColumns(applicationId), [applicationId]) | ||
|
||
return <LazyLoadDataTable columns={tableColumns} fetchNextPage={fetchNextPage} /> | ||
} | ||
|
||
const createTableColumns = (applicationId: ApplicationId): ColumnDef<ApplicationBoxSummary>[] => [ | ||
{ | ||
header: 'Name', | ||
accessorKey: 'name', | ||
cell: (context) => { | ||
const boxName = context.getValue<string>() | ||
return <ApplicationBoxDetailsDialog applicationId={applicationId} boxName={boxName} /> | ||
}, | ||
}, | ||
] |
111 changes: 111 additions & 0 deletions
111
src/features/applications/components/application-details.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { Card, CardContent } from '@/features/common/components/card' | ||
import { DescriptionList } from '@/features/common/components/description-list' | ||
import { cn } from '@/features/common/utils' | ||
import { Application } from '../models' | ||
import { useMemo } from 'react' | ||
import { | ||
applicationAccountLabel, | ||
applicationApprovalProgramLabel, | ||
applicationApprovalProgramTabsListAriaLabel, | ||
applicationBoxesLabel, | ||
applicationClearStateProgramLabel, | ||
applicationClearStateProgramTabsListAriaLabel, | ||
applicationCreatorAccountLabel, | ||
applicationDetailsLabel, | ||
applicationGlobalStateByteLabel, | ||
applicationGlobalStateLabel, | ||
applicationGlobalStateUintLabel, | ||
applicationIdLabel, | ||
applicationLocalStateByteLabel, | ||
applicationLocalStateUintLabel, | ||
} from './labels' | ||
import { isDefined } from '@/utils/is-defined' | ||
import { ApplicationProgram } from './application-program' | ||
import { ApplicationGlobalStateTable } from './application-global-state-table' | ||
import { ApplicationBoxes } from './application-boxes' | ||
|
||
type Props = { | ||
application: Application | ||
} | ||
|
||
export function ApplicationDetails({ application }: Props) { | ||
const applicationItems = useMemo( | ||
() => [ | ||
{ | ||
dt: applicationIdLabel, | ||
dd: application.id, | ||
}, | ||
{ | ||
dt: applicationCreatorAccountLabel, | ||
dd: application.creator, | ||
}, | ||
{ | ||
dt: applicationAccountLabel, | ||
dd: application.account, | ||
}, | ||
application.globalStateSchema | ||
? { | ||
dt: applicationGlobalStateByteLabel, | ||
dd: application.globalStateSchema.numByteSlice, | ||
} | ||
: undefined, | ||
application.localStateSchema | ||
? { | ||
dt: applicationLocalStateByteLabel, | ||
dd: application.localStateSchema.numByteSlice, | ||
} | ||
: undefined, | ||
application.globalStateSchema | ||
? { | ||
dt: applicationGlobalStateUintLabel, | ||
dd: application.globalStateSchema.numUint, | ||
} | ||
: undefined, | ||
application.localStateSchema | ||
? { | ||
dt: applicationLocalStateUintLabel, | ||
dd: application.localStateSchema.numUint, | ||
} | ||
: undefined, | ||
], | ||
[application.id, application.creator, application.account, application.globalStateSchema, application.localStateSchema] | ||
).filter(isDefined) | ||
|
||
return ( | ||
<div className={cn('space-y-6 pt-7')}> | ||
<Card aria-label={applicationDetailsLabel} className={cn('p-4')}> | ||
<CardContent className={cn('text-sm space-y-2')}> | ||
<h1 className={cn('text-2xl text-primary font-bold')}>{applicationDetailsLabel}</h1> | ||
<DescriptionList items={applicationItems} /> | ||
</CardContent> | ||
</Card> | ||
<Card aria-label={applicationApprovalProgramLabel} className={cn('p-4')}> | ||
<CardContent className={cn('text-sm space-y-2')}> | ||
<h1 className={cn('text-2xl text-primary font-bold')}>{applicationApprovalProgramLabel}</h1> | ||
<ApplicationProgram tabsListAriaLabel={applicationApprovalProgramTabsListAriaLabel} base64Program={application.approvalProgram} /> | ||
</CardContent> | ||
</Card> | ||
<Card aria-label={applicationClearStateProgramLabel} className={cn('p-4')}> | ||
<CardContent className={cn('text-sm space-y-2')}> | ||
<h1 className={cn('text-2xl text-primary font-bold')}>{applicationClearStateProgramLabel}</h1> | ||
<ApplicationProgram | ||
tabsListAriaLabel={applicationClearStateProgramTabsListAriaLabel} | ||
base64Program={application.clearStateProgram} | ||
/> | ||
</CardContent> | ||
</Card> | ||
<Card aria-label={applicationGlobalStateLabel} className={cn('p-4')}> | ||
<CardContent className={cn('text-sm space-y-2')}> | ||
<h1 className={cn('text-2xl text-primary font-bold')}>{applicationGlobalStateLabel}</h1> | ||
<ApplicationGlobalStateTable application={application} /> | ||
</CardContent> | ||
</Card> | ||
<Card aria-label={applicationBoxesLabel} className={cn('p-4')}> | ||
<CardContent className={cn('text-sm space-y-2')}> | ||
<h1 className={cn('text-2xl text-primary font-bold')}>{applicationBoxesLabel}</h1> | ||
<ApplicationBoxes applicationId={application.id} /> | ||
</CardContent> | ||
</Card> | ||
</div> | ||
) | ||
} |
31 changes: 31 additions & 0 deletions
31
src/features/applications/components/application-global-state-table.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { ColumnDef } from '@tanstack/react-table' | ||
import { Application, ApplicationGlobalStateValue } from '../models' | ||
import { DataTable } from '@/features/common/components/data-table' | ||
import { useMemo } from 'react' | ||
|
||
type Props = { | ||
application: Application | ||
} | ||
|
||
export function ApplicationGlobalStateTable({ application }: Props) { | ||
const entries = useMemo(() => Array.from(application.globalState.entries()), [application]) | ||
return <DataTable columns={tableColumns} data={entries} /> | ||
} | ||
|
||
const tableColumns: ColumnDef<[string, ApplicationGlobalStateValue]>[] = [ | ||
{ | ||
header: 'Key', | ||
accessorFn: (item) => item, | ||
cell: (c) => c.getValue<[string, ApplicationGlobalStateValue]>()[0], | ||
}, | ||
{ | ||
header: 'Type', | ||
accessorFn: (item) => item, | ||
cell: (c) => c.getValue<[string, ApplicationGlobalStateValue]>()[1].type, | ||
}, | ||
{ | ||
header: 'Value', | ||
accessorFn: (item) => item, | ||
cell: (c) => c.getValue<[string, ApplicationGlobalStateValue]>()[1].value, | ||
}, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { cn } from '@/features/common/utils' | ||
import { TemplatedNavLink } from '@/features/routing/components/templated-nav-link/templated-nav-link' | ||
import { Urls } from '@/routes/urls' | ||
import { PropsWithChildren } from 'react' | ||
import { ApplicationId } from '../data/types' | ||
|
||
type Props = PropsWithChildren<{ | ||
applicationId: ApplicationId | ||
className?: string | ||
}> | ||
|
||
export function ApplicationLink({ applicationId, className, children }: Props) { | ||
return ( | ||
<TemplatedNavLink | ||
className={cn(!children && 'text-primary underline', className)} | ||
urlTemplate={Urls.Explore.Application.ById} | ||
urlParams={{ applicationId: applicationId.toString() }} | ||
> | ||
{children ? children : applicationId} | ||
</TemplatedNavLink> | ||
) | ||
} |
37 changes: 37 additions & 0 deletions
37
src/features/applications/components/application-program.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { describe, expect, it, vi } from 'vitest' | ||
import { getByRole, render, waitFor } from '../../../tests/testing-library' | ||
import { ApplicationProgram, base64ProgramTabLabel, tealProgramTabLabel } from './application-program' | ||
import { algod } from '@/features/common/data' | ||
import { executeComponentTest } from '@/tests/test-component' | ||
|
||
describe('application-program', () => { | ||
describe('when rendering an application program', () => { | ||
const tabListName = 'test' | ||
const program = 'CIEBQw==' | ||
const teal = '\n#pragma version 8\nint 1\nreturn\n' | ||
|
||
it('should be rendered with the correct data', () => { | ||
vi.mocked(algod.disassemble('').do).mockImplementation(() => Promise.resolve({ result: teal })) | ||
|
||
return executeComponentTest( | ||
() => { | ||
return render(<ApplicationProgram tabsListAriaLabel={tabListName} base64Program={program} />) | ||
}, | ||
async (component, user) => { | ||
const tabList = component.getByRole('tablist', { name: tabListName }) | ||
expect(tabList).toBeTruthy() | ||
expect(tabList.children.length).toBe(2) | ||
|
||
const base64Tab = component.getByRole('tabpanel', { name: base64ProgramTabLabel }) | ||
expect(base64Tab.getAttribute('data-state'), 'Base64 tab should be active').toBe('active') | ||
expect(base64Tab.textContent).toBe(program) | ||
|
||
await user.click(getByRole(tabList, 'tab', { name: tealProgramTabLabel })) | ||
const tealTab = component.getByRole('tabpanel', { name: tealProgramTabLabel }) | ||
await waitFor(() => expect(tealTab.getAttribute('data-state'), 'Teal tab should be active').toBe('active')) | ||
expect(tealTab.textContent).toBe(teal) | ||
} | ||
) | ||
}) | ||
}) | ||
}) |
45 changes: 45 additions & 0 deletions
45
src/features/applications/components/application-program.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { RenderLoadable } from '@/features/common/components/render-loadable' | ||
import { OverflowAutoTabsContent, Tabs, TabsList, TabsTrigger } from '@/features/common/components/tabs' | ||
import { cn } from '@/features/common/utils' | ||
import { useProgramTeal } from '../data/program-teal' | ||
|
||
const base64ProgramTabId = 'base64' | ||
const tealProgramTabId = 'teal' | ||
export const base64ProgramTabLabel = 'Base64' | ||
export const tealProgramTabLabel = 'Teal' | ||
|
||
type Props = { | ||
tabsListAriaLabel: string | ||
base64Program: string | ||
} | ||
export function ApplicationProgram({ tabsListAriaLabel, base64Program }: Props) { | ||
const [tealLoadable, fetchTeal] = useProgramTeal(base64Program) | ||
|
||
return ( | ||
<Tabs | ||
defaultValue={base64ProgramTabId} | ||
onValueChange={(activeTab) => { | ||
if (activeTab === tealProgramTabId) { | ||
fetchTeal() | ||
} | ||
}} | ||
> | ||
<TabsList aria-label={tabsListAriaLabel}> | ||
<TabsTrigger className={cn('data-[state=active]:border-primary data-[state=active]:border-b-2 w-32')} value={base64ProgramTabId}> | ||
{base64ProgramTabLabel} | ||
</TabsTrigger> | ||
<TabsTrigger className={cn('data-[state=active]:border-primary data-[state=active]:border-b-2 w-32')} value={tealProgramTabId}> | ||
{tealProgramTabLabel} | ||
</TabsTrigger> | ||
</TabsList> | ||
<OverflowAutoTabsContent value={base64ProgramTabId}> | ||
<pre>{base64Program}</pre> | ||
</OverflowAutoTabsContent> | ||
<OverflowAutoTabsContent value={tealProgramTabId}> | ||
<div className="h-96"> | ||
<RenderLoadable loadable={tealLoadable}>{(teal) => <pre>{teal}</pre>}</RenderLoadable> | ||
</div> | ||
</OverflowAutoTabsContent> | ||
</Tabs> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export const applicationDetailsLabel = 'Application Details' | ||
export const applicationIdLabel = 'Application ID' | ||
export const applicationCreatorAccountLabel = 'Creator' | ||
export const applicationAccountLabel = 'Account' | ||
export const applicationGlobalStateByteLabel = 'Global State Byte' | ||
export const applicationGlobalStateUintLabel = 'Global State Uint' | ||
export const applicationLocalStateByteLabel = 'Local State Byte' | ||
export const applicationLocalStateUintLabel = 'Local State Uint' | ||
|
||
export const applicationProgramsLabel = 'Application Programs' | ||
export const applicationApprovalProgramLabel = 'Approval Program' | ||
export const applicationClearStateProgramLabel = 'Clear State Program' | ||
export const applicationApprovalProgramTabsListAriaLabel = 'View Application Approval Program Tabs' | ||
export const applicationClearStateProgramTabsListAriaLabel = 'View Application Clear State Program Tabs' | ||
|
||
export const applicationGlobalStateLabel = 'Global State' | ||
|
||
export const applicationBoxesLabel = 'Boxes' | ||
|
||
export const applicationBoxNameLabel = 'Box Name' | ||
export const applicationBoxValueLabel = 'Box Value' |
Oops, something went wrong.