Skip to content

Commit 9be9c66

Browse files
refactor: better workspace drawer ux.
1 parent 9da5e93 commit 9be9c66

2 files changed

Lines changed: 99 additions & 2 deletions

File tree

playwright/github-pr-drawer/open-pr-create.spec.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,10 @@ test('Local New workspace always creates a new stored workspace snapshot', async
11081108

11091109
const initialLocalRecordCount = await countLocalRecords()
11101110
await page.getByRole('button', { name: 'New workspace', exact: true }).click()
1111+
await expect(page.getByRole('complementary', { name: 'Workspaces' })).toBeHidden()
1112+
1113+
await page.getByRole('button', { name: 'Workspaces' }).click()
1114+
await expect(page.getByRole('button', { name: 'Remove', exact: true })).toBeDisabled()
11111115

11121116
await expect.poll(async () => countLocalRecords()).toBe(initialLocalRecordCount + 1)
11131117
})
@@ -1151,6 +1155,7 @@ test('Non-Local New workspace forks a new repository-scoped workspace when entri
11511155
page.getByRole('button', { name: 'New workspace', exact: true }),
11521156
).toBeVisible()
11531157
await page.getByRole('button', { name: 'New workspace', exact: true }).click()
1158+
await expect(page.getByRole('complementary', { name: 'Workspaces' })).toBeHidden()
11541159

11551160
await expect.poll(async () => countRepositoryRecords()).toBe(initialRepositoryCount + 1)
11561161

@@ -1174,6 +1179,86 @@ test('Non-Local New workspace forks a new repository-scoped workspace when entri
11741179
expect(String(forkedRepositoryRecord?.head ?? '')).not.toBe(seededHead)
11751180
})
11761181

1182+
test('Removing a non-active workspace reselects the active workspace in Workspaces select', async ({
1183+
page,
1184+
}) => {
1185+
const activeWorkspaceId = 'active_workspace_select_fallback_target'
1186+
1187+
await waitForAppReady(page, `${appEntryPath}`)
1188+
1189+
await seedLocalWorkspaceContexts(page, [
1190+
{
1191+
id: activeWorkspaceId,
1192+
repo: '',
1193+
base: 'main',
1194+
head: 'feat/active-workspace',
1195+
prTitle: 'Active workspace',
1196+
prNumber: null,
1197+
prContextState: 'inactive',
1198+
},
1199+
{
1200+
id: 'workspace_to_remove_from_drawer',
1201+
repo: '',
1202+
base: 'main',
1203+
head: 'feat/removable-workspace',
1204+
prTitle: 'Removable workspace',
1205+
prNumber: null,
1206+
prContextState: 'inactive',
1207+
},
1208+
])
1209+
1210+
await page.reload()
1211+
await waitForAppReady(page, `${appEntryPath}`)
1212+
await connectByotWithSingleRepo(page)
1213+
1214+
await openStoredWorkspaceContextById(page, activeWorkspaceId, {
1215+
repositoryFilter: '__local__',
1216+
})
1217+
1218+
await page.getByRole('button', { name: 'Workspaces' }).click()
1219+
await selectWorkspacesRepositoryFilter(page, '__local__')
1220+
1221+
const storedWorkspaceSelect = page.locator('#workspaces-select')
1222+
const removeWorkspaceButton = page.getByRole('button', {
1223+
name: 'Remove',
1224+
exact: true,
1225+
})
1226+
1227+
const resolveRemovableWorkspaceId = () =>
1228+
storedWorkspaceSelect.evaluate((element, activeId) => {
1229+
if (!(element instanceof HTMLSelectElement)) {
1230+
return ''
1231+
}
1232+
1233+
const candidates = Array.from(element.options)
1234+
.map(option => option.value)
1235+
.filter(value => value && value !== activeId)
1236+
1237+
return candidates[0] ?? ''
1238+
}, activeWorkspaceId)
1239+
1240+
await expect.poll(resolveRemovableWorkspaceId).not.toBe('')
1241+
const removableWorkspaceId = await resolveRemovableWorkspaceId()
1242+
1243+
await storedWorkspaceSelect.selectOption(removableWorkspaceId)
1244+
await expect(storedWorkspaceSelect).toHaveValue(removableWorkspaceId)
1245+
await expect(removeWorkspaceButton).toBeEnabled()
1246+
await removeWorkspaceButton.click()
1247+
1248+
const dialog = page.locator('#clear-confirm-dialog')
1249+
await expect(dialog).toBeVisible()
1250+
await dialog.locator('button[value="confirm"]').evaluate(element => {
1251+
if (element instanceof HTMLButtonElement) {
1252+
element.click()
1253+
}
1254+
})
1255+
1256+
await expect
1257+
.poll(async () => storedWorkspaceSelect.inputValue())
1258+
.toBe(activeWorkspaceId)
1259+
await expect(removeWorkspaceButton).toBeDisabled()
1260+
})
1261+
11771262
test('Switching Workspaces repository scope to Local keeps inactive record repo and shows it as local in drawer', async ({
11781263
page,
11791264
}) => {

src/modules/workspace/workspaces-drawer/drawer.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,11 @@ export const createWorkspacesDrawer = ({
149149
selectInput instanceof HTMLSelectElement
150150
? toSafeText(selectInput.value)
151151
: toSafeText(selectedId)
152+
const activeWorkspaceId =
153+
typeof getActiveWorkspaceId === 'function' ? toSafeText(getActiveWorkspaceId()) : ''
152154
const hasSelection = normalizedSelectedId.length > 0
155+
const isSelectedWorkspaceActive =
156+
hasSelection && activeWorkspaceId && normalizedSelectedId === activeWorkspaceId
153157
const canCreateWorkspace = typeof onCreateWorkspace === 'function'
154158
const canInitializeWorkspace = typeof onInitializeWorkspace === 'function'
155159
const hasStoredWorkspaces =
@@ -185,7 +189,7 @@ export const createWorkspacesDrawer = ({
185189
}
186190

187191
if (removeButton instanceof HTMLButtonElement) {
188-
removeButton.disabled = !hasSelection
192+
removeButton.disabled = !hasSelection || isSelectedWorkspaceActive
189193
}
190194
}
191195

@@ -325,7 +329,14 @@ export const createWorkspacesDrawer = ({
325329
}
326330

327331
if (!entries.some(entry => toSafeText(entry?.id) === selectedId)) {
328-
selectedId = ''
332+
const activeWorkspaceId =
333+
typeof getActiveWorkspaceId === 'function'
334+
? toSafeText(getActiveWorkspaceId())
335+
: ''
336+
const hasActiveWorkspaceEntry = entries.some(
337+
entry => toSafeText(entry?.id) === activeWorkspaceId,
338+
)
339+
selectedId = hasActiveWorkspaceEntry ? activeWorkspaceId : ''
329340
}
330341

331342
renderOptions()
@@ -466,6 +477,7 @@ export const createWorkspacesDrawer = ({
466477
typeof getActiveWorkspaceId === 'function' ? toSafeText(getActiveWorkspaceId()) : ''
467478
setStatus('Created workspace.', 'neutral')
468479
await refresh({ preserveSelection: Boolean(selectedId) })
480+
closeDrawer()
469481
})
470482

471483
openButton?.addEventListener('click', async () => {

0 commit comments

Comments
 (0)