Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/plus/integrations/authentication/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ export function isSupportedCloudIntegrationId(id: string): id is SupportedCloudI
return getSupportedCloudIntegrationIds().includes(id as SupportedCloudIntegrationIds);
}

export function isIssueCloudIntegrationId(id: string): id is IssuesCloudHostIntegrationId {
const issueIds: string[] = Object.values(IssuesCloudHostIntegrationId);
return issueIds.includes(id);
}

export const toIntegrationId: { [key in CloudIntegrationType]: IntegrationIds } = {
jira: IssuesCloudHostIntegrationId.Jira,
linear: IssuesCloudHostIntegrationId.Linear,
Expand Down
40 changes: 32 additions & 8 deletions src/webviews/apps/settings/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
import './settings.scss';
import type { ConnectCloudIntegrationsCommandArgs } from '../../../commands/cloudIntegrations';
import type { AutolinkConfig } from '../../../config';
import type { IssuesCloudHostIntegrationId, SupportedCloudIntegrationIds } from '../../../constants.integrations';
import type { SupportedCloudIntegrationIds } from '../../../constants.integrations';
import { IssuesCloudHostIntegrationId } from '../../../constants.integrations';
import { createCommandLink } from '../../../system/commands';
import type { IpcMessage, UpdateConfigurationParams } from '../../protocol';
import { DidChangeConfigurationNotification, UpdateConfigurationCommand } from '../../protocol';
import type { State } from '../../settings/protocol';
import {
DidChangeAccountNotification,
DidChangeConnectedJiraNotification,
DidChangeIssueIntegrationConnectedNotification,
DidOpenAnchorNotification,
GenerateConfigurationPreviewRequest,
} from '../../settings/protocol';
Expand Down Expand Up @@ -159,8 +160,12 @@ export class SettingsApp extends App<State> {
this.renderAutolinkIntegration();
break;

case DidChangeConnectedJiraNotification.is(msg):
this.state.hasConnectedJira = msg.params.hasConnectedJira;
case DidChangeIssueIntegrationConnectedNotification.is(msg):
if (msg.params.integrationId === IssuesCloudHostIntegrationId.Jira) {
this.state.hasConnectedJira = msg.params.connected;
} else if (msg.params.integrationId === IssuesCloudHostIntegrationId.Linear) {
this.state.hasConnectedLinear = msg.params.connected;
}
this.setState(this.state);
this.renderAutolinkIntegration();
break;
Expand Down Expand Up @@ -804,8 +809,8 @@ export class SettingsApp extends App<State> {
const $root = document.querySelector('[data-component="autolink-integration"]');
if ($root == null) return;

const { hasAccount, hasConnectedJira } = this.state;
let message = `<a href="${createCommandLink<ConnectCloudIntegrationsCommandArgs>(
const { hasAccount, hasConnectedJira, hasConnectedLinear } = this.state;
let messageJira = `<a href="${createCommandLink<ConnectCloudIntegrationsCommandArgs>(
'gitlens.plus.cloudIntegrations.connect',
{
integrationIds: ['jira' as IssuesCloudHostIntegrationId.Jira] as SupportedCloudIntegrationIds[],
Expand All @@ -821,11 +826,30 @@ export class SettingsApp extends App<State> {
hasAccount ? '' : 'sign up and '
}get access to automatic rich Jira autolinks.`;
if (hasAccount && hasConnectedJira) {
message =
messageJira =
'<i class="codicon codicon-check" style="vertical-align: text-bottom"></i> Jira connected &mdash; automatic rich Jira autolinks are enabled.';
}
let messageLinear = `<a href="${createCommandLink<ConnectCloudIntegrationsCommandArgs>(
'gitlens.plus.cloudIntegrations.connect',
{
integrationIds: ['linear' as IssuesCloudHostIntegrationId.Linear] as SupportedCloudIntegrationIds[],
source: {
source: 'settings',
detail: {
action: 'connect',
integration: 'linear',
},
},
},
)}">Connect to Linear</a> &mdash; ${
hasAccount ? '' : 'sign up and '
}get access to automatic rich Linear autolinks.`;
if (hasAccount && hasConnectedLinear) {
messageLinear =
'<i class="codicon codicon-check" style="vertical-align: text-bottom"></i> Linear connected &mdash; automatic rich Linear autolinks are enabled.';
}

$root.innerHTML = message;
$root.innerHTML = `${messageJira}<br/>${messageLinear}`;
}

private renderAutolinks() {
Expand Down
13 changes: 7 additions & 6 deletions src/webviews/settings/protocol.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Config } from '../../config';
import type { IssuesCloudHostIntegrationId } from '../../constants.integrations';
import type { IpcScope, WebviewState } from '../protocol';
import { IpcNotification, IpcRequest } from '../protocol';

Expand All @@ -12,6 +13,7 @@ export interface State extends WebviewState {
scopes: ['user' | 'workspace', string][];
hasAccount: boolean;
hasConnectedJira: boolean;
hasConnectedLinear: boolean;
}

// REQUESTS
Expand Down Expand Up @@ -43,10 +45,9 @@ export interface DidChangeAccountParams {
}
export const DidChangeAccountNotification = new IpcNotification<DidChangeAccountParams>(scope, 'didChangeAccount');

export interface DidChangeConnectedJiraParams {
hasConnectedJira: boolean;
export interface DidChangeIssueIntegrationConnectedParams {
integrationId: IssuesCloudHostIntegrationId;
connected: boolean;
}
export const DidChangeConnectedJiraNotification = new IpcNotification<DidChangeConnectedJiraParams>(
scope,
'didChangeConnectedJira',
);
export const DidChangeIssueIntegrationConnectedNotification =
new IpcNotification<DidChangeIssueIntegrationConnectedParams>(scope, 'didChangeIssueIntegrationConnected');
25 changes: 21 additions & 4 deletions src/webviews/settings/settingsWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import { GitFileChange } from '../../git/models/fileChange';
import { GitFileIndexStatus } from '../../git/models/fileStatus';
import { PullRequest } from '../../git/models/pullRequest';
import type { SubscriptionChangeEvent } from '../../plus/gk/subscriptionService';
import { isIssueCloudIntegrationId } from '../../plus/integrations/authentication/models';
import type { ConnectionStateChangeEvent } from '../../plus/integrations/integrationService';
import type { ConfigPath, CoreConfigPath } from '../../system/-webview/configuration';
import { configuration } from '../../system/-webview/configuration';
import { map } from '../../system/iterable';
import { getSettledValue } from '../../system/promise';
import type { CustomConfigPath, IpcMessage } from '../protocol';
import {
assertsConfigKeyValue,
Expand All @@ -25,7 +27,7 @@ import type { WebviewHost, WebviewProvider } from '../webviewProvider';
import type { State } from './protocol';
import {
DidChangeAccountNotification,
DidChangeConnectedJiraNotification,
DidChangeIssueIntegrationConnectedNotification,
DidOpenAnchorNotification,
GenerateConfigurationPreviewRequest,
} from './protocol';
Expand Down Expand Up @@ -61,8 +63,12 @@ export class SettingsWebviewProvider implements WebviewProvider<State, State, Se
}

private onIntegrationConnectionStateChanged(e: ConnectionStateChangeEvent) {
if (e.key === 'jira') {
void this.host.notify(DidChangeConnectedJiraNotification, { hasConnectedJira: e.reason === 'connected' });
const key = e.key;
if (isIssueCloudIntegrationId(key)) {
void this.host.notify(DidChangeIssueIntegrationConnectedNotification, {
integrationId: key,
connected: e.reason === 'connected',
});
}
}

Expand All @@ -76,12 +82,22 @@ export class SettingsWebviewProvider implements WebviewProvider<State, State, Se
return jira.maybeConnected ?? jira.isConnected();
}

async getLinearConnected(): Promise<boolean> {
const linear = await this.container.integrations.get(IssuesCloudHostIntegrationId.Linear);
if (linear == null) return false;
return linear.maybeConnected ?? linear.isConnected();
}

async includeBootstrap(): Promise<State> {
const scopes: ['user' | 'workspace', string][] = [['user', 'User']];
if (workspace.workspaceFolders?.length) {
scopes.push(['workspace', 'Workspace']);
}

const [jiraConnected, linearConnected] = (
await Promise.allSettled([this.getJiraConnected(), this.getLinearConnected()])
).map(r => getSettledValue(r, false));

return {
...this.host.baseWebviewState,
version: this.container.version,
Expand All @@ -91,7 +107,8 @@ export class SettingsWebviewProvider implements WebviewProvider<State, State, Se
scope: 'user',
scopes: scopes,
hasAccount: await this.getAccountState(),
hasConnectedJira: await this.getJiraConnected(),
hasConnectedJira: jiraConnected,
hasConnectedLinear: linearConnected,
};
}

Expand Down
Loading