Skip to content

Commit 7c4c6b6

Browse files
fix(codecatalyst): Dev Env "Space" input also shows Projects #3292
Problem: When selecting a Space while creating a Dev Env, the user sees a quick pick of all Spaces + Projects. Solution: - When the user selects a Space, show only the Space names. - The Project is disabled until a Space is chosen. - Upon initial loading of the webview, Space names are pre-loaded. - Upon selection of a Space, Projects are pre-loaded before the user clicks the 'edit' icon on a Project. Signed-off-by: Nikolas Komonen <[email protected]>
1 parent 2bceced commit 7c4c6b6

File tree

4 files changed

+65
-31
lines changed

4 files changed

+65
-31
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Dev Env Space quick pick shows all Spaces + Projects"
4+
}

src/codecatalyst/vue/create/backend.ts

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,29 @@ import { isCloud9 } from '../../../shared/extensionUtilities'
3333
import { telemetry } from '../../../shared/telemetry/telemetry'
3434
import { isNonNullable } from '../../../shared/utilities/tsUtils'
3535
import { recordSource } from '../../utils'
36-
import { QuickPickPrompter } from '../../../shared/ui/pickerPrompter'
37-
import { createProjectPrompter } from '../../wizards/selectResource'
36+
import { createOrgPrompter, createProjectPrompter } from '../../wizards/selectResource'
3837
import { GetSourceRepositoryCloneUrlsRequest } from 'aws-sdk/clients/codecatalyst'
38+
import { QuickPickPrompter } from '../../../shared/ui/pickerPrompter'
3939

4040
interface LinkedResponse {
4141
readonly type: 'linked'
42+
readonly selectedSpace: Pick<CodeCatalystOrg, 'name'>
4243
readonly selectedProject: CodeCatalystProject
4344
readonly selectedBranch: CodeCatalystBranch
4445
readonly newBranch: string
4546
}
4647

4748
interface EmptyResponse {
4849
readonly type: 'none'
50+
readonly selectedSpace: Pick<CodeCatalystOrg, 'name'>
4951
readonly selectedProject: CodeCatalystProject
5052
}
5153

5254
export type SourceResponse = LinkedResponse | EmptyResponse
5355

5456
export class CodeCatalystCreateWebview extends VueWebview {
5557
private projectPrompter?: QuickPickPrompter<CodeCatalystProject>
58+
private spacePrompter?: QuickPickPrompter<CodeCatalystOrg>
5659

5760
public readonly id = 'createCodeCatalyst'
5861
public readonly source = 'src/codecatalyst/vue/create/index.js'
@@ -64,13 +67,8 @@ export class CodeCatalystCreateWebview extends VueWebview {
6467
) {
6568
super()
6669

67-
// When webview first loads, an instance of this class
68-
// is created.
69-
// We build the prompter here since it immeditely starts
70-
// fetching the Projects upon creation.
71-
// When a user triggers the prompt to select a Project the **first** time,
72-
// the fetching of Projects will already be in progress.
73-
this.projectPrompter = createProjectPrompter(this.client)
70+
// triggers pre-loading of Spaces
71+
this.spacePrompter = createOrgPrompter(client)
7472
}
7573

7674
public close() {
@@ -79,24 +77,38 @@ export class CodeCatalystCreateWebview extends VueWebview {
7977
}
8078

8179
/**
82-
* Opens a quick pick that lists all Projects from all Spaces.
80+
* Opens a quick pick that lists all Spaces of the user.
8381
*
84-
* @param spaceName Only show Projects from this Space in the quick pick. If undefined,
85-
* shows Projects from all Spaces.
86-
* @returns Project if it was selected, otherwise undefined due to user cancellation.
82+
* @returns Space if it was selected, otherwise undefined due to user cancellation.
8783
*/
88-
public async quickPickProject(spaceName?: CodeCatalystOrg['name']): Promise<CodeCatalystProject | undefined> {
89-
// We use an existing prompter since it would have already started
90-
// fetching Projects (improved UX).
91-
if (this.projectPrompter === undefined) {
92-
this.projectPrompter = createProjectPrompter(this.client, spaceName)
84+
public async quickPickSpace(): Promise<CodeCatalystOrg | undefined> {
85+
this.spacePrompter = this.spacePrompter ?? createOrgPrompter(this.client)
86+
const selectedSpace = await this.spacePrompter.prompt()
87+
this.spacePrompter = undefined // We want the prompter to be re-created on subsequent calls
88+
89+
if (!isValidResponse(selectedSpace)) {
90+
return undefined
9391
}
9492

93+
// This will initiate preloading of the projects
94+
this.projectPrompter = createProjectPrompter(this.client, selectedSpace?.name)
95+
96+
return selectedSpace
97+
}
98+
99+
/**
100+
* Opens a quick pick that lists all Projects from a given Space.
101+
*
102+
* @param spaceName Space to show Projects from
103+
* @returns Project if it was selected, otherwise undefined due to user cancellation.
104+
*/
105+
public async quickPickProject(spaceName: CodeCatalystOrg['name']): Promise<CodeCatalystProject | undefined> {
106+
this.projectPrompter = this.projectPrompter ?? createProjectPrompter(this.client, spaceName)
95107
const selectedProject = await this.projectPrompter.prompt()
96-
this.projectPrompter = undefined
108+
this.projectPrompter = undefined // We want the prompter to be re-created on subsequent calls
97109

98110
if (!isValidResponse(selectedProject)) {
99-
return
111+
return undefined
100112
}
101113

102114
return selectedProject

src/codecatalyst/vue/create/source.vue

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@
1515
<div class="modes flex-sizing mt-16">
1616
<span class="flex-sizing mt-8">
1717
<label class="option-label soft">Space</label>
18-
<button class="project-button" @click="quickPickProject()">
18+
<button class="project-button" @click="quickPickSpace()">
1919
{{ selectedSpaceName }}
2020
<span class="icon icon-lg icon-vscode-edit edit-icon"></span>
2121
</button>
2222
</span>
2323

2424
<span class="flex-sizing mt-8">
2525
<label class="option-label soft">Project</label>
26-
<button class="project-button" @click="quickPickProject(model.selectedProject?.org.name)">
26+
<button class="project-button" @click="quickPickProject()" :disabled="!isSpaceSelected">
2727
{{ selectedProjectName }}
2828
<span class="icon icon-lg icon-vscode-edit edit-icon"></span>
2929
</button>
@@ -71,15 +71,15 @@
7171
<div class="modes flex-sizing mt-16">
7272
<span class="flex-sizing mt-8">
7373
<label class="option-label soft">Space</label>
74-
<button class="project-button" @click="quickPickProject()">
74+
<button class="project-button" @click="quickPickSpace()">
7575
{{ selectedSpaceName }}
7676
<span class="icon icon-lg icon-vscode-edit edit-icon"></span>
7777
</button>
7878
</span>
7979

8080
<span class="flex-sizing mt-8">
8181
<label class="option-label soft">Project</label>
82-
<button class="project-button" @click="quickPickProject(model.selectedProject?.org.name)">
82+
<button class="project-button" @click="quickPickProject()" :disabled="!isSpaceSelected">
8383
{{ selectedProjectName }}
8484
<span class="icon icon-lg icon-vscode-edit edit-icon"></span>
8585
</button>
@@ -90,7 +90,7 @@
9090

9191
<script lang="ts">
9292
import { defineComponent } from 'vue'
93-
import { CodeCatalystBranch, CodeCatalystOrg, CodeCatalystProject } from '../../../shared/clients/codecatalystClient'
93+
import { CodeCatalystBranch, CodeCatalystProject } from '../../../shared/clients/codecatalystClient'
9494
import { WebviewClientFactory } from '../../../webviews/client'
9595
import { createClass, createType } from '../../../webviews/util'
9696
import { CodeCatalystCreateWebview, SourceResponse } from './backend'
@@ -214,14 +214,17 @@ export default defineComponent({
214214
return 'Branch already exists'
215215
}
216216
},
217+
isSpaceSelected() {
218+
return !!this.model.selectedSpace
219+
},
217220
isProjectSelected() {
218221
return !!this.model.selectedProject
219222
},
220223
selectedSpaceName() {
221-
if (this.model.selectedProject === undefined) {
224+
if (this.model.selectedSpace === undefined) {
222225
return 'Not Selected'
223226
}
224-
return this.model.selectedProject.org.name
227+
return this.model.selectedSpace.name
225228
},
226229
selectedProjectName() {
227230
if (this.model.selectedProject === undefined) {
@@ -248,12 +251,24 @@ export default defineComponent({
248251
})
249252
this.update()
250253
},
251-
async quickPickProject(spaceToGetProjects: CodeCatalystOrg['name'] | undefined = undefined) {
252-
const res = await client.quickPickProject(spaceToGetProjects)
253-
if (res === undefined) {
254+
async quickPickSpace() {
255+
const space = await client.quickPickSpace()
256+
if (space === undefined) {
257+
return
258+
}
259+
this.$emit('update:modelValue', { ...this.modelValue, selectedSpace: space, selectedProject: undefined })
260+
},
261+
async quickPickProject() {
262+
const selectedSpace = this.modelValue.selectedSpace
263+
if (selectedSpace === undefined) {
264+
return
265+
}
266+
267+
const project = await client.quickPickProject(selectedSpace.name)
268+
if (project === undefined) {
254269
return
255270
}
256-
this.$emit('update:modelValue', { ...this.modelValue, selectedProject: res })
271+
this.$emit('update:modelValue', { ...this.modelValue, selectedProject: project })
257272
},
258273
},
259274
emits: {

src/testE2E/codecatalyst/client.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ describe('Test how this codebase uses the CodeCatalyst API', function () {
117117
const emptyDevEnvSettings = buildDevEnvSettings()
118118
const emptyDevEnv = await webviewClient.createDevEnvOfType(emptyDevEnvSettings, {
119119
type: 'none',
120+
selectedSpace: { name: spaceName },
120121
selectedProject: { name: projectName, org: { name: spaceName }, type: 'project' },
121122
})
122123
assert.strictEqual(emptyDevEnv.project.name, projectName)
@@ -128,6 +129,7 @@ describe('Test how this codebase uses the CodeCatalyst API', function () {
128129

129130
const actualDevEnv = await webviewClient.createDevEnvOfType(differentDevEnvSettings, {
130131
type: 'none',
132+
selectedSpace: { name: spaceName },
131133
selectedProject: { name: projectName, org: { name: spaceName }, type: 'project' },
132134
})
133135

@@ -202,6 +204,7 @@ describe('Test how this codebase uses the CodeCatalyst API', function () {
202204
// Create multiple Dev Envs
203205
const projectSource: SourceResponse = {
204206
type: 'none',
207+
selectedSpace: { name: spaceName },
205208
selectedProject: { name: isolatedProjectName, org: { name: spaceName }, type: 'project' },
206209
}
207210
const createdDevEnvs = await Promise.all([

0 commit comments

Comments
 (0)