diff --git a/src/plus/gk/models/organization.ts b/src/plus/gk/models/organization.ts index bf61599cf6062..5c5960642aec3 100644 --- a/src/plus/gk/models/organization.ts +++ b/src/plus/gk/models/organization.ts @@ -29,7 +29,18 @@ export enum OrganizationType { export type OrganizationConnection = Record; +export type OrganizationMemberStatus = 'activated' | 'pending'; + export interface OrganizationMember { + readonly id: string; + readonly email: string; + readonly name: string; + readonly username: string; + readonly role: OrganizationRole; + readonly status: OrganizationMemberStatus; +} + +export interface OrganizationMemberOld { readonly id: string; readonly email: string; readonly name: string; diff --git a/src/plus/gk/organizationService.ts b/src/plus/gk/organizationService.ts index 9f3b0d2ebd5bc..59c0b3f5fc6c0 100644 --- a/src/plus/gk/organizationService.ts +++ b/src/plus/gk/organizationService.ts @@ -20,8 +20,8 @@ const organizationsCacheExpiration = 24 * 60 * 60 * 1000; // 1 day export class OrganizationService implements Disposable { private _disposable: Disposable; private _organizations: Organization[] | null | undefined; - private _fullOrganizations: Map | undefined; private _organizationSettings: Map | undefined; + private _organizationMembers: Map | undefined; constructor( private readonly container: Container, @@ -147,43 +147,34 @@ export class OrganizationService implements Disposable { } @gate() - private async getFullOrganization( - id: string, - options?: { force?: boolean }, - ): Promise { - if (!this._fullOrganizations?.has(id) || options?.force === true) { - const rsp = await this.connection.fetchGkApi(`organization/${id}`, { method: 'GET' }); + async getMembers(id?: string | undefined, options?: { force?: boolean }): Promise { + if (id == null) { + id = await this.getActiveOrganizationId(); + if (id == null) return []; + } + + if (!this._organizationMembers?.has(id) || options?.force === true) { + type MemberResponse = { + members: OrganizationMember[]; + }; + const rsp = await this.connection.fetchGkApi(`organization/${id}/members`, { method: 'GET' }); if (!rsp.ok) { Logger.error( '', getLogScope(), - `Unable to get organization; status=(${rsp.status}): ${rsp.statusText}`, + `Unable to get organization members; status=(${rsp.status}): ${rsp.statusText}`, ); - return undefined; + return []; } - const organization = (await rsp.json()) as FullOrganization; - if (this._fullOrganizations == null) { - this._fullOrganizations = new Map(); - } - organization.members.sort((a, b) => (a.name ?? a.username).localeCompare(b.name ?? b.username)); - this._fullOrganizations.set(id, organization); - } - return this._fullOrganizations.get(id); - } + const members: OrganizationMember[] = ((await rsp.json()) as MemberResponse).members; + sortOrgMembers(members); - @gate() - async getMembers( - organizationId?: string | undefined, - options?: { force?: boolean }, - ): Promise { - if (organizationId == null) { - organizationId = await this.getActiveOrganizationId(); - if (organizationId == null) return []; + this._organizationMembers ??= new Map(); + this._organizationMembers.set(id, members); } - const organization = await this.getFullOrganization(organizationId, options); - return organization?.members ?? []; + return this._organizationMembers.get(id) ?? []; } async getMemberById(id: string, organizationId: string): Promise { @@ -245,3 +236,7 @@ export class OrganizationService implements Disposable { return this._organizationSettings.get(id); } } + +function sortOrgMembers(members: OrganizationMember[]): OrganizationMember[] { + return members.sort((a, b) => (a.name ?? a.username).localeCompare(b.name ?? b.username)); +} diff --git a/src/plus/integrations/authentication/configuredIntegrationService.ts b/src/plus/integrations/authentication/configuredIntegrationService.ts index 7fd3b39b6c761..07d1890d7244c 100644 --- a/src/plus/integrations/authentication/configuredIntegrationService.ts +++ b/src/plus/integrations/authentication/configuredIntegrationService.ts @@ -1,3 +1,5 @@ +import type { Event } from 'vscode'; +import { EventEmitter } from 'vscode'; import type { IntegrationId } from '../../../constants.integrations'; import { HostingIntegrationId } from '../../../constants.integrations'; import type { StoredConfiguredIntegrationDescriptor } from '../../../constants.storage'; @@ -27,6 +29,11 @@ export type ConfiguredIntegrationType = 'cloud' | 'local'; export class ConfiguredIntegrationService { private _configured?: Map; + private readonly _onDidChangeConfiguredIntegrations = new EventEmitter(); + get onDidChangeConfiguredIntegrations(): Event { + return this._onDidChangeConfiguredIntegrations.event; + } + constructor(private readonly container: Container) {} private get configured(): Map {