Skip to content

Commit cccc238

Browse files
authWebview: Green bar (#3590)
* greenBar: emit more detail on auth connection change Previously when an auth connection changed we would emit that a change happened but nothing else. Now we emit an event that has more information including the current status, cause, and specific auth type Signed-off-by: Nikolas Komonen <[email protected]> * greenBar: show when has connection This adds a green bar that tells the user they have a successful connection and gives more info on how to switch connections if necessary. This is a quick implementation and requires more work if we want to list the currently selected connections. Signed-off-by: Nikolas Komonen <[email protected]> * greenBar: remove Document Type service item We do not want to show the Document Type service item anymore, this removes it. Signed-off-by: Nikolas Komonen <[email protected]> * greenBar: make bar width fit content The width of the bar will adjust to fit the size of the content Signed-off-by: Nikolas Komonen <[email protected]> --------- Signed-off-by: Nikolas Komonen <[email protected]>
1 parent 68f5a44 commit cccc238

15 files changed

+112
-98
lines changed

src/auth/ui/vue/authForms/baseAuth.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import { defineComponent } from 'vue'
33
import { AuthStatus } from './shared.vue'
44
import { AuthFormId } from './types'
55
6+
export type ConnectionUpdateCause = 'signIn' | 'signOut' | 'created'
7+
export type ConnectionUpdateArgs = { id: AuthFormId; isConnected: boolean; cause?: ConnectionUpdateCause }
8+
69
export default defineComponent({
710
emits: ['auth-connection-updated'],
811
methods: {
9-
emitAuthConnectionUpdated(id: AuthFormId) {
10-
this.$emit('auth-connection-updated', id)
12+
emitAuthConnectionUpdated(args: ConnectionUpdateArgs) {
13+
this.$emit('auth-connection-updated', args)
1114
},
1215
},
1316
})

src/auth/ui/vue/authForms/manageBuilderId.vue

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div class="auth-form container-background border-common" id="builder-id-form">
3-
<div v-show="canShowAll">
3+
<div>
44
<FormTitle :isConnected="isConnected">AWS Builder ID</FormTitle>
55

66
<div v-if="stage === 'START'">
@@ -38,7 +38,7 @@
3838
</template>
3939
<script lang="ts">
4040
import { PropType, defineComponent } from 'vue'
41-
import BaseAuthForm from './baseAuth.vue'
41+
import BaseAuthForm, { ConnectionUpdateCause } from './baseAuth.vue'
4242
import FormTitle from './formTitle.vue'
4343
import { AuthStatus } from './shared.vue'
4444
import { AuthWebview } from '../show'
@@ -65,29 +65,26 @@ export default defineComponent({
6565
stage: 'START' as BuilderIdStage,
6666
isConnected: false,
6767
builderIdCode: '',
68-
canShowAll: false,
6968
name: this.state.name,
7069
}
7170
},
7271
async created() {
73-
await this.update()
74-
this.canShowAll = true
72+
await this.update('created')
7573
},
7674
methods: {
7775
async startSignIn() {
7876
this.stage = 'WAITING_ON_USER'
7977
await this.state.startBuilderIdSetup()
80-
await this.update()
78+
await this.update('signIn')
8179
},
82-
async update() {
80+
async update(cause?: ConnectionUpdateCause) {
8381
this.stage = await this.state.stage()
8482
this.isConnected = await this.state.isAuthConnected()
85-
this.emitAuthConnectionUpdated(this.state.id)
83+
this.emitAuthConnectionUpdated({ id: this.state.id, isConnected: this.isConnected, cause })
8684
},
8785
async signout() {
8886
await this.state.signout()
89-
90-
this.update()
87+
this.update('signOut')
9188
},
9289
showNodeInView() {
9390
this.state.showNodeInView()

src/auth/ui/vue/authForms/manageCredentials.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
</template>
5959
<script lang="ts">
6060
import { PropType, defineComponent } from 'vue'
61-
import BaseAuthForm from './baseAuth.vue'
61+
import BaseAuthForm, { ConnectionUpdateCause } from './baseAuth.vue'
6262
import FormTitle from './formTitle.vue'
6363
import { SectionName, StaticProfile } from '../../../credentials/types'
6464
import { WebviewClientFactory } from '../../../../webviews/client'
@@ -107,7 +107,7 @@ export default defineComponent({
107107
this.isFormShown = !(await this.state.isAuthConnected())
108108
await this.updateSubmittableStatus()
109109
110-
this.updateConnectedStatus()
110+
this.updateConnectedStatus('created')
111111
},
112112
computed: {
113113
/** The appropriate accordion symbol (collapsed/uncollapsed) */
@@ -136,10 +136,10 @@ export default defineComponent({
136136
this.canSubmit = errors === undefined
137137
})
138138
},
139-
async updateConnectedStatus() {
139+
async updateConnectedStatus(cause?: ConnectionUpdateCause) {
140140
return this.state.isAuthConnected().then(isConnected => {
141141
this.isConnected = isConnected
142-
this.emitAuthConnectionUpdated('credentials')
142+
this.emitAuthConnectionUpdated({ id: 'credentials', isConnected: this.isConnected, cause })
143143
})
144144
},
145145
async submitData() {
@@ -159,7 +159,7 @@ export default defineComponent({
159159
this.clearFormData()
160160
this.isFormShown = false
161161
this.canSubmit = true // enable submit button
162-
await this.updateConnectedStatus()
162+
await this.updateConnectedStatus('signIn')
163163
},
164164
toggleShowForm() {
165165
this.isFormShown = !this.isFormShown

src/auth/ui/vue/authForms/manageIdentityCenter.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
</template>
5353
<script lang="ts">
5454
import { PropType, defineComponent } from 'vue'
55-
import BaseAuthForm from './baseAuth.vue'
55+
import BaseAuthForm, { ConnectionUpdateCause } from './baseAuth.vue'
5656
import FormTitle from './formTitle.vue'
5757
import { WebviewClientFactory } from '../../../../webviews/client'
5858
import { AuthWebview } from '../show'
@@ -98,21 +98,23 @@ export default defineComponent({
9898
this.data.startUrl = this.state.getValue('startUrl')
9999
this.data.region = this.state.getValue('region')
100100
101-
await this.update()
101+
await this.update('created')
102102
this.canShowAll = true
103103
},
104104
computed: {},
105105
methods: {
106106
async signin(): Promise<void> {
107107
await this.state.startIdentityCenterSetup()
108+
await this.update('signIn')
108109
},
109110
async signout(): Promise<void> {
110111
await this.state.signout()
112+
this.update('signOut')
111113
},
112-
async update() {
114+
async update(cause?: ConnectionUpdateCause) {
113115
this.stage = await this.state.stage()
114116
this.isConnected = await this.state.isAuthConnected()
115-
this.emitAuthConnectionUpdated(this.state.id)
117+
this.emitAuthConnectionUpdated({ id: this.state.id, isConnected: this.isConnected, cause })
116118
},
117119
async getRegion() {
118120
const region = await this.state.getRegion()

src/auth/ui/vue/authForms/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,10 @@ export type AuthFormId =
88
| 'builderIdCodeWhisperer'
99
| 'builderIdCodeCatalyst'
1010
| 'identityCenterCodeWhisperer'
11+
12+
export const AuthFormDisplayName: Record<AuthFormId, string> = {
13+
credentials: 'IAM Credentials',
14+
builderIdCodeCatalyst: 'Builder ID',
15+
builderIdCodeWhisperer: 'Builder ID',
16+
identityCenterCodeWhisperer: 'IAM Identity Center',
17+
} as const

src/auth/ui/vue/root.vue

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div>
2+
<div :style="{ display: 'flex', flexDirection: 'column', gap: '20px' }">
33
<div>
44
<div style="display: flex; justify-content: left; align-items: center; gap: 25px">
55
<div style="fill: white">
@@ -30,6 +30,36 @@
3030
</div>
3131
</div>
3232
</div>
33+
34+
<div
35+
v-if="successfulAuthConnection"
36+
class="border-common"
37+
style="
38+
width: fit-content;
39+
white-space: nowrap;
40+
display: flex;
41+
flex-direction: row;
42+
background-color: #28632b;
43+
color: #ffffff;
44+
padding: 10px;
45+
"
46+
>
47+
<div class="icon icon-lg icon-vscode-check"></div>
48+
&nbsp; &nbsp;
49+
<div style="display: flex; flex-direction: row">
50+
You're connected to {{ authFormDisplayName }}! Switch between connections in the&nbsp;<a
51+
v-on:click="showConnectionQuickPick()"
52+
style="cursor: pointer"
53+
>Toolkit panel</a
54+
>&nbsp;or add additional connections below.
55+
</div>
56+
&nbsp;&nbsp;
57+
<div
58+
v-on:click="closeStatusBar"
59+
style="cursor: pointer"
60+
class="icon icon-lg icon-vscode-chrome-close"
61+
></div>
62+
</div>
3363
<div class="flex-container">
3464
<div id="left-column">
3565
<div>
@@ -53,7 +83,7 @@
5383
:is="getServiceItemContent(item.id)"
5484
:state="serviceItemsAuthStatus[item.id]"
5585
:key="item.id + rerenderContentWindowKey"
56-
@is-auth-connected="onIsAuthConnected"
86+
@auth-connection-updated="onAuthConnectionUpdated"
5787
></component>
5888
</template>
5989
</ServiceItem>
@@ -65,7 +95,7 @@
6595
:is="getServiceItemContent(getSelectedService())"
6696
:state="serviceItemsAuthStatus[getSelectedService()]"
6797
:key="getSelectedService() + rerenderContentWindowKey"
68-
@is-auth-connected="onIsAuthConnected"
98+
@auth-connection-updated="onAuthConnectionUpdated"
6999
></component>
70100
</div>
71101
</div>
@@ -79,6 +109,8 @@ import serviceItemsContent, { serviceItemsAuthStatus } from './serviceItemConten
79109
import { AuthWebview } from './show'
80110
import { WebviewClientFactory } from '../../../webviews/client'
81111
import { ServiceItemId } from './types'
112+
import { AuthFormDisplayName, AuthFormId } from './authForms/types'
113+
import { ConnectionUpdateArgs } from './authForms/baseAuth.vue'
82114
83115
const client = WebviewClientFactory.create<AuthWebview>()
84116
const serviceItemsState = new ServiceItemsState()
@@ -95,6 +127,8 @@ export default defineComponent({
95127
serviceItemsAuthStatus: serviceItemsAuthStatus,
96128
97129
rerenderContentWindowKey: 0,
130+
131+
successfulAuthConnection: undefined as AuthFormId | undefined,
98132
}
99133
},
100134
async created() {
@@ -110,7 +144,7 @@ export default defineComponent({
110144
// and its content window is being shown. If there is an external
111145
// event that changes the state of this service (eg: disconnected)
112146
// this forced rerender will display the new state
113-
this.rerenderSelectedContentWindow()
147+
// this.rerenderSelectedContentWindow()
114148
})
115149
client.onDidSelectService((id: ServiceItemId) => {
116150
this.selectService(id)
@@ -132,6 +166,12 @@ export default defineComponent({
132166
})
133167
return [...unlocked, ...locked]
134168
},
169+
authFormDisplayName() {
170+
if (this.successfulAuthConnection === undefined) {
171+
return ''
172+
}
173+
return AuthFormDisplayName[this.successfulAuthConnection]
174+
},
135175
},
136176
methods: {
137177
isLandscape() {
@@ -187,8 +227,13 @@ export default defineComponent({
187227
serviceItemsState.lock(id)
188228
}
189229
},
190-
onIsAuthConnected(id: ServiceItemId, isConnected: boolean) {
191-
this.updateServiceLock(id, isConnected)
230+
onAuthConnectionUpdated(id: ServiceItemId, args: ConnectionUpdateArgs) {
231+
if (args.isConnected && args.cause === 'signIn') {
232+
this.successfulAuthConnection = args.id
233+
this.rerenderSelectedContentWindow()
234+
}
235+
236+
this.updateServiceLock(id, args.isConnected)
192237
this.renderItems()
193238
// In some cases, during the connection process for one auth method,
194239
// an already connected auth can be disconnected. This refreshes all
@@ -221,6 +266,12 @@ export default defineComponent({
221266
this.selectService(initialService)
222267
}
223268
},
269+
showConnectionQuickPick() {
270+
client.showConnectionQuickPick()
271+
},
272+
closeStatusBar() {
273+
this.successfulAuthConnection = undefined
274+
},
224275
},
225276
})
226277
</script>
@@ -249,10 +300,4 @@ export default defineComponent({
249300
/* Creates an even separation between all list items*/
250301
margin-top: 10px;
251302
}
252-
253-
#right-column {
254-
/* This can be deleted, for development purposes */
255-
height: 800px;
256-
margin: 10px;
257-
}
258303
</style>

src/auth/ui/vue/serviceItem.vue

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,6 @@ export default defineComponent({
127127
*/
128128
129129
const staticServiceItemProps: Readonly<Record<ServiceItemId, { title: string; description: string }>> = {
130-
documentTypeSupport: {
131-
title: 'Edit CloudFormation Templates',
132-
description: 'Invalid syntax validation and auto-completion.',
133-
},
134130
resourceExplorer: {
135131
title: 'View, modify, and deploy AWS Resources',
136132
description: 'Work with S3, CloudWatch, and more.',
@@ -160,10 +156,10 @@ export class ServiceItemsState {
160156
*
161157
* Note the default unlocked service(s) are pre-defined here.
162158
*/
163-
private readonly unlockedServices: Set<ServiceItemId> = new Set(['documentTypeSupport'])
159+
private readonly unlockedServices: Set<ServiceItemId> = new Set(['resourceExplorer'])
164160
165161
/** Note a service item is pre-selected by default */
166-
private currentlySelected?: ServiceItemId = 'documentTypeSupport'
162+
private currentlySelected?: ServiceItemId = 'resourceExplorer'
167163
168164
/**
169165
* The Ids of the service items, separated by the ones that are locked vs. unlocked

src/auth/ui/vue/serviceItemContent/awsExplorerContent.vue

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import CredentialsForm, { CredentialsState } from '../authForms/manageCredential
4141
import BaseServiceItemContent from './baseServiceItemContent.vue'
4242
import authFormsState, { AuthStatus } from '../authForms/shared.vue'
4343
import { AuthFormId } from '../authForms/types'
44+
import { ConnectionUpdateArgs } from '../authForms/baseAuth.vue'
4445
4546
export default defineComponent({
4647
name: 'AwsExplorerContent',
@@ -64,12 +65,10 @@ export default defineComponent({
6465
const hasUnloaded = Object.values(this.isLoaded).filter(val => !val).length > 0
6566
this.isAllAuthsLoaded = !hasUnloaded
6667
},
67-
async onAuthConnectionUpdated(id: AuthFormId) {
68-
this.isLoaded[id] = true
68+
async onAuthConnectionUpdated(args: ConnectionUpdateArgs) {
69+
this.isLoaded[args.id] = true
6970
this.updateIsAllAuthsLoaded()
70-
71-
const isConnected = await this.state.isAuthConnected()
72-
this.emitIsAuthConnected('resourceExplorer', isConnected)
71+
this.emitAuthConnectionUpdated('resourceExplorer', args)
7372
},
7473
},
7574
})

src/auth/ui/vue/serviceItemContent/baseServiceItemContent.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@
66
import { PropType, defineComponent } from 'vue'
77
import { AuthStatus } from '../authForms/shared.vue'
88
import { ServiceItemId } from '../types'
9+
import { ConnectionUpdateArgs } from '../authForms/baseAuth.vue'
910
1011
export default defineComponent({
1112
name: 'BaseServiceItemContent',
12-
emits: ['is-auth-connected'],
13+
emits: ['auth-connection-updated'],
1314
props: {
1415
state: {
1516
type: Object as PropType<AuthStatus>,
1617
required: true,
1718
},
1819
},
1920
methods: {
20-
emitIsAuthConnected(id: ServiceItemId, isConnected: boolean) {
21-
this.$emit('is-auth-connected', id, isConnected)
21+
emitAuthConnectionUpdated(id: ServiceItemId, args: ConnectionUpdateArgs) {
22+
this.$emit('auth-connection-updated', id, args)
2223
},
2324
},
2425
})

src/auth/ui/vue/serviceItemContent/codeCatalystContent.vue

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import BuilderIdForm, { CodeCatalystBuilderIdState } from '../authForms/manageBu
3838
import BaseServiceItemContent from './baseServiceItemContent.vue'
3939
import authFormsState, { AuthStatus } from '../authForms/shared.vue'
4040
import { AuthFormId } from '../authForms/types'
41+
import { ConnectionUpdateArgs } from '../authForms/baseAuth.vue'
4142
4243
export default defineComponent({
4344
name: 'CodeCatalystContent',
@@ -61,12 +62,10 @@ export default defineComponent({
6162
const hasUnloaded = Object.values(this.isLoaded).filter(val => !val).length > 0
6263
this.isAllAuthsLoaded = !hasUnloaded
6364
},
64-
async onAuthConnectionUpdated(id: AuthFormId) {
65-
this.isLoaded[id] = true
65+
async onAuthConnectionUpdated(args: ConnectionUpdateArgs) {
66+
this.isLoaded[args.id] = true
6667
this.updateIsAllAuthsLoaded()
67-
68-
const isConnected = await this.state.isAuthConnected()
69-
this.emitIsAuthConnected('codecatalyst', isConnected)
68+
this.emitAuthConnectionUpdated('codecatalyst', args)
7069
},
7170
},
7271
})

0 commit comments

Comments
 (0)