Skip to content

Commit 373fc1a

Browse files
MrFlashAccountjdunkerley
authored andcommitted
Adjust Refresh Interval in Assets table (#10775)
(cherry picked from commit 77183e5)
1 parent fd8804e commit 373fc1a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1689
-1838
lines changed

app/dashboard/e2e/api.ts

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -504,24 +504,21 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
504504
(a, b) => backend.ASSET_TYPE_ORDER[a.type] - backend.ASSET_TYPE_ORDER[b.type],
505505
)
506506
const json: remoteBackend.ListDirectoryResponseBody = { assets: filteredAssets }
507+
507508
return json
508509
})
509-
await get(
510-
remoteBackendPaths.LIST_FILES_PATH + '*',
511-
() => ({ files: [] }) satisfies remoteBackend.ListFilesResponseBody,
512-
)
513-
await get(
514-
remoteBackendPaths.LIST_PROJECTS_PATH + '*',
515-
() => ({ projects: [] }) satisfies remoteBackend.ListProjectsResponseBody,
516-
)
517-
await get(
518-
remoteBackendPaths.LIST_SECRETS_PATH + '*',
519-
() => ({ secrets: [] }) satisfies remoteBackend.ListSecretsResponseBody,
520-
)
521-
await get(
522-
remoteBackendPaths.LIST_TAGS_PATH + '*',
523-
() => ({ tags: labels }) satisfies remoteBackend.ListTagsResponseBody,
524-
)
510+
await get(remoteBackendPaths.LIST_FILES_PATH + '*', () => {
511+
return { files: [] } satisfies remoteBackend.ListFilesResponseBody
512+
})
513+
await get(remoteBackendPaths.LIST_PROJECTS_PATH + '*', () => {
514+
return { projects: [] } satisfies remoteBackend.ListProjectsResponseBody
515+
})
516+
await get(remoteBackendPaths.LIST_SECRETS_PATH + '*', () => {
517+
return { secrets: [] } satisfies remoteBackend.ListSecretsResponseBody
518+
})
519+
await get(remoteBackendPaths.LIST_TAGS_PATH + '*', () => {
520+
return { tags: labels } satisfies remoteBackend.ListTagsResponseBody
521+
})
525522
await get(remoteBackendPaths.LIST_USERS_PATH + '*', async (route) => {
526523
if (currentUser != null) {
527524
return { users } satisfies remoteBackend.ListUsersResponseBody
@@ -584,6 +581,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
584581
interface Body {
585582
readonly parentDirectoryId: backend.DirectoryId
586583
}
584+
587585
const assetId = request.url().match(/[/]assets[/]([^?/]+)/)?.[1]
588586
// eslint-disable-next-line no-restricted-syntax
589587
const asset = assetId != null ? assetMap.get(assetId as backend.AssetId) : null
@@ -605,7 +603,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
605603
const body: Body = await request.postDataJSON()
606604
const parentId = body.parentDirectoryId
607605
// Can be any asset ID.
608-
const id = backend.DirectoryId(uniqueString.uniqueString())
606+
const id = backend.DirectoryId(`directory-${uniqueString.uniqueString()}`)
609607
const json: backend.CopyAssetResponse = {
610608
asset: {
611609
id,
@@ -621,6 +619,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
621619
await route.fulfill({ json })
622620
}
623621
})
622+
624623
await get(remoteBackendPaths.INVITATION_PATH + '*', async (route) => {
625624
await route.fulfill({
626625
json: { invitations: [] } satisfies backend.ListInvitationsResponseBody,
@@ -695,15 +694,17 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
695694
const searchParams: SearchParams = Object.fromEntries(
696695
new URL(request.url()).searchParams.entries(),
697696
) as never
698-
const file = createFile(searchParams.file_name)
697+
698+
const file = addFile(searchParams.file_name)
699+
699700
return { path: '', id: file.id, project: null } satisfies backend.FileInfo
700701
})
701702

702703
await post(remoteBackendPaths.CREATE_SECRET_PATH + '*', async (_route, request) => {
703704
// The type of the body sent by this app is statically known.
704705
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
705706
const body: backend.CreateSecretRequestBody = await request.postDataJSON()
706-
const secret = createSecret(body.name)
707+
const secret = addSecret(body.name)
707708
return secret.id
708709
})
709710

@@ -721,6 +722,10 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
721722
if (body.description != null) {
722723
object.unsafeMutable(asset).description = body.description
723724
}
725+
726+
if (body.parentDirectoryId != null) {
727+
object.unsafeMutable(asset).parentId = body.parentDirectoryId
728+
}
724729
}
725730
})
726731
await patch(remoteBackendPaths.associateTagPath(GLOB_ASSET_ID), async (_route, request) => {
@@ -813,7 +818,9 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
813818
currentUser = { ...currentUser, name: body.username }
814819
}
815820
})
816-
await get(remoteBackendPaths.USERS_ME_PATH + '*', () => currentUser)
821+
await get(remoteBackendPaths.USERS_ME_PATH + '*', () => {
822+
return currentUser
823+
})
817824
await patch(remoteBackendPaths.UPDATE_ORGANIZATION_PATH + '*', async (route, request) => {
818825
// The type of the body sent by this app is statically known.
819826
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment

app/dashboard/e2e/copy.spec.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ test.test('copy', ({ page }) =>
2323
.driveTable.withRows(async (rows) => {
2424
await test.expect(rows).toHaveCount(3)
2525
await test.expect(rows.nth(2)).toBeVisible()
26-
await test.expect(rows.nth(2)).toHaveText(/^New Folder 2 [(]copy[)]/)
26+
await test.expect(rows.nth(2)).toHaveText(/^New Folder 1 [(]copy[)]*/)
2727
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(1))
2828
const childLeft = await actions.getAssetRowLeftPx(rows.nth(2))
2929
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
@@ -46,7 +46,7 @@ test.test('copy (keyboard)', ({ page }) =>
4646
.driveTable.withRows(async (rows) => {
4747
await test.expect(rows).toHaveCount(3)
4848
await test.expect(rows.nth(2)).toBeVisible()
49-
await test.expect(rows.nth(2)).toHaveText(/^New Folder 2 [(]copy[)]/)
49+
await test.expect(rows.nth(2)).toHaveText(/^New Folder 1 [(]copy[)]*/)
5050
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(1))
5151
const childLeft = await actions.getAssetRowLeftPx(rows.nth(2))
5252
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
@@ -69,7 +69,7 @@ test.test('move', ({ page }) =>
6969
.driveTable.withRows(async (rows) => {
7070
await test.expect(rows).toHaveCount(2)
7171
await test.expect(rows.nth(1)).toBeVisible()
72-
await test.expect(rows.nth(1)).toHaveText(/^New Folder 2/)
72+
await test.expect(rows.nth(1)).toHaveText(/^New Folder 1/)
7373
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(0))
7474
const childLeft = await actions.getAssetRowLeftPx(rows.nth(1))
7575
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
@@ -88,7 +88,7 @@ test.test('move (drag)', ({ page }) =>
8888
.driveTable.withRows(async (rows) => {
8989
await test.expect(rows).toHaveCount(2)
9090
await test.expect(rows.nth(1)).toBeVisible()
91-
await test.expect(rows.nth(1)).toHaveText(/^New Folder 2/)
91+
await test.expect(rows.nth(1)).toHaveText(/^New Folder 1/)
9292
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(0))
9393
const childLeft = await actions.getAssetRowLeftPx(rows.nth(1))
9494
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
@@ -129,7 +129,7 @@ test.test('move (keyboard)', ({ page }) =>
129129
.driveTable.withRows(async (rows) => {
130130
await test.expect(rows).toHaveCount(2)
131131
await test.expect(rows.nth(1)).toBeVisible()
132-
await test.expect(rows.nth(1)).toHaveText(/^New Folder 2/)
132+
await test.expect(rows.nth(1)).toHaveText(/^New Folder 1/)
133133
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(0))
134134
const childLeft = await actions.getAssetRowLeftPx(rows.nth(1))
135135
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
@@ -164,11 +164,11 @@ test.test('duplicate', ({ page }) =>
164164
.driveTable.rightClickRow(0)
165165
.contextMenu.duplicate()
166166
.driveTable.withRows(async (rows) => {
167-
// Assets: [0: New Project 1 (copy), 1: New Project 1]
167+
// Assets: [0: New Project 1, 1: New Project 1 (copy)]
168168
await test.expect(rows).toHaveCount(2)
169169
await test.expect(actions.locateContextMenus(page)).not.toBeVisible()
170-
await test.expect(rows.nth(0)).toBeVisible()
171-
await test.expect(rows.nth(0)).toHaveText(/^New Project 1 [(]copy[)]/)
170+
await test.expect(rows.nth(1)).toBeVisible()
171+
await test.expect(rows.nth(1)).toHaveText(/^New Project 1 [(]copy[)]/)
172172
}),
173173
)
174174

@@ -184,7 +184,7 @@ test.test('duplicate (keyboard)', ({ page }) =>
184184
.driveTable.withRows(async (rows) => {
185185
// Assets: [0: New Project 1 (copy), 1: New Project 1]
186186
await test.expect(rows).toHaveCount(2)
187-
await test.expect(rows.nth(0)).toBeVisible()
188-
await test.expect(rows.nth(0)).toHaveText(/^New Project 1 [(]copy[)]/)
187+
await test.expect(rows.nth(1)).toBeVisible()
188+
await test.expect(rows.nth(1)).toHaveText(/^New Project 1 [(]copy[)]/)
189189
}),
190190
)

app/dashboard/e2e/driveView.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ test.test('drive view', ({ page }) =>
3333
// user that project creation may take a while. Previously opened projects are stopped when the
3434
// new project is created.
3535
.driveTable.withRows(async (rows) => {
36-
await actions.locateStopProjectButton(rows.nth(0)).click()
36+
await actions.locateStopProjectButton(rows.nth(1)).click()
3737
})
3838
// Project context menu
3939
.driveTable.rightClickRow(0)

app/dashboard/src/App.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ import * as inputBindingsModule from '#/configurations/inputBindings'
4949
import AuthProvider, * as authProvider from '#/providers/AuthProvider'
5050
import BackendProvider, { useLocalBackend } from '#/providers/BackendProvider'
5151
import DriveProvider from '#/providers/DriveProvider'
52-
import DevtoolsProvider from '#/providers/EnsoDevtoolsProvider'
5352
import { useHttpClient } from '#/providers/HttpClientProvider'
5453
import InputBindingsProvider from '#/providers/InputBindingsProvider'
5554
import LocalStorageProvider, * as localStorageProvider from '#/providers/LocalStorageProvider'
@@ -91,10 +90,11 @@ import * as appBaseUrl from '#/utilities/appBaseUrl'
9190
import * as eventModule from '#/utilities/event'
9291
import LocalStorage from '#/utilities/LocalStorage'
9392
import * as object from '#/utilities/object'
93+
import { Path } from '#/utilities/path'
9494

9595
import { useInitAuthService } from '#/authentication/service'
9696
import { InvitedToOrganizationModal } from '#/modals/InvitedToOrganizationModal'
97-
import { Path } from '#/utilities/path'
97+
import { FeatureFlagsProvider } from '#/providers/FeatureFlagsProvider'
9898

9999
// ============================
100100
// === Global configuration ===
@@ -492,7 +492,7 @@ function AppRouter(props: AppRouterProps) {
492492
)
493493

494494
return (
495-
<DevtoolsProvider>
495+
<FeatureFlagsProvider>
496496
<RouterProvider navigate={navigate}>
497497
<SessionProvider
498498
saveAccessToken={authService?.cognito.saveAccessToken.bind(authService.cognito) ?? null}
@@ -517,7 +517,9 @@ function AppRouter(props: AppRouterProps) {
517517
{routes}
518518
{detect.IS_DEV_MODE && (
519519
<suspense.Suspense>
520-
<devtools.EnsoDevtools />
520+
<errorBoundary.ErrorBoundary>
521+
<devtools.EnsoDevtools />
522+
</errorBoundary.ErrorBoundary>
521523
</suspense.Suspense>
522524
)}
523525
</errorBoundary.ErrorBoundary>
@@ -527,7 +529,7 @@ function AppRouter(props: AppRouterProps) {
527529
</BackendProvider>
528530
</SessionProvider>
529531
</RouterProvider>
530-
</DevtoolsProvider>
532+
</FeatureFlagsProvider>
531533
)
532534
}
533535

app/dashboard/src/components/AriaComponents/Dialog/DialogTrigger.tsx

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,76 @@ import * as modalProvider from '#/providers/ModalProvider'
55

66
import * as aria from '#/components/aria'
77

8-
import type * as types from './types'
8+
import { AnimatePresence, motion } from 'framer-motion'
99

1010
const PLACEHOLDER = <div />
1111

12+
/**
13+
* Props passed to the render function of a {@link DialogTrigger}.
14+
*/
15+
export interface DialogTriggerRenderProps {
16+
readonly isOpened: boolean
17+
}
1218
/**
1319
* Props for a {@link DialogTrigger}.
1420
*/
15-
export interface DialogTriggerProps extends types.DialogTriggerProps {}
21+
export interface DialogTriggerProps extends Omit<aria.DialogTriggerProps, 'children'> {
22+
/**
23+
* The trigger element.
24+
*/
25+
readonly children: [
26+
React.ReactElement,
27+
React.ReactElement | ((props: DialogTriggerRenderProps) => React.ReactElement),
28+
]
29+
}
1630

1731
/** A DialogTrigger opens a dialog when a trigger element is pressed. */
1832
export function DialogTrigger(props: DialogTriggerProps) {
1933
const { children, onOpenChange, ...triggerProps } = props
2034

35+
const [isOpened, setIsOpened] = React.useState(false)
2136
const { setModal, unsetModal } = modalProvider.useSetModal()
2237

2338
const onOpenChangeInternal = React.useCallback(
24-
(isOpened: boolean) => {
25-
if (isOpened) {
39+
(opened: boolean) => {
40+
if (opened) {
2641
// We're using a placeholder here just to let the rest of the code know that the modal
2742
// is open.
2843
setModal(PLACEHOLDER)
2944
} else {
3045
unsetModal()
3146
}
3247

33-
onOpenChange?.(isOpened)
48+
setIsOpened(opened)
49+
onOpenChange?.(opened)
3450
},
3551
[setModal, unsetModal, onOpenChange],
3652
)
3753

54+
const renderProps = {
55+
isOpened,
56+
} satisfies DialogTriggerRenderProps
57+
58+
const [trigger, dialog] = children
59+
3860
return (
3961
<aria.DialogTrigger onOpenChange={onOpenChangeInternal} {...triggerProps}>
40-
{children}
62+
{trigger}
63+
64+
{/* We're using AnimatePresence here to animate the dialog in and out. */}
65+
<AnimatePresence>
66+
{isOpened && (
67+
<motion.div
68+
style={{ display: 'none' }}
69+
initial={{ opacity: 1 }}
70+
animate={{ opacity: 1 }}
71+
exit={{ opacity: 0 }}
72+
transition={{ duration: 1 }}
73+
>
74+
{typeof dialog === 'function' ? dialog(renderProps) : dialog}
75+
</motion.div>
76+
)}
77+
</AnimatePresence>
4178
</aria.DialogTrigger>
4279
)
4380
}

app/dashboard/src/components/AriaComponents/Dialog/types.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,3 @@ export interface DialogProps extends aria.DialogProps {
1010
readonly modalProps?: Pick<aria.ModalOverlayProps, 'className' | 'defaultOpen' | 'isOpen'>
1111
readonly testId?: string
1212
}
13-
14-
/** The props for the DialogTrigger component. */
15-
export interface DialogTriggerProps extends aria.DialogTriggerProps {}

0 commit comments

Comments
 (0)