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

feat: add activate workspace button into detail page #328

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
77 changes: 77 additions & 0 deletions src/features/workspace/components/workspace-activate-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { useMutationActivateWorkspace } from '@/hooks/use-mutation-activate-workspace'
import { useQueryActiveWorkspaceName } from '@/hooks/use-query-active-workspace-name'
import {
Button,
Tooltip,
TooltipInfoButton,
TooltipTrigger,
} from '@stacklok/ui-kit'
import { Check } from '@untitled-ui/icons-react'

function getTooltipText({
isActivated,
isArchived,
}: {
isArchived: boolean
isActivated: boolean
}) {
if (isArchived) {
return 'Cannot activate an archived workspace'
}

if (isActivated) {
return 'Workspace already active'
}

return null
}

function TooltipActivateBtn({
isActivated,
isArchived,
}: {
isActivated: boolean
isArchived: boolean
}) {
const text = getTooltipText({ isActivated, isArchived })

if (!text) return null
return (
<TooltipTrigger delay={0}>
<TooltipInfoButton aria-label="Context active button" />
<Tooltip>{text}</Tooltip>
</TooltipTrigger>
)
}

export function WorkspaceActivateButton({
workspaceName,
isArchived,
}: {
workspaceName: string
isArchived: boolean | undefined
}) {
const { data: activeWorkspaceName, isPending: isPendingWsName } =
useQueryActiveWorkspaceName()
const { mutateAsync: activateWorkspace, isPending: isPendingMutation } =
useMutationActivateWorkspace()
const isActivated = activeWorkspaceName === workspaceName
const isPending = isPendingWsName || isPendingMutation

return (
<div
className="flex items-center justify-end gap-2"
data-testid="workspace-activate"
>
<Button
isDisabled={isActivated || isArchived}
isPending={isPending}
type="submit"
onPress={() => activateWorkspace({ body: { name: workspaceName } })}
>
<Check /> Activate
</Button>
<TooltipActivateBtn isActivated={isActivated} isArchived={!!isArchived} />
</div>
)
}
61 changes: 61 additions & 0 deletions src/routes/__tests__/route-workspace.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { test, expect, vi } from 'vitest'
import userEvent from '@testing-library/user-event'
import { RouteWorkspace } from '../route-workspace'
import { useParams } from 'react-router-dom'
import { server } from '@/mocks/msw/node'
import { http, HttpResponse } from 'msw'
import { mswEndpoint } from '@/test/msw-endpoint'

const mockNavigate = vi.fn()

Expand Down Expand Up @@ -148,3 +151,61 @@ test('revert changes button', async () => {
})
).toHaveValue('foo')
})

test('disable activate workspace button', async () => {
server.use(
http.get(mswEndpoint('/api/v1/workspaces/active'), async () => {
return HttpResponse.json({
workspaces: [
{
name: 'foo',
is_active: true,
last_updated: new Date(Date.now()).toISOString(),
},
],
})
})
)

const { getByTestId } = renderComponent()
const activateSection = getByTestId(/workspace-activate/i)
await waitFor(() => {
expect(
within(activateSection).getByRole('button', { name: /activate/i })
).toBeDisabled()
})

expect(
within(activateSection).getByRole('button', {
name: /context active button/i,
})
).toBeVisible()
})

test('activate workspace', async () => {
server.use(
http.get(mswEndpoint('/api/v1/workspaces/active'), async () => {
return HttpResponse.json({
workspaces: [
{
name: 'bar',
is_active: true,
last_updated: new Date(Date.now()).toISOString(),
},
],
})
})
)
const { getByTestId, getByText } = renderComponent()
const activateSection = getByTestId(/workspace-activate/i)
const activateButton = await within(activateSection).findByRole('button', {
name: /activate/i,
})
expect(activateButton).not.toBeDisabled()

await userEvent.click(activateButton)

await waitFor(() => {
expect(getByText(/Activated "foo" workspace/i)).toBeVisible()
})
})
23 changes: 13 additions & 10 deletions src/routes/route-workspace.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { BreadcrumbHome } from '@/components/BreadcrumbHome'
import { ArchiveWorkspace } from '@/features/workspace/components/archive-workspace'
import { PageHeading } from "@/components/heading";
import { WorkspaceName } from "@/features/workspace/components/workspace-name";
import { Alert, Breadcrumb, Breadcrumbs } from "@stacklok/ui-kit";
import { useParams } from "react-router-dom";
import { useArchivedWorkspaces } from "@/features/workspace/hooks/use-archived-workspaces";
import { useRestoreWorkspaceButton } from "@/features/workspace/hooks/use-restore-workspace-button";
import { WorkspaceCustomInstructions } from "@/features/workspace/components/workspace-custom-instructions";
import { WorkspaceMuxingModel } from "@/features/workspace/components/workspace-muxing-model";
import { PageContainer } from "@/components/page-container";
import { PageHeading } from '@/components/heading'
import { WorkspaceName } from '@/features/workspace/components/workspace-name'
import { Alert, Breadcrumb, Breadcrumbs } from '@stacklok/ui-kit'
import { useParams } from 'react-router-dom'
import { useArchivedWorkspaces } from '@/features/workspace/hooks/use-archived-workspaces'
import { useRestoreWorkspaceButton } from '@/features/workspace/hooks/use-restore-workspace-button'
import { WorkspaceCustomInstructions } from '@/features/workspace/components/workspace-custom-instructions'
import { WorkspaceMuxingModel } from '@/features/workspace/components/workspace-muxing-model'
import { PageContainer } from '@/components/page-container'
import { WorkspaceActivateButton } from '@/features/workspace/components/workspace-activate-button'

function WorkspaceArchivedBanner({ name }: { name: string }) {
const restoreButtonProps = useRestoreWorkspaceButton({ workspaceName: name })
Expand Down Expand Up @@ -44,7 +45,9 @@ export function RouteWorkspace() {
<Breadcrumb>Workspace Settings</Breadcrumb>
</Breadcrumbs>

<PageHeading level={1} title={`Workspace settings for ${name}`} />
<PageHeading level={1} title={`Workspace settings for ${name}`}>
<WorkspaceActivateButton isArchived={isArchived} workspaceName={name} />
</PageHeading>

{isArchived ? <WorkspaceArchivedBanner name={name} /> : null}

Expand Down
Loading