Skip to content

Commit d7809d3

Browse files
refactor: better workspace drawer ux. (#112)
1 parent 9da5e93 commit d7809d3

2 files changed

Lines changed: 101 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: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,13 @@ 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 &&
157+
Boolean(activeWorkspaceId) &&
158+
normalizedSelectedId === activeWorkspaceId
153159
const canCreateWorkspace = typeof onCreateWorkspace === 'function'
154160
const canInitializeWorkspace = typeof onInitializeWorkspace === 'function'
155161
const hasStoredWorkspaces =
@@ -185,7 +191,7 @@ export const createWorkspacesDrawer = ({
185191
}
186192

187193
if (removeButton instanceof HTMLButtonElement) {
188-
removeButton.disabled = !hasSelection
194+
removeButton.disabled = !hasSelection || isSelectedWorkspaceActive
189195
}
190196
}
191197

@@ -325,7 +331,14 @@ export const createWorkspacesDrawer = ({
325331
}
326332

327333
if (!entries.some(entry => toSafeText(entry?.id) === selectedId)) {
328-
selectedId = ''
334+
const activeWorkspaceId =
335+
typeof getActiveWorkspaceId === 'function'
336+
? toSafeText(getActiveWorkspaceId())
337+
: ''
338+
const hasActiveWorkspaceEntry = entries.some(
339+
entry => toSafeText(entry?.id) === activeWorkspaceId,
340+
)
341+
selectedId = hasActiveWorkspaceEntry ? activeWorkspaceId : ''
329342
}
330343

331344
renderOptions()
@@ -466,6 +479,7 @@ export const createWorkspacesDrawer = ({
466479
typeof getActiveWorkspaceId === 'function' ? toSafeText(getActiveWorkspaceId()) : ''
467480
setStatus('Created workspace.', 'neutral')
468481
await refresh({ preserveSelection: Boolean(selectedId) })
482+
closeDrawer()
469483
})
470484

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

0 commit comments

Comments
 (0)