@c8y/ngx-components 1017.0.4 → 1017.0.5
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/core/bootstrap/bootstrap.component.d.ts +1 -0
- package/core/dynamic-component/dynamic-component.service.d.ts +2 -0
- package/core/plugins/plugins-resolve.service.d.ts +1 -0
- package/esm2020/core/bootstrap/bootstrap.component.mjs +7 -1
- package/esm2020/core/common/ui-state.service.mjs +3 -2
- package/esm2020/core/dynamic-component/dynamic-component.service.mjs +8 -3
- package/esm2020/core/plugins/plugins-resolve.service.mjs +11 -2
- package/fesm2015/c8y-ngx-components.mjs +24 -3
- package/fesm2015/c8y-ngx-components.mjs.map +1 -1
- package/fesm2020/c8y-ngx-components.mjs +24 -3
- package/fesm2020/c8y-ngx-components.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -642,7 +642,7 @@ class AppStateService extends StateService {
|
|
|
642
642
|
this.currentUser = new BehaviorSubject(null);
|
|
643
643
|
this.currentTenant = new BehaviorSubject(null);
|
|
644
644
|
this.currentApplication = new BehaviorSubject(null);
|
|
645
|
-
this.currentApplicationConfig = this.currentApplication.pipe(map(app => app?.config || null));
|
|
645
|
+
this.currentApplicationConfig = this.currentApplication.pipe(filter(app => !!app), map(app => app?.config || null));
|
|
646
646
|
this.apiService.calls
|
|
647
647
|
.pipe(filter(({ url }) => !/notification\/realtime/.test(url)), map(({ phase }) => (phase === 'start' ? 1 : -1)), scan((count, item) => count + item, 0), map(count => count > 0), distinctUntilChanged())
|
|
648
648
|
.subscribe(isLoading => (this.state.isLoading = isLoading));
|
|
@@ -686,6 +686,7 @@ class AppStateService extends StateService {
|
|
|
686
686
|
await this.loadDefaultOptions();
|
|
687
687
|
}
|
|
688
688
|
catch (ex) {
|
|
689
|
+
this.currentApplication.next({});
|
|
689
690
|
throw ex;
|
|
690
691
|
}
|
|
691
692
|
}
|
|
@@ -9292,11 +9293,13 @@ class DynamicComponentService extends StateService {
|
|
|
9292
9293
|
*/
|
|
9293
9294
|
this.factories = [];
|
|
9294
9295
|
this.injectors = [this.rootInjector];
|
|
9296
|
+
this.remotePluginsLoaded$ = new BehaviorSubject(false);
|
|
9297
|
+
const remotesLoaded$ = this.remotePluginsLoaded$.pipe(filter(loaded => !!loaded), take(1));
|
|
9295
9298
|
this.items$ = fromTriggerOnce(router, this.refreshTrigger, [
|
|
9296
9299
|
getInjectedHooks(HOOK_COMPONENTS, this.injectors),
|
|
9297
9300
|
() => this.factories,
|
|
9298
9301
|
stateToFactory(this.state$)
|
|
9299
|
-
]).pipe(distinctUntilChanged(), takeUntil(timer(waitTimeout || this.DEFAULT_WAIT_TIMEOUT)), shareReplay(1));
|
|
9302
|
+
]).pipe(distinctUntilChanged(), takeUntil(combineLatest([timer(waitTimeout || this.DEFAULT_WAIT_TIMEOUT), remotesLoaded$])), shareReplay(1));
|
|
9300
9303
|
}
|
|
9301
9304
|
refresh() {
|
|
9302
9305
|
this.refreshTrigger.next(1);
|
|
@@ -9333,6 +9336,9 @@ class DynamicComponentService extends StateService {
|
|
|
9333
9336
|
const dynamicDef = await Promise.all(componentIdAndConfig.map(({ componentId }) => this.getById(componentId)));
|
|
9334
9337
|
return this.dynamicResolver.serialize(componentIdAndConfig, dynamicDef);
|
|
9335
9338
|
}
|
|
9339
|
+
markPluginsAsLoaded() {
|
|
9340
|
+
this.remotePluginsLoaded$.next(true);
|
|
9341
|
+
}
|
|
9336
9342
|
}
|
|
9337
9343
|
DynamicComponentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DynamicComponentService, deps: [{ token: i0.Injector }, { token: i1.Router }, { token: RESOLVING_COMPONENT_WAIT_TIME, optional: true }, { token: DynamicResolverService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
9338
9344
|
DynamicComponentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: DynamicComponentService, providedIn: 'root' });
|
|
@@ -10164,6 +10170,7 @@ class PluginsResolveService {
|
|
|
10164
10170
|
.map(({ name, factory }) => factory[name]);
|
|
10165
10171
|
this.loadModulesDynamically(remoteNgModules);
|
|
10166
10172
|
this.refreshHooks();
|
|
10173
|
+
this.markPluginsAsLoaded();
|
|
10167
10174
|
}
|
|
10168
10175
|
/**
|
|
10169
10176
|
* Loads modules and handles hooking correctly.
|
|
@@ -10200,6 +10207,9 @@ class PluginsResolveService {
|
|
|
10200
10207
|
}
|
|
10201
10208
|
});
|
|
10202
10209
|
}
|
|
10210
|
+
markPluginsAsLoaded() {
|
|
10211
|
+
this.dynamicComponent.markPluginsAsLoaded();
|
|
10212
|
+
}
|
|
10203
10213
|
/**
|
|
10204
10214
|
* Loads a list of remotes so that a particular application can use them.
|
|
10205
10215
|
* The request is made to the following address: /apps/<contextPath>/remoteEntry.js
|
|
@@ -10216,15 +10226,20 @@ class PluginsResolveService {
|
|
|
10216
10226
|
if (remotes.hasOwnProperty(pluginId)) {
|
|
10217
10227
|
const moduleNames = remotes[pluginId];
|
|
10218
10228
|
const url = `/apps/${pluginId}/remoteEntry.js?nocache=${date.getTime()}`;
|
|
10229
|
+
let atLeastOneModuleLoadedSuccessfully = false;
|
|
10219
10230
|
for (const moduleName of moduleNames) {
|
|
10220
10231
|
try {
|
|
10221
10232
|
remoteModules.push(await this.loadRemoteModule(url, pluginId, moduleName));
|
|
10233
|
+
atLeastOneModuleLoadedSuccessfully = true;
|
|
10222
10234
|
}
|
|
10223
10235
|
catch (ex) {
|
|
10224
10236
|
console.warn(`Could not load remote module '${moduleName}' from url:`, url);
|
|
10225
10237
|
}
|
|
10226
10238
|
}
|
|
10227
|
-
|
|
10239
|
+
// no need to load translations if we were unable to load a single module..
|
|
10240
|
+
if (atLeastOneModuleLoadedSuccessfully) {
|
|
10241
|
+
await this.loadRemoteTranslations(pluginId);
|
|
10242
|
+
}
|
|
10228
10243
|
}
|
|
10229
10244
|
}
|
|
10230
10245
|
return remoteModules;
|
|
@@ -16361,6 +16376,7 @@ class BootstrapComponent {
|
|
|
16361
16376
|
}
|
|
16362
16377
|
async loadRemotes(remotes) {
|
|
16363
16378
|
if (!remotes) {
|
|
16379
|
+
this.ensureWeMarkPluginsAsLoaded();
|
|
16364
16380
|
return;
|
|
16365
16381
|
}
|
|
16366
16382
|
const remoteModules = await this.pluginsResolve.loadRemotes(remotes);
|
|
@@ -16372,12 +16388,17 @@ class BootstrapComponent {
|
|
|
16372
16388
|
}
|
|
16373
16389
|
subscribeToLoadRemotes() {
|
|
16374
16390
|
if (this.options.get('noPlugins', false)) {
|
|
16391
|
+
this.ensureWeMarkPluginsAsLoaded();
|
|
16375
16392
|
return;
|
|
16376
16393
|
}
|
|
16377
16394
|
this.ui.currentApplicationConfig
|
|
16378
16395
|
.pipe(takeUntil(this.destroy$))
|
|
16379
16396
|
.subscribe((config) => this.loadRemotes(this.getRemotes(config)));
|
|
16380
16397
|
}
|
|
16398
|
+
ensureWeMarkPluginsAsLoaded() {
|
|
16399
|
+
// ensure we call markPluginsAsLoaded on the DynamicComponentService
|
|
16400
|
+
this.pluginsResolve.markPluginsAsLoaded();
|
|
16401
|
+
}
|
|
16381
16402
|
}
|
|
16382
16403
|
BootstrapComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: BootstrapComponent, deps: [{ token: TabsService }, { token: AppStateService }, { token: NavigatorService }, { token: ActionBarService }, { token: HeaderService }, { token: OptionsService }, { token: PluginsResolveService }, { token: SetupService }], target: i0.ɵɵFactoryTarget.Component });
|
|
16383
16404
|
BootstrapComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: BootstrapComponent, selector: "c8y-bootstrap", ngImport: i0, template: "<c8y-login *ngIf=\"!noLogin && !(ui.currentUser | async)\"></c8y-login>\n\n<div\n *ngIf=\"noLogin || ((ui.currentUser | async) && !(setupService.isSetupNeeded$ | async))\"\n [class.head-open]=\"headerService.headerOpen\"\n>\n <c8y-header-bar #header></c8y-header-bar>\n <c8y-navigator-outlet\n [nodes]=\"navigator.items$ | async\"\n [open]=\"headerService.navigatorOpen$ | async\"\n role=\"region\"\n title=\"{{ 'Navigator menu' | translate }}\"\n >\n <header class=\"title navigator-slot-top\">\n <div class=\"tenant-brand\"></div>\n <c8y-app-icon\n [name]=\"(ui.state$ | async).app.name\"\n [contextPath]=\"(ui.state$ | async).app.contextPath\"\n ></c8y-app-icon>\n <span>{{ (ui.state$ | async).app | humanizeAppName | async }}</span>\n </header>\n <div class=\"powered-by navigator-slot-bottom\" *ngIf=\"showPoweredBy\">\n <p translate>powered by Cumulocity</p>\n </div>\n </c8y-navigator-outlet>\n\n <div class=\"alerts\">\n <c8y-alert-outlet></c8y-alert-outlet>\n </div>\n <c8y-tabs-outlet\n #tabsComponent\n [tabs]=\"tabs.items$ | async\"\n [navigatorOpen]=\"headerService.navigatorOpen$ | async\"\n [orientation]=\"tabs.orientation$ | async\"\n role=\"navigation\"\n ></c8y-tabs-outlet>\n <c8y-action-bar\n #actionBarComponent\n [navigatorOpen]=\"headerService.navigatorOpen$ | async\"\n [hasTabs]=\"tabsComponent.hasTabs\"\n [isTabsHorizontal]=\"tabsComponent?.isHorizontal\"\n [items$]=\"actionBar.items$\"\n role=\"group\"\n ></c8y-action-bar>\n\n <div\n class=\"mcontainer\"\n [ngClass]=\"{\n open: headerService.navigatorOpen$ | async,\n 'no-apps-margin': noAppsMargin$ | async,\n 'horizontal-tabs': tabsComponent.isHorizontal,\n 'vertical-tabs': !tabsComponent.isHorizontal,\n 'has-tabs': tabsComponent.hasTabs,\n 'has-action-bar': !actionBarComponent?.hidden\n }\"\n >\n <main id=\"main-content\" class=\"container-fluid\" tabindex=\"-1\">\n <router-outlet></router-outlet>\n <ng-content select=\"#c8y-legacy-view\"></ng-content>\n <!-- legacy ng-view, will not be migrated atm -->\n </main>\n </div>\n</div>\n\n<div *ngIf=\"(ui.currentUser | async) && (setupService.isSetupNeeded$ | async)\">\n <c8y-header-bar [simple]=\"true\"></c8y-header-bar>\n <div class=\"mcontainer\" role=\"main\">\n <div class=\"container-fluid\">\n <c8y-setup></c8y-setup>\n </div>\n </div>\n</div>\n\n<c8y-cookie-banner></c8y-cookie-banner>\n", dependencies: [{ kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i1$5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: HeaderBarComponent, selector: "c8y-header-bar", inputs: ["simple"] }, { kind: "component", type: AppIconComponent, selector: "c8y-app-icon", inputs: ["contextPath", "name", "app"] }, { kind: "component", type: LoginComponent, selector: "c8y-login", inputs: ["name"] }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: TabsOutletComponent, selector: "c8y-tabs-outlet,c8y-ui-tabs", inputs: ["tabs", "orientation", "navigatorOpen"] }, { kind: "component", type: ActionBarComponent, selector: "c8y-action-bar", inputs: ["navigatorOpen", "hasTabs", "isTabsHorizontal", "items$"] }, { kind: "component", type: AlertOutletComponent, selector: "c8y-alert-outlet" }, { kind: "component", type: NavigatorOutletComponent, selector: "c8y-navigator-outlet, c8y-ui-navigator", inputs: ["nodes", "open"] }, { kind: "component", type: SetupComponent, selector: "c8y-setup" }, { kind: "component", type: CookieBannerComponent, selector: "c8y-cookie-banner" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i1$5.AsyncPipe, name: "async" }, { kind: "pipe", type: HumanizeAppNamePipe, name: "humanizeAppName" }] });
|