Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust Refresh Interval in Assets table #10775

Merged
merged 22 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 27 additions & 20 deletions app/dashboard/e2e/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,24 +504,21 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
(a, b) => backend.ASSET_TYPE_ORDER[a.type] - backend.ASSET_TYPE_ORDER[b.type],
)
const json: remoteBackend.ListDirectoryResponseBody = { assets: filteredAssets }

return json
})
await get(
remoteBackendPaths.LIST_FILES_PATH + '*',
() => ({ files: [] }) satisfies remoteBackend.ListFilesResponseBody,
)
await get(
remoteBackendPaths.LIST_PROJECTS_PATH + '*',
() => ({ projects: [] }) satisfies remoteBackend.ListProjectsResponseBody,
)
await get(
remoteBackendPaths.LIST_SECRETS_PATH + '*',
() => ({ secrets: [] }) satisfies remoteBackend.ListSecretsResponseBody,
)
await get(
remoteBackendPaths.LIST_TAGS_PATH + '*',
() => ({ tags: labels }) satisfies remoteBackend.ListTagsResponseBody,
)
await get(remoteBackendPaths.LIST_FILES_PATH + '*', () => {
return { files: [] } satisfies remoteBackend.ListFilesResponseBody
})
await get(remoteBackendPaths.LIST_PROJECTS_PATH + '*', () => {
return { projects: [] } satisfies remoteBackend.ListProjectsResponseBody
})
await get(remoteBackendPaths.LIST_SECRETS_PATH + '*', () => {
return { secrets: [] } satisfies remoteBackend.ListSecretsResponseBody
})
await get(remoteBackendPaths.LIST_TAGS_PATH + '*', () => {
return { tags: labels } satisfies remoteBackend.ListTagsResponseBody
})
await get(remoteBackendPaths.LIST_USERS_PATH + '*', async (route) => {
if (currentUser != null) {
return { users } satisfies remoteBackend.ListUsersResponseBody
Expand Down Expand Up @@ -584,6 +581,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
interface Body {
readonly parentDirectoryId: backend.DirectoryId
}

const assetId = request.url().match(/[/]assets[/]([^?/]+)/)?.[1]
// eslint-disable-next-line no-restricted-syntax
const asset = assetId != null ? assetMap.get(assetId as backend.AssetId) : null
Expand All @@ -605,7 +603,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
const body: Body = await request.postDataJSON()
const parentId = body.parentDirectoryId
// Can be any asset ID.
const id = backend.DirectoryId(uniqueString.uniqueString())
const id = backend.DirectoryId(`directory-${uniqueString.uniqueString()}`)
const json: backend.CopyAssetResponse = {
asset: {
id,
Expand All @@ -621,6 +619,7 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
await route.fulfill({ json })
}
})

await get(remoteBackendPaths.INVITATION_PATH + '*', async (route) => {
await route.fulfill({
json: { invitations: [] } satisfies backend.ListInvitationsResponseBody,
Expand Down Expand Up @@ -695,15 +694,17 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
const searchParams: SearchParams = Object.fromEntries(
new URL(request.url()).searchParams.entries(),
) as never
const file = createFile(searchParams.file_name)

const file = addFile(searchParams.file_name)

return { path: '', id: file.id, project: null } satisfies backend.FileInfo
})

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

Expand All @@ -721,6 +722,10 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
if (body.description != null) {
object.unsafeMutable(asset).description = body.description
}

if (body.parentDirectoryId != null) {
object.unsafeMutable(asset).parentId = body.parentDirectoryId
}
}
})
await patch(remoteBackendPaths.associateTagPath(GLOB_ASSET_ID), async (_route, request) => {
Expand Down Expand Up @@ -813,7 +818,9 @@ async function mockApiInternal({ page, setupAPI }: MockParams) {
currentUser = { ...currentUser, name: body.username }
}
})
await get(remoteBackendPaths.USERS_ME_PATH + '*', () => currentUser)
await get(remoteBackendPaths.USERS_ME_PATH + '*', () => {
return currentUser
})
await patch(remoteBackendPaths.UPDATE_ORGANIZATION_PATH + '*', async (route, request) => {
// The type of the body sent by this app is statically known.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Expand Down
20 changes: 10 additions & 10 deletions app/dashboard/e2e/copy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test.test('copy', ({ page }) =>
.driveTable.withRows(async (rows) => {
await test.expect(rows).toHaveCount(3)
await test.expect(rows.nth(2)).toBeVisible()
await test.expect(rows.nth(2)).toHaveText(/^New Folder 2 [(]copy[)]/)
await test.expect(rows.nth(2)).toHaveText(/^New Folder 1 [(]copy[)]*/)
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(1))
const childLeft = await actions.getAssetRowLeftPx(rows.nth(2))
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
Expand All @@ -46,7 +46,7 @@ test.test('copy (keyboard)', ({ page }) =>
.driveTable.withRows(async (rows) => {
await test.expect(rows).toHaveCount(3)
await test.expect(rows.nth(2)).toBeVisible()
await test.expect(rows.nth(2)).toHaveText(/^New Folder 2 [(]copy[)]/)
await test.expect(rows.nth(2)).toHaveText(/^New Folder 1 [(]copy[)]*/)
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(1))
const childLeft = await actions.getAssetRowLeftPx(rows.nth(2))
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
Expand All @@ -69,7 +69,7 @@ test.test('move', ({ page }) =>
.driveTable.withRows(async (rows) => {
await test.expect(rows).toHaveCount(2)
await test.expect(rows.nth(1)).toBeVisible()
await test.expect(rows.nth(1)).toHaveText(/^New Folder 2/)
await test.expect(rows.nth(1)).toHaveText(/^New Folder 1/)
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(0))
const childLeft = await actions.getAssetRowLeftPx(rows.nth(1))
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
Expand All @@ -88,7 +88,7 @@ test.test('move (drag)', ({ page }) =>
.driveTable.withRows(async (rows) => {
await test.expect(rows).toHaveCount(2)
await test.expect(rows.nth(1)).toBeVisible()
await test.expect(rows.nth(1)).toHaveText(/^New Folder 2/)
await test.expect(rows.nth(1)).toHaveText(/^New Folder 1/)
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(0))
const childLeft = await actions.getAssetRowLeftPx(rows.nth(1))
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
Expand Down Expand Up @@ -129,7 +129,7 @@ test.test('move (keyboard)', ({ page }) =>
.driveTable.withRows(async (rows) => {
await test.expect(rows).toHaveCount(2)
await test.expect(rows.nth(1)).toBeVisible()
await test.expect(rows.nth(1)).toHaveText(/^New Folder 2/)
await test.expect(rows.nth(1)).toHaveText(/^New Folder 1/)
const parentLeft = await actions.getAssetRowLeftPx(rows.nth(0))
const childLeft = await actions.getAssetRowLeftPx(rows.nth(1))
test.expect(childLeft, 'child is indented further than parent').toBeGreaterThan(parentLeft)
Expand Down Expand Up @@ -164,11 +164,11 @@ test.test('duplicate', ({ page }) =>
.driveTable.rightClickRow(0)
.contextMenu.duplicate()
.driveTable.withRows(async (rows) => {
// Assets: [0: New Project 1 (copy), 1: New Project 1]
// Assets: [0: New Project 1, 1: New Project 1 (copy)]
await test.expect(rows).toHaveCount(2)
await test.expect(actions.locateContextMenus(page)).not.toBeVisible()
await test.expect(rows.nth(0)).toBeVisible()
await test.expect(rows.nth(0)).toHaveText(/^New Project 1 [(]copy[)]/)
await test.expect(rows.nth(1)).toBeVisible()
await test.expect(rows.nth(1)).toHaveText(/^New Project 1 [(]copy[)]/)
}),
)

Expand All @@ -184,7 +184,7 @@ test.test('duplicate (keyboard)', ({ page }) =>
.driveTable.withRows(async (rows) => {
// Assets: [0: New Project 1 (copy), 1: New Project 1]
await test.expect(rows).toHaveCount(2)
await test.expect(rows.nth(0)).toBeVisible()
await test.expect(rows.nth(0)).toHaveText(/^New Project 1 [(]copy[)]/)
await test.expect(rows.nth(1)).toBeVisible()
await test.expect(rows.nth(1)).toHaveText(/^New Project 1 [(]copy[)]/)
}),
)
2 changes: 1 addition & 1 deletion app/dashboard/e2e/driveView.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test.test('drive view', ({ page }) =>
// user that project creation may take a while. Previously opened projects are stopped when the
// new project is created.
.driveTable.withRows(async (rows) => {
await actions.locateStopProjectButton(rows.nth(0)).click()
await actions.locateStopProjectButton(rows.nth(1)).click()
})
// Project context menu
.driveTable.rightClickRow(0)
Expand Down
12 changes: 7 additions & 5 deletions app/dashboard/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import * as inputBindingsModule from '#/configurations/inputBindings'
import AuthProvider, * as authProvider from '#/providers/AuthProvider'
import BackendProvider, { useLocalBackend } from '#/providers/BackendProvider'
import DriveProvider from '#/providers/DriveProvider'
import DevtoolsProvider from '#/providers/EnsoDevtoolsProvider'
import { useHttpClient } from '#/providers/HttpClientProvider'
import InputBindingsProvider from '#/providers/InputBindingsProvider'
import LocalStorageProvider, * as localStorageProvider from '#/providers/LocalStorageProvider'
Expand Down Expand Up @@ -91,10 +90,11 @@ import * as appBaseUrl from '#/utilities/appBaseUrl'
import * as eventModule from '#/utilities/event'
import LocalStorage from '#/utilities/LocalStorage'
import * as object from '#/utilities/object'
import { Path } from '#/utilities/path'

import { useInitAuthService } from '#/authentication/service'
import { InvitedToOrganizationModal } from '#/modals/InvitedToOrganizationModal'
import { Path } from '#/utilities/path'
import { FeatureFlagsProvider } from '#/providers/FeatureFlagsProvider'

// ============================
// === Global configuration ===
Expand Down Expand Up @@ -492,7 +492,7 @@ function AppRouter(props: AppRouterProps) {
)

return (
<DevtoolsProvider>
<FeatureFlagsProvider>
<RouterProvider navigate={navigate}>
<SessionProvider
saveAccessToken={authService?.cognito.saveAccessToken.bind(authService.cognito) ?? null}
Expand All @@ -517,7 +517,9 @@ function AppRouter(props: AppRouterProps) {
{routes}
{detect.IS_DEV_MODE && (
<suspense.Suspense>
<devtools.EnsoDevtools />
<errorBoundary.ErrorBoundary>
<devtools.EnsoDevtools />
</errorBoundary.ErrorBoundary>
</suspense.Suspense>
)}
</errorBoundary.ErrorBoundary>
Expand All @@ -527,7 +529,7 @@ function AppRouter(props: AppRouterProps) {
</BackendProvider>
</SessionProvider>
</RouterProvider>
</DevtoolsProvider>
</FeatureFlagsProvider>
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,76 @@ import * as modalProvider from '#/providers/ModalProvider'

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

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

const PLACEHOLDER = <div />

/**
* Props passed to the render function of a {@link DialogTrigger}.
*/
export interface DialogTriggerRenderProps {
readonly isOpened: boolean
}
/**
* Props for a {@link DialogTrigger}.
*/
export interface DialogTriggerProps extends types.DialogTriggerProps {}
export interface DialogTriggerProps extends Omit<aria.DialogTriggerProps, 'children'> {
/**
* The trigger element.
*/
readonly children: [
React.ReactElement,
React.ReactElement | ((props: DialogTriggerRenderProps) => React.ReactElement),
]
}

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

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

const onOpenChangeInternal = React.useCallback(
(isOpened: boolean) => {
if (isOpened) {
(opened: boolean) => {
if (opened) {
// We're using a placeholder here just to let the rest of the code know that the modal
// is open.
setModal(PLACEHOLDER)
} else {
unsetModal()
}

onOpenChange?.(isOpened)
setIsOpened(opened)
onOpenChange?.(opened)
},
[setModal, unsetModal, onOpenChange],
)

const renderProps = {
isOpened,
} satisfies DialogTriggerRenderProps

const [trigger, dialog] = children

return (
<aria.DialogTrigger onOpenChange={onOpenChangeInternal} {...triggerProps}>
{children}
{trigger}

{/* We're using AnimatePresence here to animate the dialog in and out. */}
<AnimatePresence>
{isOpened && (
<motion.div
style={{ display: 'none' }}
initial={{ opacity: 1 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 1 }}
>
{typeof dialog === 'function' ? dialog(renderProps) : dialog}
</motion.div>
)}
</AnimatePresence>
</aria.DialogTrigger>
)
}
3 changes: 0 additions & 3 deletions app/dashboard/src/components/AriaComponents/Dialog/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,3 @@ export interface DialogProps extends aria.DialogProps {
readonly modalProps?: Pick<aria.ModalOverlayProps, 'className' | 'defaultOpen' | 'isOpen'>
readonly testId?: string
}

/** The props for the DialogTrigger component. */
export interface DialogTriggerProps extends aria.DialogTriggerProps {}
Loading
Loading