@acorex-platform/module-integration-management-client 0.0.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-module-integration-management-client-connect-with-credentials.command-DO_zqjHV.mjs +102 -0
- package/fesm2022/acorex-platform-module-integration-management-client-connect-with-credentials.command-DO_zqjHV.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-contracts.mjs +163 -0
- package/fesm2022/acorex-platform-module-integration-management-client-contracts.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-delete-connection.command-DQ_kn8dH.mjs +53 -0
- package/fesm2022/acorex-platform-module-integration-management-client-delete-connection.command-DQ_kn8dH.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-disconnect-connection.command-B4HeDA1n.mjs +60 -0
- package/fesm2022/acorex-platform-module-integration-management-client-disconnect-connection.command-B4HeDA1n.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-get-provider.query-Ds10RwnU.mjs +30 -0
- package/fesm2022/acorex-platform-module-integration-management-client-get-provider.query-Ds10RwnU.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-integration-connection-lifecycle.dispatcher-DRWR9ysx.mjs +45 -0
- package/fesm2022/acorex-platform-module-integration-management-client-integration-connection-lifecycle.dispatcher-DRWR9ysx.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-integration-oauth-callback-page.component-XhloXUsZ.mjs +176 -0
- package/fesm2022/acorex-platform-module-integration-management-client-integration-oauth-callback-page.component-XhloXUsZ.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-integrations-page.component-Q-SHidYA.mjs +406 -0
- package/fesm2022/acorex-platform-module-integration-management-client-integrations-page.component-Q-SHidYA.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-list-domains.query--GGD6J46.mjs +52 -0
- package/fesm2022/acorex-platform-module-integration-management-client-list-domains.query--GGD6J46.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-list-my-connections.query-CmHu1qFm.mjs +27 -0
- package/fesm2022/acorex-platform-module-integration-management-client-list-my-connections.query-CmHu1qFm.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-list-providers.query-ODKJ_UhI.mjs +65 -0
- package/fesm2022/acorex-platform-module-integration-management-client-list-providers.query-ODKJ_UhI.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-update-connection.command-BNMR-t12.mjs +42 -0
- package/fesm2022/acorex-platform-module-integration-management-client-update-connection.command-BNMR-t12.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client-validate-connection.command-CGtb_GPX.mjs +83 -0
- package/fesm2022/acorex-platform-module-integration-management-client-validate-connection.command-CGtb_GPX.mjs.map +1 -0
- package/fesm2022/acorex-platform-module-integration-management-client.mjs +776 -0
- package/fesm2022/acorex-platform-module-integration-management-client.mjs.map +1 -0
- package/package.json +28 -0
- package/types/acorex-platform-module-integration-management-client-contracts.d.ts +191 -0
- package/types/acorex-platform-module-integration-management-client.d.ts +74 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import * as i2 from '@acorex/components/badge';
|
|
2
|
+
import { AXBadgeModule } from '@acorex/components/badge';
|
|
3
|
+
import * as i3 from '@acorex/components/button';
|
|
4
|
+
import { AXButtonModule } from '@acorex/components/button';
|
|
5
|
+
import * as i4 from '@acorex/components/check-box';
|
|
6
|
+
import { AXCheckBoxModule } from '@acorex/components/check-box';
|
|
7
|
+
import * as i5 from '@acorex/components/dropdown-button';
|
|
8
|
+
import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
|
|
9
|
+
import * as i6 from '@acorex/components/decorators';
|
|
10
|
+
import { AXDecoratorModule } from '@acorex/components/decorators';
|
|
11
|
+
import * as i7 from '@acorex/components/label';
|
|
12
|
+
import { AXLabelModule } from '@acorex/components/label';
|
|
13
|
+
import * as i8 from '@acorex/components/skeleton';
|
|
14
|
+
import { AXSkeletonModule } from '@acorex/components/skeleton';
|
|
15
|
+
import * as i9 from '@acorex/components/switch';
|
|
16
|
+
import { AXSwitchModule } from '@acorex/components/switch';
|
|
17
|
+
import * as i10 from '@acorex/components/tooltip';
|
|
18
|
+
import { AXTooltipModule } from '@acorex/components/tooltip';
|
|
19
|
+
import * as i11 from '@acorex/core/translation';
|
|
20
|
+
import { AXTranslationModule } from '@acorex/core/translation';
|
|
21
|
+
import { AXPDeviceService, AXPLogoComponent } from '@acorex-platform/framework-client/core';
|
|
22
|
+
import { AXPStateMessageComponent, AXPThemeLayoutBlockComponent, AXPThemeLayoutStartSideComponent } from '@acorex-platform/framework-client/layout/components';
|
|
23
|
+
import { AXPIntegrationConnectionActionsService } from '@acorex-platform/framework-client/layout/widgets';
|
|
24
|
+
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageLayoutBase } from '@acorex-platform/framework-client/layout/views';
|
|
25
|
+
import { AXPQueryService } from '@acorex-platform/framework-client/runtime';
|
|
26
|
+
import { AXP_INTEGRATION_CONNECTION_STATUS, AXP_INTEGRATION_CONNECTION_SCOPE, runtimeQueryCollectionData } from '@acorex-platform/framework-shared/core';
|
|
27
|
+
import { AsyncPipe } from '@angular/common';
|
|
28
|
+
import * as i0 from '@angular/core';
|
|
29
|
+
import { inject, signal, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
30
|
+
import * as i1 from '@angular/forms';
|
|
31
|
+
import { FormsModule } from '@angular/forms';
|
|
32
|
+
|
|
33
|
+
//#region ----- Imports -----
|
|
34
|
+
const ERROR_CONNECTION_STATUSES = new Set([
|
|
35
|
+
AXP_INTEGRATION_CONNECTION_STATUS.Error,
|
|
36
|
+
AXP_INTEGRATION_CONNECTION_STATUS.Invalid,
|
|
37
|
+
AXP_INTEGRATION_CONNECTION_STATUS.Expired,
|
|
38
|
+
AXP_INTEGRATION_CONNECTION_STATUS.RefreshRequired,
|
|
39
|
+
AXP_INTEGRATION_CONNECTION_STATUS.PendingAuthorization,
|
|
40
|
+
AXP_INTEGRATION_CONNECTION_STATUS.Revoked,
|
|
41
|
+
]);
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region ----- Constants -----
|
|
44
|
+
const PAGE_I18N = '@integration-management:pages.integrations';
|
|
45
|
+
const PANEL_I18N = '@platform-layout-widgets:widgets.integration-connections-panel';
|
|
46
|
+
const TENANT_SCOPE = AXP_INTEGRATION_CONNECTION_SCOPE.Tenant;
|
|
47
|
+
const SKELETON_SECTION_COUNT = 2;
|
|
48
|
+
const SKELETON_CARDS_PER_SECTION = 4;
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region ----- Component -----
|
|
51
|
+
class AXMIntegrationsPageComponent extends AXPPageLayoutBaseComponent {
|
|
52
|
+
constructor() {
|
|
53
|
+
super(...arguments);
|
|
54
|
+
//#region ----- Services & Dependencies -----
|
|
55
|
+
this.queryService = inject(AXPQueryService);
|
|
56
|
+
this.actionsService = inject(AXPIntegrationConnectionActionsService);
|
|
57
|
+
this.deviceService = inject(AXPDeviceService);
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region ----- Constants -----
|
|
60
|
+
this.PAGE_I18N = PAGE_I18N;
|
|
61
|
+
this.PANEL_I18N = PANEL_I18N;
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region ----- State Signals -----
|
|
64
|
+
this.loading = signal(true, /* @ts-ignore */
|
|
65
|
+
...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
66
|
+
this.pendingAction = signal(false, /* @ts-ignore */
|
|
67
|
+
...(ngDevMode ? [{ debugName: "pendingAction" }] : /* istanbul ignore next */ []));
|
|
68
|
+
this.domainSections = signal([], /* @ts-ignore */
|
|
69
|
+
...(ngDevMode ? [{ debugName: "domainSections" }] : /* istanbul ignore next */ []));
|
|
70
|
+
this.selectedDomainIds = signal(new Set(), /* @ts-ignore */
|
|
71
|
+
...(ngDevMode ? [{ debugName: "selectedDomainIds" }] : /* istanbul ignore next */ []));
|
|
72
|
+
this.panelData = signal({
|
|
73
|
+
providers: [],
|
|
74
|
+
connections: [],
|
|
75
|
+
providerBadges: {},
|
|
76
|
+
connectAvailabilityByProvider: {},
|
|
77
|
+
}, /* @ts-ignore */
|
|
78
|
+
...(ngDevMode ? [{ debugName: "panelData" }] : /* istanbul ignore next */ []));
|
|
79
|
+
this.skeletonSectionPlaceholders = Array.from({ length: SKELETON_SECTION_COUNT }, (_, index) => index);
|
|
80
|
+
this.skeletonCardPlaceholders = Array.from({ length: SKELETON_CARDS_PER_SECTION }, (_, index) => index);
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region ----- Sidebar Computed -----
|
|
83
|
+
this.overviewStats = computed(() => {
|
|
84
|
+
const providers = this.domainSections().flatMap((section) => section.providers);
|
|
85
|
+
const connections = this.panelData().connections;
|
|
86
|
+
let connected = 0;
|
|
87
|
+
let error = 0;
|
|
88
|
+
let disabled = 0;
|
|
89
|
+
let notConnected = 0;
|
|
90
|
+
for (const provider of providers) {
|
|
91
|
+
if (this.actionsService.isConnectionEnabled(connections, provider.id, TENANT_SCOPE)) {
|
|
92
|
+
connected += 1;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (this.actionsService.hasEstablishedConnection(connections, provider.id, TENANT_SCOPE)) {
|
|
96
|
+
if (this.isProviderInError(connections, provider.id)) {
|
|
97
|
+
error += 1;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
disabled += 1;
|
|
101
|
+
}
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
notConnected += 1;
|
|
105
|
+
}
|
|
106
|
+
return { connected, error, disabled, notConnected };
|
|
107
|
+
}, /* @ts-ignore */
|
|
108
|
+
...(ngDevMode ? [{ debugName: "overviewStats" }] : /* istanbul ignore next */ []));
|
|
109
|
+
this.isAllDomainsSelected = computed(() => {
|
|
110
|
+
const sections = this.domainSections();
|
|
111
|
+
const selected = this.selectedDomainIds();
|
|
112
|
+
if (!sections.length) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
return sections.every((section) => selected.has(section.domain.id));
|
|
116
|
+
}, /* @ts-ignore */
|
|
117
|
+
...(ngDevMode ? [{ debugName: "isAllDomainsSelected" }] : /* istanbul ignore next */ []));
|
|
118
|
+
this.filteredDomainSections = computed(() => {
|
|
119
|
+
const selected = this.selectedDomainIds();
|
|
120
|
+
if (!selected.size) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
return this.domainSections().filter((section) => selected.has(section.domain.id));
|
|
124
|
+
}, /* @ts-ignore */
|
|
125
|
+
...(ngDevMode ? [{ debugName: "filteredDomainSections" }] : /* istanbul ignore next */ []));
|
|
126
|
+
this.visibleDomainSections = computed(() => {
|
|
127
|
+
if (!this.deviceService.isLarge()) {
|
|
128
|
+
return this.domainSections();
|
|
129
|
+
}
|
|
130
|
+
return this.filteredDomainSections();
|
|
131
|
+
}, /* @ts-ignore */
|
|
132
|
+
...(ngDevMode ? [{ debugName: "visibleDomainSections" }] : /* istanbul ignore next */ []));
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region ----- Lifecycle -----
|
|
136
|
+
async ngOnInit() {
|
|
137
|
+
super.ngOnInit();
|
|
138
|
+
await this.loadPage();
|
|
139
|
+
}
|
|
140
|
+
async getPageTitle() {
|
|
141
|
+
return this.translateService.translateAsync(`${PAGE_I18N}.title`);
|
|
142
|
+
}
|
|
143
|
+
async getPageDescription() {
|
|
144
|
+
return this.translateService.translateAsync(`${PAGE_I18N}.description`);
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region ----- Connection Helpers -----
|
|
148
|
+
getConnections(providerId) {
|
|
149
|
+
return this.actionsService.getConnections(this.panelData().connections, providerId, TENANT_SCOPE);
|
|
150
|
+
}
|
|
151
|
+
getConnection(providerId) {
|
|
152
|
+
return this.actionsService.getConnection(this.panelData().connections, providerId, TENANT_SCOPE);
|
|
153
|
+
}
|
|
154
|
+
hasEstablishedConnection(providerId) {
|
|
155
|
+
return this.actionsService.hasEstablishedConnection(this.panelData().connections, providerId, TENANT_SCOPE);
|
|
156
|
+
}
|
|
157
|
+
isConnectionEnabled(providerId) {
|
|
158
|
+
return this.actionsService.isConnectionEnabled(this.panelData().connections, providerId, TENANT_SCOPE);
|
|
159
|
+
}
|
|
160
|
+
isEstablishedConnection(connection) {
|
|
161
|
+
return this.actionsService.isEstablishedConnection(connection);
|
|
162
|
+
}
|
|
163
|
+
isEnabledConnection(connection) {
|
|
164
|
+
return this.actionsService.isEnabledConnection(connection);
|
|
165
|
+
}
|
|
166
|
+
getProviderConnectionSummary(providerId) {
|
|
167
|
+
const connections = this.getConnections(providerId);
|
|
168
|
+
return {
|
|
169
|
+
connected: connections.filter((connection) => this.isEstablishedConnection(connection)).length,
|
|
170
|
+
total: connections.length,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
getMultiConnectionStatusBadgeColor(providerId) {
|
|
174
|
+
const { connected, total } = this.getProviderConnectionSummary(providerId);
|
|
175
|
+
if (total === 0 || connected === 0) {
|
|
176
|
+
return 'secondary';
|
|
177
|
+
}
|
|
178
|
+
if (connected === total) {
|
|
179
|
+
return 'success';
|
|
180
|
+
}
|
|
181
|
+
return 'warning';
|
|
182
|
+
}
|
|
183
|
+
supportsConnect(provider) {
|
|
184
|
+
return this.actionsService.supportsConnect(provider);
|
|
185
|
+
}
|
|
186
|
+
supportsConfigure(provider, connection) {
|
|
187
|
+
return this.actionsService.supportsConfigure(provider, this.panelData().connections, TENANT_SCOPE, connection);
|
|
188
|
+
}
|
|
189
|
+
isConnectDisabled(providerId) {
|
|
190
|
+
return this.actionsService.isConnectDisabled(this.panelData().connectAvailabilityByProvider, providerId);
|
|
191
|
+
}
|
|
192
|
+
connectDisabledBadgeKey(providerId) {
|
|
193
|
+
return (this.panelData().connectAvailabilityByProvider[providerId]?.disabledBadgeKey
|
|
194
|
+
?? this.panelData().providers.find((provider) => provider.id === providerId)?.connectDisabledBadgeKey);
|
|
195
|
+
}
|
|
196
|
+
connectDisabledMessageKey(providerId) {
|
|
197
|
+
return (this.panelData().connectAvailabilityByProvider[providerId]?.disabledMessageKey
|
|
198
|
+
?? this.panelData().providers.find((provider) => provider.id === providerId)?.connectDisabledMessageKey);
|
|
199
|
+
}
|
|
200
|
+
getProviderBadges(providerId) {
|
|
201
|
+
return this.panelData().providerBadges[providerId] ?? [];
|
|
202
|
+
}
|
|
203
|
+
getManageActions(provider) {
|
|
204
|
+
return this.actionsService.getManageActions(provider, TENANT_SCOPE);
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region ----- Sidebar Filters -----
|
|
208
|
+
showSidebarPanel() {
|
|
209
|
+
return this.deviceService.isLarge();
|
|
210
|
+
}
|
|
211
|
+
isDomainFilterSelected(domainId) {
|
|
212
|
+
return this.selectedDomainIds().has(domainId);
|
|
213
|
+
}
|
|
214
|
+
handleAllDomainsFilterChange(event) {
|
|
215
|
+
if (event.value) {
|
|
216
|
+
this.selectAllDomainFilters();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
this.selectedDomainIds.set(new Set());
|
|
220
|
+
}
|
|
221
|
+
handleSelectAllDomainFilters() {
|
|
222
|
+
this.selectAllDomainFilters();
|
|
223
|
+
}
|
|
224
|
+
handleDomainFilterChange(domainId, event) {
|
|
225
|
+
const next = new Set(this.selectedDomainIds());
|
|
226
|
+
if (event.value) {
|
|
227
|
+
next.add(domainId);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
next.delete(domainId);
|
|
231
|
+
}
|
|
232
|
+
this.selectedDomainIds.set(next);
|
|
233
|
+
}
|
|
234
|
+
selectAllDomainFilters() {
|
|
235
|
+
this.selectedDomainIds.set(new Set(this.domainSections().map((section) => section.domain.id)));
|
|
236
|
+
}
|
|
237
|
+
//#endregion
|
|
238
|
+
//#region ----- Event Handlers -----
|
|
239
|
+
async handleConnect(provider, connection) {
|
|
240
|
+
if (this.pendingAction()) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
this.pendingAction.set(true);
|
|
244
|
+
try {
|
|
245
|
+
const outcome = await this.actionsService.connect(provider, {
|
|
246
|
+
connectionScope: TENANT_SCOPE,
|
|
247
|
+
connectAvailabilityByProvider: this.panelData().connectAvailabilityByProvider,
|
|
248
|
+
...(connection?.id ? { connectionId: connection.id } : {}),
|
|
249
|
+
});
|
|
250
|
+
if (outcome === 'reload') {
|
|
251
|
+
await this.loadPage(false);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
this.actionsService.releasePendingAction(() => this.pendingAction.set(false));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async handleAddConnection(provider) {
|
|
259
|
+
await this.handleConnect(provider);
|
|
260
|
+
}
|
|
261
|
+
async handleConfigure(provider, connection) {
|
|
262
|
+
await this.handleConnect(provider, connection ?? this.getConnection(provider.id));
|
|
263
|
+
}
|
|
264
|
+
async handleManageAction(provider, action, connection) {
|
|
265
|
+
if (this.pendingAction()) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
this.pendingAction.set(true);
|
|
269
|
+
try {
|
|
270
|
+
const success = await this.actionsService.runManageAction(provider, action, TENANT_SCOPE, connection?.id);
|
|
271
|
+
if (success) {
|
|
272
|
+
await this.loadPage(false);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
finally {
|
|
276
|
+
this.actionsService.releasePendingAction(() => this.pendingAction.set(false));
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async handleDisconnect(provider, connection) {
|
|
280
|
+
if (this.pendingAction()) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const target = connection ?? this.getConnection(provider.id);
|
|
284
|
+
if (!target) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
this.pendingAction.set(true);
|
|
288
|
+
try {
|
|
289
|
+
const success = await this.actionsService.disconnect(provider, target);
|
|
290
|
+
if (success) {
|
|
291
|
+
await this.loadPage(false);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
finally {
|
|
295
|
+
this.actionsService.releasePendingAction(() => this.pendingAction.set(false));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async handleRemove(provider, connection) {
|
|
299
|
+
if (this.pendingAction()) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
this.pendingAction.set(true);
|
|
303
|
+
try {
|
|
304
|
+
const success = await this.actionsService.remove(provider, connection);
|
|
305
|
+
if (success) {
|
|
306
|
+
await this.loadPage(false);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
this.actionsService.releasePendingAction(() => this.pendingAction.set(false));
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async handleToggleEnabled(provider, enabled, connection) {
|
|
314
|
+
if (this.pendingAction()) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const target = connection ?? this.getConnection(provider.id);
|
|
318
|
+
if (!target || !this.isEstablishedConnection(target)) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if (this.isEnabledConnection(target) === enabled) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
this.pendingAction.set(true);
|
|
325
|
+
try {
|
|
326
|
+
const success = await this.actionsService.setConnectionEnabled(target.id, enabled);
|
|
327
|
+
if (success) {
|
|
328
|
+
await this.loadPage(false);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
finally {
|
|
332
|
+
this.actionsService.releasePendingAction(() => this.pendingAction.set(false));
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
//#endregion
|
|
336
|
+
//#region ----- Data Loading -----
|
|
337
|
+
async loadPage(showBlockingLoader = true) {
|
|
338
|
+
if (showBlockingLoader) {
|
|
339
|
+
this.loading.set(true);
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
await this.actionsService.waitForSettingsLoaded();
|
|
343
|
+
const [domainsResult, panelData] = await Promise.all([
|
|
344
|
+
this.queryService.fetch('IntegrationManagement.Domain:List', { includeProviderCount: false }),
|
|
345
|
+
this.actionsService.loadPanelData({ connectionScope: TENANT_SCOPE }),
|
|
346
|
+
]);
|
|
347
|
+
const domains = runtimeQueryCollectionData(domainsResult)?.items ?? [];
|
|
348
|
+
const sections = [];
|
|
349
|
+
for (const domain of [...domains].sort((left, right) => (left.sortOrder ?? 100) - (right.sortOrder ?? 100))) {
|
|
350
|
+
const providers = panelData.providers.filter((provider) => provider.domainId === domain.id && provider.connectionScopes.includes(TENANT_SCOPE));
|
|
351
|
+
if (!providers.length) {
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
sections.push({ domain, providers });
|
|
355
|
+
}
|
|
356
|
+
this.domainSections.set(sections);
|
|
357
|
+
this.selectAllDomainFilters();
|
|
358
|
+
this.panelData.set(panelData);
|
|
359
|
+
this.recompute();
|
|
360
|
+
}
|
|
361
|
+
finally {
|
|
362
|
+
if (showBlockingLoader) {
|
|
363
|
+
this.loading.set(false);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
//#endregion
|
|
368
|
+
//#region ----- Overview Helpers -----
|
|
369
|
+
isProviderInError(connections, providerId) {
|
|
370
|
+
const providerConnections = this.actionsService.getConnections(connections, providerId, TENANT_SCOPE);
|
|
371
|
+
return providerConnections.some((connection) => {
|
|
372
|
+
if (connection.isRevoked || ERROR_CONNECTION_STATUSES.has(connection.status)) {
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
return Boolean(String(connection.lastErrorCode ?? '').trim()
|
|
376
|
+
|| String(connection.lastErrorMessage ?? '').trim());
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMIntegrationsPageComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
380
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMIntegrationsPageComponent, isStandalone: true, selector: "axm-integrations-page", providers: [{ provide: AXPPageLayoutBase, useExisting: AXMIntegrationsPageComponent }], usesInheritance: true, ngImport: i0, template: "<axp-page-layout>\n <!-- ----- Page start side: overview stats and category filters (large screens) ----- -->\n @if (showSidebarPanel()) {\n <axp-layout-start-side class=\"h-full\">\n <axp-layout-content class=\"axm-integrations-page__sidebar\">\n @if (loading()) {\n <!-- ----- Sidebar skeleton while domains and providers load ----- -->\n <section class=\"axm-integrations-page__sidebar-section\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-sidebar-title\"></ax-skeleton>\n <div class=\"axm-integrations-page__sidebar-section-body\">\n @for (row of [0, 1, 2, 3]; track row) {\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-sidebar-row\"></ax-skeleton>\n }\n </div>\n </section>\n <section class=\"axm-integrations-page__sidebar-section\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-sidebar-title\"></ax-skeleton>\n <div class=\"axm-integrations-page__sidebar-section-body\">\n @for (row of [0, 1, 2, 3, 4]; track row) {\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-sidebar-row\"></ax-skeleton>\n }\n </div>\n </section>\n } @else {\n <section class=\"axm-integrations-page__sidebar-section\">\n <h3 class=\"axm-integrations-page__sidebar-section-title\">\n {{ (PAGE_I18N + '.sidebar.overview.title' | translate | async) ?? '' }}\n </h3>\n <ul class=\"axm-integrations-page__overview-list\">\n <li class=\"axm-integrations-page__overview-item\">\n <span class=\"axm-integrations-page__overview-label\">\n <ax-icon icon=\"fa-light fa-circle-check\"></ax-icon>\n <span>{{ (PAGE_I18N + '.sidebar.overview.connected' | translate | async) ?? '' }}</span>\n </span>\n <span class=\"axm-integrations-page__overview-count\">{{ overviewStats().connected }}</span>\n </li>\n <li class=\"axm-integrations-page__overview-item\">\n <span class=\"axm-integrations-page__overview-label\">\n <ax-icon icon=\"fa-light fa-shield-exclamation\"></ax-icon>\n <span>{{ (PAGE_I18N + '.sidebar.overview.error' | translate | async) ?? '' }}</span>\n </span>\n <span class=\"axm-integrations-page__overview-count\" [class.--danger]=\"overviewStats().error > 0\">{{ overviewStats().error }}</span>\n </li>\n <li class=\"axm-integrations-page__overview-item\">\n <span class=\"axm-integrations-page__overview-label\">\n <ax-icon icon=\"fa-light fa-toggle-off\"></ax-icon>\n <span>{{ (PAGE_I18N + '.sidebar.overview.disabled' | translate | async) ?? '' }}</span>\n </span>\n <span class=\"axm-integrations-page__overview-count\">{{ overviewStats().disabled }}</span>\n </li>\n <li class=\"axm-integrations-page__overview-item\">\n <span class=\"axm-integrations-page__overview-label\">\n <ax-icon icon=\"fa-light fa-plug\"></ax-icon>\n <span>{{ (PAGE_I18N + '.sidebar.overview.not-connected' | translate | async) ?? '' }}</span>\n </span>\n <span class=\"axm-integrations-page__overview-count\">{{ overviewStats().notConnected }}</span>\n </li>\n </ul>\n </section>\n\n <section class=\"axm-integrations-page__sidebar-section\">\n <h3 class=\"axm-integrations-page__sidebar-section-title\">\n {{ (PAGE_I18N + '.sidebar.categories.title' | translate | async) ?? '' }}\n </h3>\n <ul class=\"axm-integrations-page__category-list\">\n <li class=\"axm-integrations-page__category-item\">\n <ax-check-box\n class=\"axm-integrations-page__category-checkbox\"\n [ngModel]=\"isAllDomainsSelected()\"\n (onValueChanged)=\"handleAllDomainsFilterChange($event)\"\n >\n <ax-label>{{ (PAGE_I18N + '.sidebar.categories.all' | translate | async) ?? '' }}</ax-label>\n </ax-check-box>\n </li>\n @for (section of domainSections(); track section.domain.id) {\n <li class=\"axm-integrations-page__category-item\">\n <ax-check-box\n class=\"axm-integrations-page__category-checkbox\"\n [ngModel]=\"isDomainFilterSelected(section.domain.id)\"\n (onValueChanged)=\"handleDomainFilterChange(section.domain.id, $event)\"\n >\n <ax-label>{{ section.domain.displayName | translate | async }}</ax-label>\n </ax-check-box>\n </li>\n }\n </ul>\n </section>\n }\n </axp-layout-content>\n </axp-layout-start-side>\n }\n\n <axp-page-content>\n @if (loading()) {\n <!-- ----- Skeleton placeholders while domains and providers are fetched ----- -->\n <div class=\"flex w-full flex-col gap-8\">\n @for (sectionIndex of skeletonSectionPlaceholders; track sectionIndex) {\n <section class=\"flex flex-col gap-4\">\n <div class=\"flex flex-col gap-2\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-section-title\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-section-description\"></ax-skeleton>\n </div>\n\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-[repeat(auto-fill,minmax(16rem,18rem))] lg:justify-start\">\n @for (cardIndex of skeletonCardPlaceholders; track cardIndex) {\n <div class=\"axm-integrations-page__skeleton-card\">\n <div class=\"flex items-start justify-between gap-3\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-icon\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-status-badge\"></ax-skeleton>\n </div>\n\n <div class=\"flex flex-col gap-2\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-title\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-description\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-description --short\"></ax-skeleton>\n </div>\n\n <div class=\"axm-integrations-page__skeleton-footer\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-action\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-switch\"></ax-skeleton>\n </div>\n </div>\n }\n </div>\n </section>\n }\n </div>\n } @else if (!visibleDomainSections().length) {\n <!-- ----- Empty state when all category filters are cleared on large screens ----- -->\n <axp-state-message mode=\"empty\" icon=\"fa-light fa-filter\" [title]=\"PAGE_I18N + '.sidebar.empty-filter.title'\" [description]=\"PAGE_I18N + '.sidebar.empty-filter.description'\">\n <ax-button slot=\"actions\" look=\"solid\" color=\"primary\" [text]=\"(PAGE_I18N + '.sidebar.empty-filter.action' | translate | async) ?? ''\" (onClick)=\"handleSelectAllDomainFilters()\"></ax-button>\n </axp-state-message>\n } @else {\n <!-- ----- Domain sections with tenant provider cards ----- -->\n <div class=\"flex w-full flex-col gap-8\">\n @for (section of visibleDomainSections(); track section.domain.id) {\n <section class=\"flex flex-col gap-4\">\n <div class=\"flex flex-col gap-1\">\n <h2 class=\"text-lg font-semibold\">\n {{ section.domain.displayName | translate | async }}\n </h2>\n @if (section.domain.description) {\n <p class=\"text-sm text-muted\">\n {{ section.domain.description | translate | async }}\n </p>\n }\n </div>\n\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-[repeat(auto-fill,minmax(18rem,24rem))] lg:justify-start\">\n @for (provider of section.providers; track provider.id) {\n <article class=\"flex h-full w-full flex-col gap-3 rounded-xl border border-surface bg-lighter-surface p-4 shadow-sm transition-shadow hover:shadow-md\">\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"flex size-14 shrink-0 items-center justify-center rounded-xl border border-surface bg-transparent\">\n @if (provider.logoKey) {\n <axp-logo [logoKey]=\"provider.logoKey\" appearance=\"colored\" [size]=\"32\" />\n } @else if (provider.icon) {\n <ax-icon class=\"text-2xl\">\n <i [class]=\"provider.icon\"></i>\n </ax-icon>\n }\n </div>\n\n <div class=\"ax-sm\">\n @if (provider.allowMultipleConnections) {\n @if (getProviderConnectionSummary(provider.id); as summary) {\n @if (summary.total > 0) {\n <ax-badge\n look=\"twotone\"\n [color]=\"getMultiConnectionStatusBadgeColor(provider.id)\"\n [text]=\"(PANEL_I18N + '.status.connected-count' | translate: { params: { connected: summary.connected, total: summary.total } } | async) ?? ''\"\n ></ax-badge>\n } @else {\n <ax-badge look=\"twotone\" color=\"secondary\" [text]=\"(PANEL_I18N + '.status.not-connected' | translate | async) ?? ''\"></ax-badge>\n }\n }\n } @else if (hasEstablishedConnection(provider.id)) {\n @if (isConnectionEnabled(provider.id)) {\n <ax-badge look=\"twotone\" color=\"success\" [text]=\"(PANEL_I18N + '.status.connected' | translate | async) ?? ''\"></ax-badge>\n } @else {\n <ax-badge look=\"twotone\" color=\"warning\" [text]=\"(PANEL_I18N + '.status.disabled' | translate | async) ?? ''\"></ax-badge>\n }\n } @else {\n <ax-badge look=\"twotone\" color=\"secondary\" [text]=\"(PANEL_I18N + '.status.not-connected' | translate | async) ?? ''\"></ax-badge>\n }\n </div>\n </div>\n\n <div class=\"flex min-w-0 flex-1 flex-col gap-2\">\n <div class=\"flex flex-wrap items-center gap-2 font-medium\">\n <span>{{ provider.displayName | translate | async }}</span>\n @if (isConnectDisabled(provider.id) && connectDisabledBadgeKey(provider.id); as badgeKey) {\n <span\n class=\"inline-flex cursor-help\"\n [axTooltip]=\"(connectDisabledMessageKey(provider.id) | translate | async) ?? ''\"\n axTooltipPlacement=\"top\"\n [attr.aria-label]=\"(connectDisabledMessageKey(provider.id) | translate | async) ?? ''\"\n >\n <ax-badge size=\"sm\" look=\"twotone\" color=\"warning\" [text]=\"(badgeKey | translate | async) ?? ''\"></ax-badge>\n </span>\n }\n </div>\n\n @if (provider.description) {\n <p class=\"text-sm text-muted\">\n {{ provider.description | translate | async }}\n </p>\n }\n\n @if (getProviderBadges(provider.id); as badges) {\n @if (badges.length > 0) {\n <div class=\"flex flex-wrap items-center gap-1\">\n @for (badge of badges; track badge.text) {\n <ax-badge size=\"sm\" look=\"twotone\" [color]=\"badge.color\" [text]=\"badge.text\"></ax-badge>\n }\n </div>\n }\n }\n\n <!-- ----- Multi-connection provider: list each connection with status and actions ----- -->\n @if (provider.allowMultipleConnections) {\n <div class=\"mt-1 flex flex-col gap-2\">\n @for (connection of getConnections(provider.id); track connection.id) {\n <div class=\"flex flex-col gap-2 rounded-lg border border-surface bg-lighter-surface p-3\">\n <!-- ----- Row 1: connection identity + status badge ----- -->\n <div class=\"flex items-start justify-between gap-2\">\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-medium\">{{ connection.displayName }}</div>\n @if (connection.instanceUrl) {\n <div class=\"truncate text-xs text-muted\">{{ connection.instanceUrl }}</div>\n }\n </div>\n <div class=\"ax-sm shrink-0\">\n @if (isEstablishedConnection(connection)) {\n @if (isEnabledConnection(connection)) {\n <ax-badge look=\"twotone\" color=\"success\" [text]=\"(PANEL_I18N + '.status.connected' | translate | async) ?? ''\"></ax-badge>\n } @else {\n <ax-badge look=\"twotone\" color=\"warning\" [text]=\"(PANEL_I18N + '.status.disabled' | translate | async) ?? ''\"></ax-badge>\n }\n } @else {\n <ax-badge look=\"twotone\" color=\"secondary\" [text]=\"(PANEL_I18N + '.status.not-connected' | translate | async) ?? ''\"></ax-badge>\n }\n </div>\n </div>\n\n <!-- ----- Row 2: actions + enable toggle ----- -->\n <div class=\"flex flex-nowrap items-center justify-between gap-2\">\n <div class=\"flex shrink-0 flex-nowrap items-center gap-2\">\n @if (isEstablishedConnection(connection)) {\n <ax-dropdown-button\n size=\"sm\"\n look=\"outline\"\n [mode]=\"'dropdown'\"\n type=\"button\"\n [disabled]=\"pendingAction()\"\n [text]=\"(PANEL_I18N + '.actions.manage' | translate | async) ?? ''\"\n >\n <ax-button-item-list>\n @if (supportsConfigure(provider, connection)) {\n <ax-button-item\n [text]=\"(PANEL_I18N + '.actions.reconfigure' | translate | async) ?? ''\"\n [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\"\n (onClick)=\"handleConfigure(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n <ax-button-item\n [text]=\"(PANEL_I18N + '.actions.disconnect' | translate | async) ?? ''\"\n color=\"danger\"\n [disabled]=\"pendingAction()\"\n (onClick)=\"handleDisconnect(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-link-slash\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"(PANEL_I18N + '.actions.remove' | translate | async) ?? ''\"\n color=\"danger\"\n [disabled]=\"pendingAction()\"\n (onClick)=\"handleRemove(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-button>\n } @else if (supportsConnect(provider)) {\n <ax-button\n size=\"sm\"\n look=\"solid\"\n type=\"button\"\n [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\"\n [text]=\"(PANEL_I18N + '.actions.connect' | translate | async) ?? ''\"\n (onClick)=\"handleConnect(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-plug\"></ax-icon>\n </ax-prefix>\n </ax-button>\n <ax-button\n size=\"sm\"\n look=\"outline\"\n color=\"danger\"\n type=\"button\"\n [disabled]=\"pendingAction()\"\n [text]=\"(PANEL_I18N + '.actions.remove' | translate | async) ?? ''\"\n (onClick)=\"handleRemove(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash\"></ax-icon>\n </ax-prefix>\n </ax-button>\n } @else {\n <ax-button\n size=\"sm\"\n look=\"outline\"\n color=\"danger\"\n type=\"button\"\n [disabled]=\"pendingAction()\"\n [text]=\"(PANEL_I18N + '.actions.remove' | translate | async) ?? ''\"\n (onClick)=\"handleRemove(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <ax-switch\n class=\"shrink-0\"\n [ngModel]=\"isEnabledConnection(connection)\"\n [disabled]=\"pendingAction() || !isEstablishedConnection(connection)\"\n (ngModelChange)=\"handleToggleEnabled(provider, $event, connection)\"\n ></ax-switch>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- ----- Card footer: single-connection manage/connect, or add connection for multi ----- -->\n <div class=\"mt-auto flex items-center justify-between gap-3 border-t border-surface pt-4\">\n @if (provider.allowMultipleConnections) {\n @if (supportsConnect(provider)) {\n <ax-button\n size=\"sm\"\n look=\"outline\"\n type=\"button\"\n [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\"\n [text]=\"(PANEL_I18N + '.actions.add-connection' | translate | async) ?? ''\"\n (onClick)=\"handleAddConnection(provider)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-plus\"></ax-icon>\n </ax-prefix>\n </ax-button>\n } @else {\n <span></span>\n }\n <span></span>\n } @else if (hasEstablishedConnection(provider.id)) {\n <ax-dropdown-button size=\"sm\" [mode]=\"'dropdown'\" type=\"button\" [disabled]=\"pendingAction()\" [text]=\"(PANEL_I18N + '.actions.manage' | translate | async) ?? ''\">\n <ax-button-item-list>\n @if (supportsConfigure(provider)) {\n <ax-button-item [text]=\"(PANEL_I18N + '.actions.reconfigure' | translate | async) ?? ''\" [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\" (onClick)=\"handleConfigure(provider)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n @for (action of getManageActions(provider); track action.commandKey) {\n <ax-button-item [text]=\"(action.titleKey | translate | async) ?? ''\" [color]=\"action.color\" [disabled]=\"pendingAction()\" (onClick)=\"handleManageAction(provider, action)\">\n @if (action.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"action.icon\"></ax-icon>\n </ax-prefix>\n }\n </ax-button-item>\n }\n <ax-button-item [text]=\"(PANEL_I18N + '.actions.disconnect' | translate | async) ?? ''\" color=\"danger\" [disabled]=\"pendingAction()\" (onClick)=\"handleDisconnect(provider)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-link-slash\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-button>\n <ax-switch [ngModel]=\"isConnectionEnabled(provider.id)\" [disabled]=\"pendingAction() || !hasEstablishedConnection(provider.id)\" (ngModelChange)=\"handleToggleEnabled(provider, $event)\"></ax-switch>\n } @else if (supportsConnect(provider)) {\n <ax-button size=\"sm\" look=\"solid\" type=\"button\" [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\" [text]=\"(PANEL_I18N + '.actions.connect' | translate | async) ?? ''\" (onClick)=\"handleConnect(provider)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-plug\"></ax-icon>\n </ax-prefix>\n </ax-button>\n <ax-switch [ngModel]=\"isConnectionEnabled(provider.id)\" [disabled]=\"pendingAction() || !hasEstablishedConnection(provider.id)\" (ngModelChange)=\"handleToggleEnabled(provider, $event)\"></ax-switch>\n } @else {\n <span></span>\n <ax-switch [ngModel]=\"isConnectionEnabled(provider.id)\" [disabled]=\"pendingAction() || !hasEstablishedConnection(provider.id)\" (ngModelChange)=\"handleToggleEnabled(provider, $event)\"></ax-switch>\n }\n </div>\n </article>\n }\n </div>\n </section>\n }\n </div>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["@layer properties;axm-integrations-page axp-layout-start-side{min-width:calc(var(--spacing, .25rem) * 80)!important;border-inline-end-style:var(--tw-border-style);border-inline-end-width:1px}axm-integrations-page axp-layout-start-side axp-layout-content.axm-integrations-page__sidebar{flex:none;padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__sidebar-section{margin-top:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__sidebar-section-title{margin:0;padding-bottom:calc(var(--spacing, .25rem) * 2);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);opacity:85%}axm-integrations-page .axm-integrations-page__sidebar-section:first-child .axm-integrations-page__sidebar-section-title{padding-top:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__sidebar-section-body{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3)}axm-integrations-page .axm-integrations-page__overview-list,axm-integrations-page .axm-integrations-page__category-list{margin:0;display:flex;list-style-type:none;flex-direction:column;gap:var(--spacing, .25rem);padding:0}axm-integrations-page .axm-integrations-page__overview-item{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axm-integrations-page .axm-integrations-page__overview-label{display:inline-flex;min-width:0px;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5)}axm-integrations-page .axm-integrations-page__overview-label ax-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-text-default))}@supports (color: color-mix(in lab,red,red)){axm-integrations-page .axm-integrations-page__overview-label ax-icon{color:color-mix(in oklab,rgba(var(--ax-sys-color-text-default)) 80%,transparent)}}axm-integrations-page .axm-integrations-page__overview-count{display:inline-flex;min-width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:var(--radius-md, .375rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);background-color:rgb(var(--ax-sys-color-surface));color:rgb(var(--ax-sys-color-on-surface))}axm-integrations-page .axm-integrations-page__overview-count.--danger{background-color:var(--color-danger);color:var(--color-on-danger);border-color:var(--color-border-danger)}axm-integrations-page .axm-integrations-page__category-item{padding-block:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axm-integrations-page .axm-integrations-page__category-checkbox{width:100%}axm-integrations-page .axm-integrations-page__skeleton-sidebar-title{height:calc(var(--spacing, .25rem) * 6);width:calc(var(--spacing, .25rem) * 28);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-sidebar-row{height:calc(var(--spacing, .25rem) * 8);width:100%;border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-section-title{height:calc(var(--spacing, .25rem) * 6);width:calc(var(--spacing, .25rem) * 40);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-section-description{height:calc(var(--spacing, .25rem) * 4);width:100%;max-width:var(--container-md, 28rem);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-card{display:flex;height:100%;width:100%;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-xl, .75rem);border-style:var(--tw-border-style);border-width:1px;background-color:var(--color-lighter);color:var(--color-on-lighter);border-color:var(--color-border-lighter);border-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__skeleton-icon{width:calc(var(--spacing, .25rem) * 14);height:calc(var(--spacing, .25rem) * 14);flex-shrink:0;border-radius:var(--radius-xl, .75rem)}axm-integrations-page .axm-integrations-page__skeleton-status-badge{height:calc(var(--spacing, .25rem) * 6);width:calc(var(--spacing, .25rem) * 20);flex-shrink:0;border-radius:calc(infinity * 1px)}axm-integrations-page .axm-integrations-page__skeleton-title{height:calc(var(--spacing, .25rem) * 5);width:calc(3 / 5 * 100%);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-description{height:calc(var(--spacing, .25rem) * 4);width:100%;border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-description.--short{width:80%}axm-integrations-page .axm-integrations-page__skeleton-footer{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-surface));padding-top:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__skeleton-action{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 24);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-switch{height:calc(var(--spacing, .25rem) * 6);width:calc(var(--spacing, .25rem) * 11);border-radius:calc(infinity * 1px)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i2.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i3.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i3.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i3.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i4.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "component", type: i5.AXDropdownButtonComponent, selector: "ax-dropdown-button", inputs: ["disabled", "size", "text", "color", "look", "type", "mode"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "lookChange", "colorChange", "disabledChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i6.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i6.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: AXLabelModule }, { kind: "component", type: i7.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i8.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "ngmodule", type: AXSwitchModule }, { kind: "component", type: i9.AXSwitchComponent, selector: "ax-switch", inputs: ["disabled", "readonly", "color", "tabIndex", "value", "name", "isLoading"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged", "readonlyChange", "disabledChange"] }, { kind: "ngmodule", type: AXTooltipModule }, { kind: "directive", type: i10.AXTooltipDirective, selector: "[axTooltip]", inputs: ["axTooltipDisabled", "axTooltip", "axTooltipContext", "axTooltipPlacement", "axTooltipOffsetX", "axTooltipOffsetY", "axTooltipOpenAfter", "axTooltipCloseAfter"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPLogoComponent, selector: "axp-logo", inputs: ["logoKey", "appearance", "size", "format"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer-container, axp-page-footer, axp-page-header, axp-page-header-container, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "component", type: AXPThemeLayoutStartSideComponent, selector: "axp-layout-page-start-side, axp-layout-start-side" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i11.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
381
|
+
}
|
|
382
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMIntegrationsPageComponent, decorators: [{
|
|
383
|
+
type: Component,
|
|
384
|
+
args: [{ selector: 'axm-integrations-page', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [{ provide: AXPPageLayoutBase, useExisting: AXMIntegrationsPageComponent }], imports: [
|
|
385
|
+
AsyncPipe,
|
|
386
|
+
FormsModule,
|
|
387
|
+
AXBadgeModule,
|
|
388
|
+
AXButtonModule,
|
|
389
|
+
AXCheckBoxModule,
|
|
390
|
+
AXDropdownButtonModule,
|
|
391
|
+
AXDecoratorModule,
|
|
392
|
+
AXLabelModule,
|
|
393
|
+
AXSkeletonModule,
|
|
394
|
+
AXSwitchModule,
|
|
395
|
+
AXTooltipModule,
|
|
396
|
+
AXTranslationModule,
|
|
397
|
+
AXPLogoComponent,
|
|
398
|
+
AXPPageLayoutComponent,
|
|
399
|
+
AXPStateMessageComponent,
|
|
400
|
+
AXPThemeLayoutBlockComponent,
|
|
401
|
+
AXPThemeLayoutStartSideComponent,
|
|
402
|
+
], template: "<axp-page-layout>\n <!-- ----- Page start side: overview stats and category filters (large screens) ----- -->\n @if (showSidebarPanel()) {\n <axp-layout-start-side class=\"h-full\">\n <axp-layout-content class=\"axm-integrations-page__sidebar\">\n @if (loading()) {\n <!-- ----- Sidebar skeleton while domains and providers load ----- -->\n <section class=\"axm-integrations-page__sidebar-section\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-sidebar-title\"></ax-skeleton>\n <div class=\"axm-integrations-page__sidebar-section-body\">\n @for (row of [0, 1, 2, 3]; track row) {\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-sidebar-row\"></ax-skeleton>\n }\n </div>\n </section>\n <section class=\"axm-integrations-page__sidebar-section\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-sidebar-title\"></ax-skeleton>\n <div class=\"axm-integrations-page__sidebar-section-body\">\n @for (row of [0, 1, 2, 3, 4]; track row) {\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-sidebar-row\"></ax-skeleton>\n }\n </div>\n </section>\n } @else {\n <section class=\"axm-integrations-page__sidebar-section\">\n <h3 class=\"axm-integrations-page__sidebar-section-title\">\n {{ (PAGE_I18N + '.sidebar.overview.title' | translate | async) ?? '' }}\n </h3>\n <ul class=\"axm-integrations-page__overview-list\">\n <li class=\"axm-integrations-page__overview-item\">\n <span class=\"axm-integrations-page__overview-label\">\n <ax-icon icon=\"fa-light fa-circle-check\"></ax-icon>\n <span>{{ (PAGE_I18N + '.sidebar.overview.connected' | translate | async) ?? '' }}</span>\n </span>\n <span class=\"axm-integrations-page__overview-count\">{{ overviewStats().connected }}</span>\n </li>\n <li class=\"axm-integrations-page__overview-item\">\n <span class=\"axm-integrations-page__overview-label\">\n <ax-icon icon=\"fa-light fa-shield-exclamation\"></ax-icon>\n <span>{{ (PAGE_I18N + '.sidebar.overview.error' | translate | async) ?? '' }}</span>\n </span>\n <span class=\"axm-integrations-page__overview-count\" [class.--danger]=\"overviewStats().error > 0\">{{ overviewStats().error }}</span>\n </li>\n <li class=\"axm-integrations-page__overview-item\">\n <span class=\"axm-integrations-page__overview-label\">\n <ax-icon icon=\"fa-light fa-toggle-off\"></ax-icon>\n <span>{{ (PAGE_I18N + '.sidebar.overview.disabled' | translate | async) ?? '' }}</span>\n </span>\n <span class=\"axm-integrations-page__overview-count\">{{ overviewStats().disabled }}</span>\n </li>\n <li class=\"axm-integrations-page__overview-item\">\n <span class=\"axm-integrations-page__overview-label\">\n <ax-icon icon=\"fa-light fa-plug\"></ax-icon>\n <span>{{ (PAGE_I18N + '.sidebar.overview.not-connected' | translate | async) ?? '' }}</span>\n </span>\n <span class=\"axm-integrations-page__overview-count\">{{ overviewStats().notConnected }}</span>\n </li>\n </ul>\n </section>\n\n <section class=\"axm-integrations-page__sidebar-section\">\n <h3 class=\"axm-integrations-page__sidebar-section-title\">\n {{ (PAGE_I18N + '.sidebar.categories.title' | translate | async) ?? '' }}\n </h3>\n <ul class=\"axm-integrations-page__category-list\">\n <li class=\"axm-integrations-page__category-item\">\n <ax-check-box\n class=\"axm-integrations-page__category-checkbox\"\n [ngModel]=\"isAllDomainsSelected()\"\n (onValueChanged)=\"handleAllDomainsFilterChange($event)\"\n >\n <ax-label>{{ (PAGE_I18N + '.sidebar.categories.all' | translate | async) ?? '' }}</ax-label>\n </ax-check-box>\n </li>\n @for (section of domainSections(); track section.domain.id) {\n <li class=\"axm-integrations-page__category-item\">\n <ax-check-box\n class=\"axm-integrations-page__category-checkbox\"\n [ngModel]=\"isDomainFilterSelected(section.domain.id)\"\n (onValueChanged)=\"handleDomainFilterChange(section.domain.id, $event)\"\n >\n <ax-label>{{ section.domain.displayName | translate | async }}</ax-label>\n </ax-check-box>\n </li>\n }\n </ul>\n </section>\n }\n </axp-layout-content>\n </axp-layout-start-side>\n }\n\n <axp-page-content>\n @if (loading()) {\n <!-- ----- Skeleton placeholders while domains and providers are fetched ----- -->\n <div class=\"flex w-full flex-col gap-8\">\n @for (sectionIndex of skeletonSectionPlaceholders; track sectionIndex) {\n <section class=\"flex flex-col gap-4\">\n <div class=\"flex flex-col gap-2\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-section-title\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-section-description\"></ax-skeleton>\n </div>\n\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-[repeat(auto-fill,minmax(16rem,18rem))] lg:justify-start\">\n @for (cardIndex of skeletonCardPlaceholders; track cardIndex) {\n <div class=\"axm-integrations-page__skeleton-card\">\n <div class=\"flex items-start justify-between gap-3\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-icon\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-status-badge\"></ax-skeleton>\n </div>\n\n <div class=\"flex flex-col gap-2\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-title\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-description\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-description --short\"></ax-skeleton>\n </div>\n\n <div class=\"axm-integrations-page__skeleton-footer\">\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-action\"></ax-skeleton>\n <ax-skeleton [animated]=\"true\" class=\"axm-integrations-page__skeleton-switch\"></ax-skeleton>\n </div>\n </div>\n }\n </div>\n </section>\n }\n </div>\n } @else if (!visibleDomainSections().length) {\n <!-- ----- Empty state when all category filters are cleared on large screens ----- -->\n <axp-state-message mode=\"empty\" icon=\"fa-light fa-filter\" [title]=\"PAGE_I18N + '.sidebar.empty-filter.title'\" [description]=\"PAGE_I18N + '.sidebar.empty-filter.description'\">\n <ax-button slot=\"actions\" look=\"solid\" color=\"primary\" [text]=\"(PAGE_I18N + '.sidebar.empty-filter.action' | translate | async) ?? ''\" (onClick)=\"handleSelectAllDomainFilters()\"></ax-button>\n </axp-state-message>\n } @else {\n <!-- ----- Domain sections with tenant provider cards ----- -->\n <div class=\"flex w-full flex-col gap-8\">\n @for (section of visibleDomainSections(); track section.domain.id) {\n <section class=\"flex flex-col gap-4\">\n <div class=\"flex flex-col gap-1\">\n <h2 class=\"text-lg font-semibold\">\n {{ section.domain.displayName | translate | async }}\n </h2>\n @if (section.domain.description) {\n <p class=\"text-sm text-muted\">\n {{ section.domain.description | translate | async }}\n </p>\n }\n </div>\n\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-[repeat(auto-fill,minmax(18rem,24rem))] lg:justify-start\">\n @for (provider of section.providers; track provider.id) {\n <article class=\"flex h-full w-full flex-col gap-3 rounded-xl border border-surface bg-lighter-surface p-4 shadow-sm transition-shadow hover:shadow-md\">\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"flex size-14 shrink-0 items-center justify-center rounded-xl border border-surface bg-transparent\">\n @if (provider.logoKey) {\n <axp-logo [logoKey]=\"provider.logoKey\" appearance=\"colored\" [size]=\"32\" />\n } @else if (provider.icon) {\n <ax-icon class=\"text-2xl\">\n <i [class]=\"provider.icon\"></i>\n </ax-icon>\n }\n </div>\n\n <div class=\"ax-sm\">\n @if (provider.allowMultipleConnections) {\n @if (getProviderConnectionSummary(provider.id); as summary) {\n @if (summary.total > 0) {\n <ax-badge\n look=\"twotone\"\n [color]=\"getMultiConnectionStatusBadgeColor(provider.id)\"\n [text]=\"(PANEL_I18N + '.status.connected-count' | translate: { params: { connected: summary.connected, total: summary.total } } | async) ?? ''\"\n ></ax-badge>\n } @else {\n <ax-badge look=\"twotone\" color=\"secondary\" [text]=\"(PANEL_I18N + '.status.not-connected' | translate | async) ?? ''\"></ax-badge>\n }\n }\n } @else if (hasEstablishedConnection(provider.id)) {\n @if (isConnectionEnabled(provider.id)) {\n <ax-badge look=\"twotone\" color=\"success\" [text]=\"(PANEL_I18N + '.status.connected' | translate | async) ?? ''\"></ax-badge>\n } @else {\n <ax-badge look=\"twotone\" color=\"warning\" [text]=\"(PANEL_I18N + '.status.disabled' | translate | async) ?? ''\"></ax-badge>\n }\n } @else {\n <ax-badge look=\"twotone\" color=\"secondary\" [text]=\"(PANEL_I18N + '.status.not-connected' | translate | async) ?? ''\"></ax-badge>\n }\n </div>\n </div>\n\n <div class=\"flex min-w-0 flex-1 flex-col gap-2\">\n <div class=\"flex flex-wrap items-center gap-2 font-medium\">\n <span>{{ provider.displayName | translate | async }}</span>\n @if (isConnectDisabled(provider.id) && connectDisabledBadgeKey(provider.id); as badgeKey) {\n <span\n class=\"inline-flex cursor-help\"\n [axTooltip]=\"(connectDisabledMessageKey(provider.id) | translate | async) ?? ''\"\n axTooltipPlacement=\"top\"\n [attr.aria-label]=\"(connectDisabledMessageKey(provider.id) | translate | async) ?? ''\"\n >\n <ax-badge size=\"sm\" look=\"twotone\" color=\"warning\" [text]=\"(badgeKey | translate | async) ?? ''\"></ax-badge>\n </span>\n }\n </div>\n\n @if (provider.description) {\n <p class=\"text-sm text-muted\">\n {{ provider.description | translate | async }}\n </p>\n }\n\n @if (getProviderBadges(provider.id); as badges) {\n @if (badges.length > 0) {\n <div class=\"flex flex-wrap items-center gap-1\">\n @for (badge of badges; track badge.text) {\n <ax-badge size=\"sm\" look=\"twotone\" [color]=\"badge.color\" [text]=\"badge.text\"></ax-badge>\n }\n </div>\n }\n }\n\n <!-- ----- Multi-connection provider: list each connection with status and actions ----- -->\n @if (provider.allowMultipleConnections) {\n <div class=\"mt-1 flex flex-col gap-2\">\n @for (connection of getConnections(provider.id); track connection.id) {\n <div class=\"flex flex-col gap-2 rounded-lg border border-surface bg-lighter-surface p-3\">\n <!-- ----- Row 1: connection identity + status badge ----- -->\n <div class=\"flex items-start justify-between gap-2\">\n <div class=\"min-w-0 flex-1\">\n <div class=\"truncate text-sm font-medium\">{{ connection.displayName }}</div>\n @if (connection.instanceUrl) {\n <div class=\"truncate text-xs text-muted\">{{ connection.instanceUrl }}</div>\n }\n </div>\n <div class=\"ax-sm shrink-0\">\n @if (isEstablishedConnection(connection)) {\n @if (isEnabledConnection(connection)) {\n <ax-badge look=\"twotone\" color=\"success\" [text]=\"(PANEL_I18N + '.status.connected' | translate | async) ?? ''\"></ax-badge>\n } @else {\n <ax-badge look=\"twotone\" color=\"warning\" [text]=\"(PANEL_I18N + '.status.disabled' | translate | async) ?? ''\"></ax-badge>\n }\n } @else {\n <ax-badge look=\"twotone\" color=\"secondary\" [text]=\"(PANEL_I18N + '.status.not-connected' | translate | async) ?? ''\"></ax-badge>\n }\n </div>\n </div>\n\n <!-- ----- Row 2: actions + enable toggle ----- -->\n <div class=\"flex flex-nowrap items-center justify-between gap-2\">\n <div class=\"flex shrink-0 flex-nowrap items-center gap-2\">\n @if (isEstablishedConnection(connection)) {\n <ax-dropdown-button\n size=\"sm\"\n look=\"outline\"\n [mode]=\"'dropdown'\"\n type=\"button\"\n [disabled]=\"pendingAction()\"\n [text]=\"(PANEL_I18N + '.actions.manage' | translate | async) ?? ''\"\n >\n <ax-button-item-list>\n @if (supportsConfigure(provider, connection)) {\n <ax-button-item\n [text]=\"(PANEL_I18N + '.actions.reconfigure' | translate | async) ?? ''\"\n [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\"\n (onClick)=\"handleConfigure(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n <ax-button-item\n [text]=\"(PANEL_I18N + '.actions.disconnect' | translate | async) ?? ''\"\n color=\"danger\"\n [disabled]=\"pendingAction()\"\n (onClick)=\"handleDisconnect(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-link-slash\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"(PANEL_I18N + '.actions.remove' | translate | async) ?? ''\"\n color=\"danger\"\n [disabled]=\"pendingAction()\"\n (onClick)=\"handleRemove(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-button>\n } @else if (supportsConnect(provider)) {\n <ax-button\n size=\"sm\"\n look=\"solid\"\n type=\"button\"\n [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\"\n [text]=\"(PANEL_I18N + '.actions.connect' | translate | async) ?? ''\"\n (onClick)=\"handleConnect(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-plug\"></ax-icon>\n </ax-prefix>\n </ax-button>\n <ax-button\n size=\"sm\"\n look=\"outline\"\n color=\"danger\"\n type=\"button\"\n [disabled]=\"pendingAction()\"\n [text]=\"(PANEL_I18N + '.actions.remove' | translate | async) ?? ''\"\n (onClick)=\"handleRemove(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash\"></ax-icon>\n </ax-prefix>\n </ax-button>\n } @else {\n <ax-button\n size=\"sm\"\n look=\"outline\"\n color=\"danger\"\n type=\"button\"\n [disabled]=\"pendingAction()\"\n [text]=\"(PANEL_I18N + '.actions.remove' | translate | async) ?? ''\"\n (onClick)=\"handleRemove(provider, connection)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-trash\"></ax-icon>\n </ax-prefix>\n </ax-button>\n }\n </div>\n\n <ax-switch\n class=\"shrink-0\"\n [ngModel]=\"isEnabledConnection(connection)\"\n [disabled]=\"pendingAction() || !isEstablishedConnection(connection)\"\n (ngModelChange)=\"handleToggleEnabled(provider, $event, connection)\"\n ></ax-switch>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- ----- Card footer: single-connection manage/connect, or add connection for multi ----- -->\n <div class=\"mt-auto flex items-center justify-between gap-3 border-t border-surface pt-4\">\n @if (provider.allowMultipleConnections) {\n @if (supportsConnect(provider)) {\n <ax-button\n size=\"sm\"\n look=\"outline\"\n type=\"button\"\n [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\"\n [text]=\"(PANEL_I18N + '.actions.add-connection' | translate | async) ?? ''\"\n (onClick)=\"handleAddConnection(provider)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-plus\"></ax-icon>\n </ax-prefix>\n </ax-button>\n } @else {\n <span></span>\n }\n <span></span>\n } @else if (hasEstablishedConnection(provider.id)) {\n <ax-dropdown-button size=\"sm\" [mode]=\"'dropdown'\" type=\"button\" [disabled]=\"pendingAction()\" [text]=\"(PANEL_I18N + '.actions.manage' | translate | async) ?? ''\">\n <ax-button-item-list>\n @if (supportsConfigure(provider)) {\n <ax-button-item [text]=\"(PANEL_I18N + '.actions.reconfigure' | translate | async) ?? ''\" [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\" (onClick)=\"handleConfigure(provider)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-gear\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n @for (action of getManageActions(provider); track action.commandKey) {\n <ax-button-item [text]=\"(action.titleKey | translate | async) ?? ''\" [color]=\"action.color\" [disabled]=\"pendingAction()\" (onClick)=\"handleManageAction(provider, action)\">\n @if (action.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"action.icon\"></ax-icon>\n </ax-prefix>\n }\n </ax-button-item>\n }\n <ax-button-item [text]=\"(PANEL_I18N + '.actions.disconnect' | translate | async) ?? ''\" color=\"danger\" [disabled]=\"pendingAction()\" (onClick)=\"handleDisconnect(provider)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-link-slash\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-button>\n <ax-switch [ngModel]=\"isConnectionEnabled(provider.id)\" [disabled]=\"pendingAction() || !hasEstablishedConnection(provider.id)\" (ngModelChange)=\"handleToggleEnabled(provider, $event)\"></ax-switch>\n } @else if (supportsConnect(provider)) {\n <ax-button size=\"sm\" look=\"solid\" type=\"button\" [disabled]=\"pendingAction() || isConnectDisabled(provider.id)\" [text]=\"(PANEL_I18N + '.actions.connect' | translate | async) ?? ''\" (onClick)=\"handleConnect(provider)\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-plug\"></ax-icon>\n </ax-prefix>\n </ax-button>\n <ax-switch [ngModel]=\"isConnectionEnabled(provider.id)\" [disabled]=\"pendingAction() || !hasEstablishedConnection(provider.id)\" (ngModelChange)=\"handleToggleEnabled(provider, $event)\"></ax-switch>\n } @else {\n <span></span>\n <ax-switch [ngModel]=\"isConnectionEnabled(provider.id)\" [disabled]=\"pendingAction() || !hasEstablishedConnection(provider.id)\" (ngModelChange)=\"handleToggleEnabled(provider, $event)\"></ax-switch>\n }\n </div>\n </article>\n }\n </div>\n </section>\n }\n </div>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["@layer properties;axm-integrations-page axp-layout-start-side{min-width:calc(var(--spacing, .25rem) * 80)!important;border-inline-end-style:var(--tw-border-style);border-inline-end-width:1px}axm-integrations-page axp-layout-start-side axp-layout-content.axm-integrations-page__sidebar{flex:none;padding-inline:calc(var(--spacing, .25rem) * 4);padding-bottom:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__sidebar-section{margin-top:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__sidebar-section-title{margin:0;padding-bottom:calc(var(--spacing, .25rem) * 2);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);opacity:85%}axm-integrations-page .axm-integrations-page__sidebar-section:first-child .axm-integrations-page__sidebar-section-title{padding-top:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__sidebar-section-body{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3)}axm-integrations-page .axm-integrations-page__overview-list,axm-integrations-page .axm-integrations-page__category-list{margin:0;display:flex;list-style-type:none;flex-direction:column;gap:var(--spacing, .25rem);padding:0}axm-integrations-page .axm-integrations-page__overview-item{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);padding-block:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axm-integrations-page .axm-integrations-page__overview-label{display:inline-flex;min-width:0px;align-items:center;gap:calc(var(--spacing, .25rem) * 2.5)}axm-integrations-page .axm-integrations-page__overview-label ax-icon{font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));color:rgba(var(--ax-sys-color-text-default))}@supports (color: color-mix(in lab,red,red)){axm-integrations-page .axm-integrations-page__overview-label ax-icon{color:color-mix(in oklab,rgba(var(--ax-sys-color-text-default)) 80%,transparent)}}axm-integrations-page .axm-integrations-page__overview-count{display:inline-flex;min-width:calc(var(--spacing, .25rem) * 7);flex-shrink:0;align-items:center;justify-content:center;border-radius:var(--radius-md, .375rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * .5);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);background-color:rgb(var(--ax-sys-color-surface));color:rgb(var(--ax-sys-color-on-surface))}axm-integrations-page .axm-integrations-page__overview-count.--danger{background-color:var(--color-danger);color:var(--color-on-danger);border-color:var(--color-border-danger)}axm-integrations-page .axm-integrations-page__category-item{padding-block:calc(var(--spacing, .25rem) * 1.5);font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}axm-integrations-page .axm-integrations-page__category-checkbox{width:100%}axm-integrations-page .axm-integrations-page__skeleton-sidebar-title{height:calc(var(--spacing, .25rem) * 6);width:calc(var(--spacing, .25rem) * 28);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-sidebar-row{height:calc(var(--spacing, .25rem) * 8);width:100%;border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-section-title{height:calc(var(--spacing, .25rem) * 6);width:calc(var(--spacing, .25rem) * 40);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-section-description{height:calc(var(--spacing, .25rem) * 4);width:100%;max-width:var(--container-md, 28rem);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-card{display:flex;height:100%;width:100%;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-xl, .75rem);border-style:var(--tw-border-style);border-width:1px;background-color:var(--color-lighter);color:var(--color-on-lighter);border-color:var(--color-border-lighter);border-color:rgba(var(--ax-sys-color-surface));padding:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__skeleton-icon{width:calc(var(--spacing, .25rem) * 14);height:calc(var(--spacing, .25rem) * 14);flex-shrink:0;border-radius:var(--radius-xl, .75rem)}axm-integrations-page .axm-integrations-page__skeleton-status-badge{height:calc(var(--spacing, .25rem) * 6);width:calc(var(--spacing, .25rem) * 20);flex-shrink:0;border-radius:calc(infinity * 1px)}axm-integrations-page .axm-integrations-page__skeleton-title{height:calc(var(--spacing, .25rem) * 5);width:calc(3 / 5 * 100%);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-description{height:calc(var(--spacing, .25rem) * 4);width:100%;border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-description.--short{width:80%}axm-integrations-page .axm-integrations-page__skeleton-footer{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 3);border-top-style:var(--tw-border-style);border-top-width:1px;border-color:rgba(var(--ax-sys-color-surface));padding-top:calc(var(--spacing, .25rem) * 4)}axm-integrations-page .axm-integrations-page__skeleton-action{height:calc(var(--spacing, .25rem) * 8);width:calc(var(--spacing, .25rem) * 24);border-radius:var(--radius-md, .375rem)}axm-integrations-page .axm-integrations-page__skeleton-switch{height:calc(var(--spacing, .25rem) * 6);width:calc(var(--spacing, .25rem) * 11);border-radius:calc(infinity * 1px)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
|
|
403
|
+
}] });
|
|
404
|
+
|
|
405
|
+
export { AXMIntegrationsPageComponent };
|
|
406
|
+
//# sourceMappingURL=acorex-platform-module-integration-management-client-integrations-page.component-Q-SHidYA.mjs.map
|