@acorex-platform/extension-project-management-jira-client 2.0.0-next.2 → 2.0.0-next.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/acorex-platform-extension-project-management-jira-client-connect-jira.command-w724jEDQ.mjs +215 -0
- package/fesm2022/acorex-platform-extension-project-management-jira-client-connect-jira.command-w724jEDQ.mjs.map +1 -0
- package/fesm2022/acorex-platform-extension-project-management-jira-client-contracts.mjs +72 -67
- package/fesm2022/acorex-platform-extension-project-management-jira-client-contracts.mjs.map +1 -1
- package/fesm2022/acorex-platform-extension-project-management-jira-client.mjs +90 -692
- package/fesm2022/acorex-platform-extension-project-management-jira-client.mjs.map +1 -1
- package/i18n/en-AU/extensions-jira.json +14 -4
- package/i18n/en-US/extensions-jira.json +14 -4
- package/i18n/fa-IR/extensions-jira.json +14 -4
- package/package.json +5 -5
- package/types/acorex-platform-extension-project-management-jira-client-contracts.d.ts +32 -66
- package/types/acorex-platform-extension-project-management-jira-client.d.ts +11 -54
- package/fesm2022/acorex-platform-extension-project-management-jira-client-connect-jira.command-BhnLiDk0.mjs +0 -355
- package/fesm2022/acorex-platform-extension-project-management-jira-client-connect-jira.command-BhnLiDk0.mjs.map +0 -1
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
import { resolveMultiLanguageString, AXP_INTEGRATION_AUTH_METHOD_TYPE, runtimeCommandPayloadData } from '@acorex-platform/framework-shared/core';
|
|
2
|
-
import { AXMIntegrationManagementCommandKeys } from '@acorex-platform/module-integration-management-client/contracts';
|
|
3
|
-
import { AXPSessionService } from '@acorex-platform/framework-client/auth';
|
|
4
|
-
import { AXPLayoutBuilderService, resolveLayoutBuilderDialogResult } from '@acorex-platform/framework-client/layout/builder';
|
|
5
|
-
import { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';
|
|
6
|
-
import { AXPCommandService } from '@acorex-platform/framework-client/runtime';
|
|
7
|
-
import { AXPopupService } from '@acorex/components/popup';
|
|
8
|
-
import { AXPDialogOpener } from '@acorex-platform/framework-client/core';
|
|
9
|
-
import * as i6 from '@acorex/core/translation';
|
|
10
|
-
import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
|
|
11
|
-
import * as i0 from '@angular/core';
|
|
12
|
-
import { ChangeDetectionStrategy, Component, inject, Injectable } from '@angular/core';
|
|
13
|
-
import { defaultTo, trim } from 'lodash-es';
|
|
14
|
-
import { RootConfig } from '@acorex-platform/extension-project-management-jira-client/contracts';
|
|
15
|
-
import * as i2 from '@acorex/components/button';
|
|
16
|
-
import { AXButtonModule } from '@acorex/components/button';
|
|
17
|
-
import * as i4 from '@acorex/components/decorators';
|
|
18
|
-
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
19
|
-
import { AXBasePageComponent } from '@acorex/components/page';
|
|
20
|
-
import * as i3 from '@acorex/components/selection-list';
|
|
21
|
-
import { AXSelectionListModule } from '@acorex/components/selection-list';
|
|
22
|
-
import { AsyncPipe } from '@angular/common';
|
|
23
|
-
|
|
24
|
-
//#endregion
|
|
25
|
-
//#region ---- Component ----
|
|
26
|
-
class AXMJiraInstancePickerPopupComponent extends AXBasePageComponent {
|
|
27
|
-
constructor() {
|
|
28
|
-
super(...arguments);
|
|
29
|
-
this.instances = [];
|
|
30
|
-
}
|
|
31
|
-
instanceListItems() {
|
|
32
|
-
return this.instances.map((instance) => ({
|
|
33
|
-
id: instance.id,
|
|
34
|
-
title: this.instanceTitle(instance),
|
|
35
|
-
deploymentLabelKey: this.deploymentLabelKey(instance),
|
|
36
|
-
}));
|
|
37
|
-
}
|
|
38
|
-
handleInstanceSelection(event) {
|
|
39
|
-
if (!event.isUserInteraction) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
const instance = this.instances.find((item) => item.id === event.value);
|
|
43
|
-
if (instance) {
|
|
44
|
-
this.selectInstance(instance);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
instanceTitle(instance) {
|
|
48
|
-
return resolveMultiLanguageString(instance.title, 'en-US');
|
|
49
|
-
}
|
|
50
|
-
deploymentLabelKey(instance) {
|
|
51
|
-
return instance.deploymentType === 'cloud'
|
|
52
|
-
? '@extensions-jira:instances.entities.instance.fields.deployment-type.options.cloud'
|
|
53
|
-
: '@extensions-jira:instances.entities.instance.fields.deployment-type.options.self-hosted';
|
|
54
|
-
}
|
|
55
|
-
selectInstance(instance) {
|
|
56
|
-
this.close({ instance });
|
|
57
|
-
}
|
|
58
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMJiraInstancePickerPopupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
59
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMJiraInstancePickerPopupComponent, isStandalone: true, selector: "axm-jira-instance-picker-popup", usesInheritance: true, ngImport: i0, template: `
|
|
60
|
-
<div class="flex flex-col gap-2 p-4">
|
|
61
|
-
@if (instances.length === 0) {
|
|
62
|
-
<p class="text-sm opacity-70">
|
|
63
|
-
{{ '@extensions-jira:integration.connect.instance-picker.empty' | translate | async }}
|
|
64
|
-
</p>
|
|
65
|
-
} @else {
|
|
66
|
-
<ax-selection-list
|
|
67
|
-
class="w-full"
|
|
68
|
-
valueField="id"
|
|
69
|
-
textField="title"
|
|
70
|
-
[direction]="'vertical'"
|
|
71
|
-
[look]="'solid'"
|
|
72
|
-
[multiple]="false"
|
|
73
|
-
[showControl]="false"
|
|
74
|
-
[items]="instanceListItems()"
|
|
75
|
-
[customTemplate]="instanceItemTemplate"
|
|
76
|
-
(onValueChanged)="handleInstanceSelection($event)"
|
|
77
|
-
>
|
|
78
|
-
<ng-template #instanceItemTemplate let-item>
|
|
79
|
-
<div class="flex w-full flex-col items-start gap-0.5 py-1">
|
|
80
|
-
<span class="font-medium">{{ item.data.title }}</span>
|
|
81
|
-
<span class="text-xs opacity-70">{{ item.data.deploymentLabelKey | translate | async }}</span>
|
|
82
|
-
</div>
|
|
83
|
-
</ng-template>
|
|
84
|
-
</ax-selection-list>
|
|
85
|
-
}
|
|
86
|
-
</div>
|
|
87
|
-
<ax-footer>
|
|
88
|
-
<ax-suffix>
|
|
89
|
-
<ax-button
|
|
90
|
-
look="outline"
|
|
91
|
-
[text]="'@general:actions.cancel.title' | translate | async"
|
|
92
|
-
(onClick)="close()"
|
|
93
|
-
></ax-button>
|
|
94
|
-
</ax-suffix>
|
|
95
|
-
</ax-footer>
|
|
96
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXSelectionListModule }, { kind: "component", type: i3.AXSelectionListComponent, selector: "ax-selection-list", inputs: ["id", "name", "disabled", "readonly", "tabIndex", "value", "valueField", "textField", "disabledField", "readonlyField", "multiple", "direction", "customTemplate", "showControl", "items", "look"], outputs: ["onValueChanged", "onBlur", "onFocus"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
97
|
-
}
|
|
98
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMJiraInstancePickerPopupComponent, decorators: [{
|
|
99
|
-
type: Component,
|
|
100
|
-
args: [{
|
|
101
|
-
selector: 'axm-jira-instance-picker-popup',
|
|
102
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
103
|
-
imports: [AsyncPipe, AXButtonModule, AXDecoratorModule, AXSelectionListModule, AXTranslationModule],
|
|
104
|
-
template: `
|
|
105
|
-
<div class="flex flex-col gap-2 p-4">
|
|
106
|
-
@if (instances.length === 0) {
|
|
107
|
-
<p class="text-sm opacity-70">
|
|
108
|
-
{{ '@extensions-jira:integration.connect.instance-picker.empty' | translate | async }}
|
|
109
|
-
</p>
|
|
110
|
-
} @else {
|
|
111
|
-
<ax-selection-list
|
|
112
|
-
class="w-full"
|
|
113
|
-
valueField="id"
|
|
114
|
-
textField="title"
|
|
115
|
-
[direction]="'vertical'"
|
|
116
|
-
[look]="'solid'"
|
|
117
|
-
[multiple]="false"
|
|
118
|
-
[showControl]="false"
|
|
119
|
-
[items]="instanceListItems()"
|
|
120
|
-
[customTemplate]="instanceItemTemplate"
|
|
121
|
-
(onValueChanged)="handleInstanceSelection($event)"
|
|
122
|
-
>
|
|
123
|
-
<ng-template #instanceItemTemplate let-item>
|
|
124
|
-
<div class="flex w-full flex-col items-start gap-0.5 py-1">
|
|
125
|
-
<span class="font-medium">{{ item.data.title }}</span>
|
|
126
|
-
<span class="text-xs opacity-70">{{ item.data.deploymentLabelKey | translate | async }}</span>
|
|
127
|
-
</div>
|
|
128
|
-
</ng-template>
|
|
129
|
-
</ax-selection-list>
|
|
130
|
-
}
|
|
131
|
-
</div>
|
|
132
|
-
<ax-footer>
|
|
133
|
-
<ax-suffix>
|
|
134
|
-
<ax-button
|
|
135
|
-
look="outline"
|
|
136
|
-
[text]="'@general:actions.cancel.title' | translate | async"
|
|
137
|
-
(onClick)="close()"
|
|
138
|
-
></ax-button>
|
|
139
|
-
</ax-suffix>
|
|
140
|
-
</ax-footer>
|
|
141
|
-
`,
|
|
142
|
-
}]
|
|
143
|
-
}] });
|
|
144
|
-
|
|
145
|
-
//#endregion
|
|
146
|
-
//#region ---- Command ----
|
|
147
|
-
/** Jira connect: pick instance → self-hosted PAT or cloud OAuth2. */
|
|
148
|
-
class ConnectJiraCommand {
|
|
149
|
-
constructor() {
|
|
150
|
-
//#region ---- Services & Dependencies ----
|
|
151
|
-
this.popupService = inject(AXPopupService);
|
|
152
|
-
this.dialogOpener = inject(AXPDialogOpener);
|
|
153
|
-
this.translationService = inject(AXTranslationService);
|
|
154
|
-
this.entityService = inject(AXPEntityService);
|
|
155
|
-
this.layoutBuilder = inject(AXPLayoutBuilderService);
|
|
156
|
-
this.commandService = inject(AXPCommandService);
|
|
157
|
-
this.sessionService = inject(AXPSessionService);
|
|
158
|
-
}
|
|
159
|
-
//#endregion
|
|
160
|
-
//#region ---- Execute ----
|
|
161
|
-
async execute(input = {}) {
|
|
162
|
-
try {
|
|
163
|
-
const providerId = defaultTo(input.providerId, 'jira');
|
|
164
|
-
const connectionScope = input.connectionScope ?? 'tenant';
|
|
165
|
-
const I18N = '@extensions-jira:integration.connect';
|
|
166
|
-
const instance = await this.pickInstance();
|
|
167
|
-
if (!instance) {
|
|
168
|
-
return { success: true, kind: 'object', data: { outcome: 'cancelled' } };
|
|
169
|
-
}
|
|
170
|
-
if (instance.deploymentType === 'selfHosted') {
|
|
171
|
-
return this.connectSelfHosted(providerId, connectionScope, instance, I18N);
|
|
172
|
-
}
|
|
173
|
-
return this.connectCloud(providerId, connectionScope, instance, I18N);
|
|
174
|
-
}
|
|
175
|
-
catch (error) {
|
|
176
|
-
const message = error instanceof Error ? error.message : 'Failed to connect Jira instance.';
|
|
177
|
-
return { success: false, message: { text: message } };
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
//#endregion
|
|
181
|
-
//#region ---- Instance Picker ----
|
|
182
|
-
async pickInstance() {
|
|
183
|
-
const instances = await this.loadActiveInstances();
|
|
184
|
-
let title = '';
|
|
185
|
-
const result = await this.dialogOpener.openPopup({
|
|
186
|
-
load: () => Promise.resolve(AXMJiraInstancePickerPopupComponent),
|
|
187
|
-
data: { instanceIds: instances.map((instance) => instance.id) },
|
|
188
|
-
prepare: async () => {
|
|
189
|
-
title = await this.translationService.translateAsync('@extensions-jira:integration.connect.instance-picker.title');
|
|
190
|
-
},
|
|
191
|
-
show: (component) => this.popupService.open(component, {
|
|
192
|
-
title,
|
|
193
|
-
size: 'sm',
|
|
194
|
-
data: { instances },
|
|
195
|
-
}),
|
|
196
|
-
});
|
|
197
|
-
return result?.data?.instance ?? null;
|
|
198
|
-
}
|
|
199
|
-
async loadActiveInstances() {
|
|
200
|
-
const accessor = this.entityService
|
|
201
|
-
.withEntity(RootConfig.module.name, RootConfig.entities.jiraInstance.name)
|
|
202
|
-
.data();
|
|
203
|
-
const result = await accessor.query({
|
|
204
|
-
skip: 0,
|
|
205
|
-
take: 200,
|
|
206
|
-
filter: {
|
|
207
|
-
logic: 'and',
|
|
208
|
-
filters: [{ field: 'isActive', operator: { type: 'equal' }, value: true }],
|
|
209
|
-
},
|
|
210
|
-
});
|
|
211
|
-
return result.items ?? [];
|
|
212
|
-
}
|
|
213
|
-
//#endregion
|
|
214
|
-
//#region ---- Self-Hosted (PAT) ----
|
|
215
|
-
async connectSelfHosted(providerId, connectionScope, instance, i18nPrefix) {
|
|
216
|
-
const form = await this.openPatDialog({
|
|
217
|
-
i18nPrefix,
|
|
218
|
-
context: {
|
|
219
|
-
displayName: instance.name,
|
|
220
|
-
instanceUrl: defaultTo(instance.baseUrl, ''),
|
|
221
|
-
token: '',
|
|
222
|
-
},
|
|
223
|
-
instanceUrlReadonly: true,
|
|
224
|
-
});
|
|
225
|
-
if (!form) {
|
|
226
|
-
return { success: true, kind: 'object', data: { outcome: 'cancelled' } };
|
|
227
|
-
}
|
|
228
|
-
const result = await this.commandService.execute(AXMIntegrationManagementCommandKeys.ConnectionConnectWithCredentials, {
|
|
229
|
-
providerId,
|
|
230
|
-
authMethodType: AXP_INTEGRATION_AUTH_METHOD_TYPE.Pat,
|
|
231
|
-
connectionScope,
|
|
232
|
-
connectionKey: instance.name,
|
|
233
|
-
displayName: defaultTo(trim(form.displayName), instance.name),
|
|
234
|
-
instanceUrl: defaultTo(trim(form.instanceUrl), defaultTo(instance.baseUrl, '')),
|
|
235
|
-
credentials: { token: form.token },
|
|
236
|
-
config: { jiraInstanceId: instance.id },
|
|
237
|
-
});
|
|
238
|
-
const data = runtimeCommandPayloadData(result);
|
|
239
|
-
if (!data) {
|
|
240
|
-
return {
|
|
241
|
-
success: false,
|
|
242
|
-
message: result?.message ?? { text: 'Failed to save Jira connection.' },
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
return { success: true, kind: 'object', data: { outcome: 'connected', connection: data } };
|
|
246
|
-
}
|
|
247
|
-
//#endregion
|
|
248
|
-
//#region ---- Cloud (OAuth2) ----
|
|
249
|
-
async connectCloud(providerId, connectionScope, instance, i18nPrefix) {
|
|
250
|
-
const instructions = await this.translationService.translateAsync('@extensions-jira:integration.auth.oauth.instructions');
|
|
251
|
-
const confirmedResult = await this.layoutBuilder
|
|
252
|
-
.create()
|
|
253
|
-
.dialog((dialog) => {
|
|
254
|
-
dialog
|
|
255
|
-
.setTitle(`${i18nPrefix}.oauth-dialog.title`)
|
|
256
|
-
.setSize('sm')
|
|
257
|
-
.setCloseButton(true)
|
|
258
|
-
.content((flex) => {
|
|
259
|
-
flex
|
|
260
|
-
.setDirection('column')
|
|
261
|
-
.setGap('12px')
|
|
262
|
-
.customWidget('text-block-layout', {
|
|
263
|
-
content: instructions ?? '',
|
|
264
|
-
});
|
|
265
|
-
})
|
|
266
|
-
.setActions((actions) => {
|
|
267
|
-
actions.cancel('@general:actions.cancel.title').submit(`${i18nPrefix}.oauth-dialog.actions.connect`);
|
|
268
|
-
})
|
|
269
|
-
.onAction(async (ref) => ref.action() !== 'cancel');
|
|
270
|
-
})
|
|
271
|
-
.show();
|
|
272
|
-
const confirmed = resolveLayoutBuilderDialogResult(confirmedResult);
|
|
273
|
-
if (!confirmed) {
|
|
274
|
-
return { success: true, kind: 'object', data: { outcome: 'cancelled' } };
|
|
275
|
-
}
|
|
276
|
-
return {
|
|
277
|
-
success: false,
|
|
278
|
-
message: {
|
|
279
|
-
text: '@extensions-jira:integration.auth.oauth.not-implemented',
|
|
280
|
-
},
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
//#endregion
|
|
284
|
-
//#region ---- Dialogs ----
|
|
285
|
-
async openPatDialog(input) {
|
|
286
|
-
const instructions = await this.translationService.translateAsync('@extensions-jira:integration.auth.pat.instructions');
|
|
287
|
-
const result = await this.layoutBuilder
|
|
288
|
-
.create()
|
|
289
|
-
.dialog((dialog) => {
|
|
290
|
-
dialog
|
|
291
|
-
.setTitle(`${input.i18nPrefix}.pat-dialog.title`)
|
|
292
|
-
.setSize('md')
|
|
293
|
-
.setCloseButton(true)
|
|
294
|
-
.setContext({ ...input.context })
|
|
295
|
-
.content((flex) => {
|
|
296
|
-
flex
|
|
297
|
-
.setDirection('column')
|
|
298
|
-
.setGap('12px')
|
|
299
|
-
.customWidget('text-block-layout', { content: instructions ?? '' })
|
|
300
|
-
.formField(`${input.i18nPrefix}.pat-dialog.fields.display-name`, (field) => {
|
|
301
|
-
field.path('displayName');
|
|
302
|
-
field.textBox({ placeholder: `${input.i18nPrefix}.pat-dialog.placeholders.display-name` });
|
|
303
|
-
})
|
|
304
|
-
.formField(`${input.i18nPrefix}.pat-dialog.fields.instance-url`, (field) => {
|
|
305
|
-
field.path('instanceUrl');
|
|
306
|
-
if (input.instanceUrlReadonly) {
|
|
307
|
-
field.readonly(true);
|
|
308
|
-
}
|
|
309
|
-
field.textBox({
|
|
310
|
-
placeholder: `${input.i18nPrefix}.pat-dialog.placeholders.instance-url`,
|
|
311
|
-
});
|
|
312
|
-
})
|
|
313
|
-
.formField(`${input.i18nPrefix}.pat-dialog.fields.token`, (field) => {
|
|
314
|
-
field.path('token');
|
|
315
|
-
field.passwordBox({
|
|
316
|
-
placeholder: `${input.i18nPrefix}.pat-dialog.placeholders.token`,
|
|
317
|
-
revealToggle: true,
|
|
318
|
-
validations: [{ rule: 'required' }],
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
})
|
|
322
|
-
.setActions((actions) => {
|
|
323
|
-
actions
|
|
324
|
-
.cancel('@general:actions.cancel.title')
|
|
325
|
-
.submit(`${input.i18nPrefix}.pat-dialog.actions.save`);
|
|
326
|
-
})
|
|
327
|
-
.onAction(async (ref) => {
|
|
328
|
-
if (ref.action() === 'cancel') {
|
|
329
|
-
return null;
|
|
330
|
-
}
|
|
331
|
-
const ctx = ref.context();
|
|
332
|
-
const token = trim(ctx.token);
|
|
333
|
-
if (!token) {
|
|
334
|
-
throw new Error('Personal access token is required.');
|
|
335
|
-
}
|
|
336
|
-
return {
|
|
337
|
-
displayName: trim(ctx.displayName),
|
|
338
|
-
instanceUrl: trim(ctx.instanceUrl),
|
|
339
|
-
token,
|
|
340
|
-
};
|
|
341
|
-
});
|
|
342
|
-
})
|
|
343
|
-
.show();
|
|
344
|
-
return resolveLayoutBuilderDialogResult(result);
|
|
345
|
-
}
|
|
346
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ConnectJiraCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
347
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ConnectJiraCommand, providedIn: 'root' }); }
|
|
348
|
-
}
|
|
349
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ConnectJiraCommand, decorators: [{
|
|
350
|
-
type: Injectable,
|
|
351
|
-
args: [{ providedIn: 'root' }]
|
|
352
|
-
}] });
|
|
353
|
-
|
|
354
|
-
export { ConnectJiraCommand };
|
|
355
|
-
//# sourceMappingURL=acorex-platform-extension-project-management-jira-client-connect-jira.command-BhnLiDk0.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-platform-extension-project-management-jira-client-connect-jira.command-BhnLiDk0.mjs","sources":["../../../../libs/extensions/project-management/jira/client/src/lib/features/connect/ui/jira-instance-picker-popup.component.ts","../../../../libs/extensions/project-management/jira/client/src/lib/features/connect/connect-jira.command.ts"],"sourcesContent":["//#region ---- Imports ----\n\nimport { AXValueChangedEvent } from '@acorex/cdk/common';\nimport { AXButtonModule } from '@acorex/components/button';\nimport { AXDecoratorModule } from '@acorex/components/decorators';\nimport { AXBasePageComponent } from '@acorex/components/page';\nimport { AXSelectionListModule } from '@acorex/components/selection-list';\nimport { AXTranslationModule } from '@acorex/core/translation';\nimport { resolveMultiLanguageString } from '@acorex-platform/framework-shared/core';\nimport type { AXEJiraInstanceEntityModel } from '@acorex-platform/extension-project-management-jira-domain';\nimport { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface AXMJiraInstancePickerPopupResult {\n instance: AXEJiraInstanceEntityModel;\n}\n\n//#endregion\n\n//#region ---- Component ----\n\n@Component({\n selector: 'axm-jira-instance-picker-popup',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [AsyncPipe, AXButtonModule, AXDecoratorModule, AXSelectionListModule, AXTranslationModule],\n template: `\n <div class=\"flex flex-col gap-2 p-4\">\n @if (instances.length === 0) {\n <p class=\"text-sm opacity-70\">\n {{ '@extensions-jira:integration.connect.instance-picker.empty' | translate | async }}\n </p>\n } @else {\n <ax-selection-list\n class=\"w-full\"\n valueField=\"id\"\n textField=\"title\"\n [direction]=\"'vertical'\"\n [look]=\"'solid'\"\n [multiple]=\"false\"\n [showControl]=\"false\"\n [items]=\"instanceListItems()\"\n [customTemplate]=\"instanceItemTemplate\"\n (onValueChanged)=\"handleInstanceSelection($event)\"\n >\n <ng-template #instanceItemTemplate let-item>\n <div class=\"flex w-full flex-col items-start gap-0.5 py-1\">\n <span class=\"font-medium\">{{ item.data.title }}</span>\n <span class=\"text-xs opacity-70\">{{ item.data.deploymentLabelKey | translate | async }}</span>\n </div>\n </ng-template>\n </ax-selection-list>\n }\n </div>\n <ax-footer>\n <ax-suffix>\n <ax-button\n look=\"outline\"\n [text]=\"'@general:actions.cancel.title' | translate | async\"\n (onClick)=\"close()\"\n ></ax-button>\n </ax-suffix>\n </ax-footer>\n `,\n})\nexport class AXMJiraInstancePickerPopupComponent extends AXBasePageComponent {\n instances: AXEJiraInstanceEntityModel[] = [];\n\n protected instanceListItems(): Array<{\n id: string;\n title: string;\n deploymentLabelKey: string;\n }> {\n return this.instances.map((instance) => ({\n id: instance.id,\n title: this.instanceTitle(instance),\n deploymentLabelKey: this.deploymentLabelKey(instance),\n }));\n }\n\n protected handleInstanceSelection(event: AXValueChangedEvent): void {\n if (!event.isUserInteraction) {\n return;\n }\n\n const instance = this.instances.find((item) => item.id === event.value);\n if (instance) {\n this.selectInstance(instance);\n }\n }\n\n protected instanceTitle(instance: AXEJiraInstanceEntityModel): string {\n return resolveMultiLanguageString(instance.title, 'en-US');\n }\n\n protected deploymentLabelKey(instance: AXEJiraInstanceEntityModel): string {\n return instance.deploymentType === 'cloud'\n ? '@extensions-jira:instances.entities.instance.fields.deployment-type.options.cloud'\n : '@extensions-jira:instances.entities.instance.fields.deployment-type.options.self-hosted';\n }\n\n protected selectInstance(instance: AXEJiraInstanceEntityModel): void {\n this.close({ instance } satisfies AXMJiraInstancePickerPopupResult);\n }\n}\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport {\n AXP_INTEGRATION_AUTH_METHOD_TYPE,\n runtimeCommandPayloadData,\n type AXPIntegrationConnectionScope,\n type AXPRuntimeCommandResult,\n type AXPSafeIntegrationConnectionDto,\n} from '@acorex-platform/framework-shared/core';\nimport {\n type ConnectCommandResult,\n} from '@acorex-platform/module-integration-management-client';\nimport { AXMIntegrationManagementCommandKeys } from '@acorex-platform/module-integration-management-client/contracts';\nimport { AXPSessionService } from '@acorex-platform/framework-client/auth';\nimport {\n AXPLayoutBuilderService,\n resolveLayoutBuilderDialogResult,\n type AXPDialogRef,\n type IActionBuilder,\n type IDialogBuilder,\n type IFlexContainerBuilder,\n type IFormFieldBuilder,\n} from '@acorex-platform/framework-client/layout/builder';\nimport { AXPEntityService } from '@acorex-platform/framework-client/layout/entity';\nimport { AXPCommandService } from '@acorex-platform/framework-client/runtime';\nimport { AXPopupService } from '@acorex/components/popup';\nimport { AXPDialogOpener } from '@acorex-platform/framework-client/core';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { Injectable, inject } from '@angular/core';\nimport { defaultTo, get, trim } from 'lodash-es';\n\nimport { RootConfig } from '@acorex-platform/extension-project-management-jira-client/contracts';\nimport type { AXEJiraInstanceEntityModel } from '@acorex-platform/extension-project-management-jira-domain';\nimport {\n AXMJiraInstancePickerPopupComponent,\n type AXMJiraInstancePickerPopupResult,\n} from './ui/jira-instance-picker-popup.component';\n\n//#endregion\n\n//#region ---- Types ----\n\nexport interface ConnectJiraCommandInput {\n providerId?: string;\n connectionScope?: AXPIntegrationConnectionScope;\n}\n\ninterface JiraPatFormContext {\n displayName: string;\n instanceUrl: string;\n token: string;\n}\n\ninterface JiraPatFormResult {\n displayName: string;\n instanceUrl: string;\n token: string;\n}\n\n//#endregion\n\n//#region ---- Command ----\n\n/** Jira connect: pick instance → self-hosted PAT or cloud OAuth2. */\n@Injectable({ providedIn: 'root' })\nexport class ConnectJiraCommand implements AXPCommand<ConnectJiraCommandInput, ConnectCommandResult> {\n //#region ---- Services & Dependencies ----\n\n private readonly popupService = inject(AXPopupService);\n private readonly dialogOpener = inject(AXPDialogOpener);\n private readonly translationService = inject(AXTranslationService);\n private readonly entityService = inject(AXPEntityService);\n private readonly layoutBuilder = inject(AXPLayoutBuilderService);\n private readonly commandService = inject(AXPCommandService);\n private readonly sessionService = inject(AXPSessionService);\n\n //#endregion\n\n //#region ---- Execute ----\n\n async execute(input: ConnectJiraCommandInput = {}): AXPCommandExecuteResultPromise<ConnectCommandResult> {\n try {\n const providerId = defaultTo(input.providerId, 'jira');\n const connectionScope: AXPIntegrationConnectionScope = input.connectionScope ?? 'tenant';\n const I18N = '@extensions-jira:integration.connect';\n\n const instance = await this.pickInstance();\n if (!instance) {\n return { success: true, kind: 'object', data: { outcome: 'cancelled' } };\n }\n\n if (instance.deploymentType === 'selfHosted') {\n return this.connectSelfHosted(providerId, connectionScope, instance, I18N);\n }\n\n return this.connectCloud(providerId, connectionScope, instance, I18N);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : 'Failed to connect Jira instance.';\n return { success: false, message: { text: message } };\n }\n }\n\n //#endregion\n\n //#region ---- Instance Picker ----\n\n private async pickInstance(): Promise<AXEJiraInstanceEntityModel | null> {\n const instances = await this.loadActiveInstances();\n let title = '';\n\n const result = await this.dialogOpener.openPopup({\n load: () => Promise.resolve(AXMJiraInstancePickerPopupComponent),\n data: { instanceIds: instances.map((instance) => instance.id) },\n prepare: async () => {\n title = await this.translationService.translateAsync(\n '@extensions-jira:integration.connect.instance-picker.title',\n );\n },\n show: (component) =>\n this.popupService.open(component, {\n title,\n size: 'sm',\n data: { instances },\n }),\n });\n\n return (result?.data as AXMJiraInstancePickerPopupResult | undefined)?.instance ?? null;\n }\n\n private async loadActiveInstances(): Promise<AXEJiraInstanceEntityModel[]> {\n const accessor = this.entityService\n .withEntity(RootConfig.module.name, RootConfig.entities.jiraInstance.name)\n .data<string, AXEJiraInstanceEntityModel>();\n\n const result = await accessor.query({\n skip: 0,\n take: 200,\n filter: {\n logic: 'and',\n filters: [{ field: 'isActive', operator: { type: 'equal' }, value: true }],\n },\n });\n\n return result.items ?? [];\n }\n\n //#endregion\n\n //#region ---- Self-Hosted (PAT) ----\n\n private async connectSelfHosted(\n providerId: string,\n connectionScope: AXPIntegrationConnectionScope,\n instance: AXEJiraInstanceEntityModel,\n i18nPrefix: string,\n ): AXPCommandExecuteResultPromise<ConnectCommandResult> {\n const form = await this.openPatDialog({\n i18nPrefix,\n context: {\n displayName: instance.name,\n instanceUrl: defaultTo(instance.baseUrl, ''),\n token: '',\n },\n instanceUrlReadonly: true,\n });\n\n if (!form) {\n return { success: true, kind: 'object', data: { outcome: 'cancelled' } };\n }\n\n const result = await this.commandService.execute<\n Record<string, unknown>,\n AXPSafeIntegrationConnectionDto\n >(AXMIntegrationManagementCommandKeys.ConnectionConnectWithCredentials, {\n providerId,\n authMethodType: AXP_INTEGRATION_AUTH_METHOD_TYPE.Pat,\n connectionScope,\n connectionKey: instance.name,\n displayName: defaultTo(trim(form.displayName), instance.name),\n instanceUrl: defaultTo(trim(form.instanceUrl), defaultTo(instance.baseUrl, '')),\n credentials: { token: form.token },\n config: { jiraInstanceId: instance.id },\n });\n\n const data = runtimeCommandPayloadData(result);\n if (!data) {\n return {\n success: false,\n message: result?.message ?? { text: 'Failed to save Jira connection.' },\n };\n }\n\n return { success: true, kind: 'object', data: { outcome: 'connected', connection: data } };\n }\n\n //#endregion\n\n //#region ---- Cloud (OAuth2) ----\n\n private async connectCloud(\n providerId: string,\n connectionScope: AXPIntegrationConnectionScope,\n instance: AXEJiraInstanceEntityModel,\n i18nPrefix: string,\n ): AXPCommandExecuteResultPromise<ConnectCommandResult> {\n const instructions = await this.translationService.translateAsync(\n '@extensions-jira:integration.auth.oauth.instructions',\n );\n\n const confirmedResult = await this.layoutBuilder\n .create()\n .dialog<boolean>((dialog: IDialogBuilder<boolean>) => {\n dialog\n .setTitle(`${i18nPrefix}.oauth-dialog.title`)\n .setSize('sm')\n .setCloseButton(true)\n .content((flex: IFlexContainerBuilder) => {\n flex\n .setDirection('column')\n .setGap('12px')\n .customWidget('text-block-layout', {\n content: instructions ?? '',\n });\n })\n .setActions((actions: IActionBuilder) => {\n actions.cancel('@general:actions.cancel.title').submit(`${i18nPrefix}.oauth-dialog.actions.connect`);\n })\n .onAction(async (ref: AXPDialogRef) => ref.action() !== 'cancel');\n })\n .show();\n\n const confirmed = resolveLayoutBuilderDialogResult<boolean>(confirmedResult);\n if (!confirmed) {\n return { success: true, kind: 'object', data: { outcome: 'cancelled' } };\n }\n\n return {\n success: false,\n message: {\n text: '@extensions-jira:integration.auth.oauth.not-implemented',\n },\n };\n }\n\n //#endregion\n\n //#region ---- Dialogs ----\n\n private async openPatDialog(input: {\n i18nPrefix: string;\n context: JiraPatFormContext;\n instanceUrlReadonly?: boolean;\n }): Promise<JiraPatFormResult | null> {\n const instructions = await this.translationService.translateAsync(\n '@extensions-jira:integration.auth.pat.instructions',\n );\n\n const result = await this.layoutBuilder\n .create()\n .dialog<JiraPatFormResult | null>((dialog: IDialogBuilder<JiraPatFormResult | null>) => {\n dialog\n .setTitle(`${input.i18nPrefix}.pat-dialog.title`)\n .setSize('md')\n .setCloseButton(true)\n .setContext({ ...input.context })\n .content((flex: IFlexContainerBuilder) => {\n flex\n .setDirection('column')\n .setGap('12px')\n .customWidget('text-block-layout', { content: instructions ?? '' })\n .formField(`${input.i18nPrefix}.pat-dialog.fields.display-name`, (field: IFormFieldBuilder) => {\n field.path('displayName');\n field.textBox({ placeholder: `${input.i18nPrefix}.pat-dialog.placeholders.display-name` });\n })\n .formField(`${input.i18nPrefix}.pat-dialog.fields.instance-url`, (field) => {\n field.path('instanceUrl');\n if (input.instanceUrlReadonly) {\n field.readonly(true);\n }\n field.textBox({\n placeholder: `${input.i18nPrefix}.pat-dialog.placeholders.instance-url`,\n });\n })\n .formField(`${input.i18nPrefix}.pat-dialog.fields.token`, (field) => {\n field.path('token');\n field.passwordBox({\n placeholder: `${input.i18nPrefix}.pat-dialog.placeholders.token`,\n revealToggle: true,\n validations: [{ rule: 'required' }],\n });\n });\n })\n .setActions((actions: IActionBuilder) => {\n actions\n .cancel('@general:actions.cancel.title')\n .submit(`${input.i18nPrefix}.pat-dialog.actions.save`);\n })\n .onAction(async (ref: AXPDialogRef) => {\n if (ref.action() === 'cancel') {\n return null;\n }\n const ctx = ref.context() as JiraPatFormContext;\n const token = trim(ctx.token);\n if (!token) {\n throw new Error('Personal access token is required.');\n }\n return {\n displayName: trim(ctx.displayName),\n instanceUrl: trim(ctx.instanceUrl),\n token,\n };\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<JiraPatFormResult>(result);\n }\n\n //#endregion\n}\n\n//#endregion\n"],"names":["i2","i4"],"mappings":"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"}
|