import * as i0 from '@angular/core';
import { Pipe, Component, Input, EventEmitter, Output, ViewChild, Injectable, NgModule } from '@angular/core';
import * as i2 from '@c8y/ngx-components';
import { gettext, ApplicationPluginStatus, PluginsService, PluginsExportScopes, DataGridComponent, CoreModule, hookRoute, ViewContext } from '@c8y/ngx-components';
import * as i3 from '@c8y/ngx-components/ecosystem/shared';
import { PRODUCT_EXPERIENCE_ECOSYSTEM, SharedEcosystemModule } from '@c8y/ngx-components/ecosystem/shared';
import * as i1$1 from '@angular/router';
import { pick, uniq } from 'lodash-es';
import * as i1 from 'ngx-bootstrap/modal';
import { Subject, BehaviorSubject, combineLatest, of, firstValueFrom } from 'rxjs';
import { map, takeUntil, shareReplay } from 'rxjs/operators';
import * as i5 from '@angular/common';
import * as i5$1 from '@angular/forms';
import { ApplicationType } from '@c8y/client';
import * as i4 from '@ngx-translate/core';

class AppStatePipe {
    constructor(ecosystemService) {
        this.ecosystemService = ecosystemService;
    }
    transform(app, arg) {
        const appState = this.ecosystemService.getAppState(app);
        return appState[arg];
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: AppStatePipe, deps: [{ token: i3.EcosystemService }], target: i0.ɵɵFactoryTarget.Pipe }); }
    static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: AppStatePipe, name: "appState" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: AppStatePipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'appState',
                    pure: true
                }]
        }], ctorParameters: () => [{ type: i3.EcosystemService }] });

class AppsToUpdateRemotesSelectComponent {
    constructor(bsModalRef, wizardModalService, ecosystemService) {
        this.bsModalRef = bsModalRef;
        this.wizardModalService = wizardModalService;
        this.ecosystemService = ecosystemService;
        this.destroy$ = new Subject();
        this.filterTerm$ = new BehaviorSubject('');
        this.filteredApps$ = new BehaviorSubject([]);
        this.appsToUpdateRemotes = [];
        this.result = new Promise((resolve, reject) => {
            this._update = resolve;
            this._cancel = reject;
        });
    }
    ngOnInit() {
        this.filteredApps$ = combineLatest([of(this.apps), this.filterTerm$]).pipe(map(([apps, filterTerm]) => filterTerm.trim().length === 0
            ? apps
            : apps.filter((application) => this.ecosystemService.filterContainString(application.name, filterTerm))));
        this.textConfig =
            this.updateType === 'install'
                ? {
                    header: gettext('Select applications to install the plugin to'),
                    applyButton: gettext('Install')
                }
                : {
                    header: gettext('Select applications to uninstall the plugin from'),
                    applyButton: gettext('Uninstall')
                };
    }
    cancel() {
        this.bsModalRef.hide();
        this._cancel();
    }
    setSelectedApps(selected, app) {
        selected
            ? this.appsToUpdateRemotes.push(app)
            : (this.appsToUpdateRemotes = this.appsToUpdateRemotes.filter(application => app.key !== application.key));
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
    async duplicateApp() {
        const wizardConfig = {
            headerText: gettext('Duplicate application'),
            headerIcon: 'c8y-copy'
        };
        const initialState = {
            wizardConfig,
            componentInitialState: {
                noBackButton: true
            },
            id: 'duplicateApplication'
        };
        const modalOptions = { initialState };
        const modalRef = this.wizardModalService.show(modalOptions);
        modalRef.content.onClose.pipe(takeUntil(this.destroy$)).subscribe(async () => {
            this.apps = await this.getOwnedHostedApps();
            this.ngOnInit();
        });
    }
    async apply() {
        this._update(this.appsToUpdateRemotes);
        this.bsModalRef.hide();
    }
    async getOwnedHostedApps() {
        return (await this.ecosystemService.getWebApplications()).filter(app => this.ecosystemService.isOwner(app) && app.type !== ApplicationType.EXTERNAL);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: AppsToUpdateRemotesSelectComponent, deps: [{ token: i1.BsModalRef }, { token: i2.WizardModalService }, { token: i3.EcosystemService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: AppsToUpdateRemotesSelectComponent, selector: "c8y-apps-to-update-remotes-select", inputs: { apps: "apps", updateType: "updateType", pluginName: "pluginName", appsDisabled: "appsDisabled" }, ngImport: i0, template: "<div class=\"viewport-modal\">\n  <div class=\"modal-header dialog-header\">\n    <i [c8yIcon]=\"'c8y-modules'\"></i>\n    <div class=\"modal-title h4\" id=\"modal-title\" translate>Custom applications</div>\n  </div>\n  <div class=\"inner-scroll\" id=\"modal-body\">\n    <div class=\"p-16 text-center separator-bottom sticky-top bg-component\">\n      <p class=\"text-medium\">\n        {{ textConfig.header | translate }}\n      </p>\n      <c8y-filter (onSearch)=\"filterTerm$.next($event)\"></c8y-filter>\n    </div>\n    <c8y-list-group *ngIf=\"apps.length; else emptyList\">\n      <c8y-li\n        [ngClass]=\"{ disabled: updateType === 'install' && appsDisabled.has(app.id) }\"\n        *ngFor=\"let app of filteredApps$ | async\"\n        data-cy=\"apps-to-update-remotes-select--applications-list\"\n      >\n        <c8y-li-checkbox (onSelect)=\"setSelectedApps($event, app)\" data-cy=\"apps-to-update-remotes-select--app-checkbox\"></c8y-li-checkbox>\n        <c8y-li-icon class=\"p-l-0 icon-32\">\n          <c8y-app-icon\n            class=\"list-group-icon\"\n            [app]=\"app\"\n            [contextPath]=\"app.contextPath\"\n            [name]=\"app.name\"\n          ></c8y-app-icon>\n        </c8y-li-icon>\n        <div class=\"d-flex\">\n          <div class=\"p-r-8\">\n            <p class=\"text-medium\" [innerText]=\"app | humanizeAppName | async\"></p>\n            <p class=\"small text-muted\">{{ app.description }}</p>\n          </div>\n          <span class=\"label m-l-auto a-s-start\" [ngClass]=\"app | appState: 'class'\">\n            {{ app | appState: 'label' | translate }}\n          </span>\n        </div>\n      </c8y-li>\n    </c8y-list-group>\n  </div>\n  <div class=\"modal-footer\">\n    <button\n      class=\"btn btn-default\"\n      title=\"{{ 'Cancel' | translate }}\"\n      type=\"button\"\n      (click)=\"cancel()\"\n    >\n      {{ 'Cancel' | translate }}\n    </button>\n    <button\n      class=\"btn btn-primary\"\n      title=\"{{ textConfig.applyButton | translate }}\"\n      [disabled]=\"appsToUpdateRemotes.length === 0\"\n      (click)=\"apply()\"\n    >\n      {{ textConfig.applyButton | translate }}\n    </button>\n  </div>\n</div>\n<ng-template #emptyList>\n  <c8y-ui-empty-state\n    [icon]=\"'c8y-modules'\"\n    [title]=\"'No custom applications available.' | translate\"\n    *ngIf=\"updateType !== 'install'\"\n    [horizontal]=\"true\"\n  ></c8y-ui-empty-state>\n  <ng-container *ngIf=\"updateType === 'install'\">\n    <c8y-ui-empty-state\n      [icon]=\"'c8y-modules'\"\n      [title]=\"'No custom applications available.' | translate\"\n      [subtitle]=\"'Create a custom application by duplicating an existing one.' | translate\"\n      [horizontal]=\"true\"\n    >\n      <button\n        class=\"btn btn-sm btn-default m-t-8\"\n        title=\"{{ 'Duplicate' | translate }}\"\n        (click)=\"duplicateApp()\"\n      >\n        {{ 'Duplicate' | translate }}\n      </button>\n    </c8y-ui-empty-state>\n  </ng-container>\n</ng-template>\n", dependencies: [{ kind: "component", type: i2.AppIconComponent, selector: "c8y-app-icon", inputs: ["contextPath", "name", "app"] }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.FilterInputComponent, selector: "c8y-filter", inputs: ["icon"], outputs: ["onSearch"] }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: i2.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i2.ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.HumanizeAppNamePipe, name: "humanizeAppName" }, { kind: "pipe", type: AppStatePipe, name: "appState" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: AppsToUpdateRemotesSelectComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-apps-to-update-remotes-select', template: "<div class=\"viewport-modal\">\n  <div class=\"modal-header dialog-header\">\n    <i [c8yIcon]=\"'c8y-modules'\"></i>\n    <div class=\"modal-title h4\" id=\"modal-title\" translate>Custom applications</div>\n  </div>\n  <div class=\"inner-scroll\" id=\"modal-body\">\n    <div class=\"p-16 text-center separator-bottom sticky-top bg-component\">\n      <p class=\"text-medium\">\n        {{ textConfig.header | translate }}\n      </p>\n      <c8y-filter (onSearch)=\"filterTerm$.next($event)\"></c8y-filter>\n    </div>\n    <c8y-list-group *ngIf=\"apps.length; else emptyList\">\n      <c8y-li\n        [ngClass]=\"{ disabled: updateType === 'install' && appsDisabled.has(app.id) }\"\n        *ngFor=\"let app of filteredApps$ | async\"\n        data-cy=\"apps-to-update-remotes-select--applications-list\"\n      >\n        <c8y-li-checkbox (onSelect)=\"setSelectedApps($event, app)\" data-cy=\"apps-to-update-remotes-select--app-checkbox\"></c8y-li-checkbox>\n        <c8y-li-icon class=\"p-l-0 icon-32\">\n          <c8y-app-icon\n            class=\"list-group-icon\"\n            [app]=\"app\"\n            [contextPath]=\"app.contextPath\"\n            [name]=\"app.name\"\n          ></c8y-app-icon>\n        </c8y-li-icon>\n        <div class=\"d-flex\">\n          <div class=\"p-r-8\">\n            <p class=\"text-medium\" [innerText]=\"app | humanizeAppName | async\"></p>\n            <p class=\"small text-muted\">{{ app.description }}</p>\n          </div>\n          <span class=\"label m-l-auto a-s-start\" [ngClass]=\"app | appState: 'class'\">\n            {{ app | appState: 'label' | translate }}\n          </span>\n        </div>\n      </c8y-li>\n    </c8y-list-group>\n  </div>\n  <div class=\"modal-footer\">\n    <button\n      class=\"btn btn-default\"\n      title=\"{{ 'Cancel' | translate }}\"\n      type=\"button\"\n      (click)=\"cancel()\"\n    >\n      {{ 'Cancel' | translate }}\n    </button>\n    <button\n      class=\"btn btn-primary\"\n      title=\"{{ textConfig.applyButton | translate }}\"\n      [disabled]=\"appsToUpdateRemotes.length === 0\"\n      (click)=\"apply()\"\n    >\n      {{ textConfig.applyButton | translate }}\n    </button>\n  </div>\n</div>\n<ng-template #emptyList>\n  <c8y-ui-empty-state\n    [icon]=\"'c8y-modules'\"\n    [title]=\"'No custom applications available.' | translate\"\n    *ngIf=\"updateType !== 'install'\"\n    [horizontal]=\"true\"\n  ></c8y-ui-empty-state>\n  <ng-container *ngIf=\"updateType === 'install'\">\n    <c8y-ui-empty-state\n      [icon]=\"'c8y-modules'\"\n      [title]=\"'No custom applications available.' | translate\"\n      [subtitle]=\"'Create a custom application by duplicating an existing one.' | translate\"\n      [horizontal]=\"true\"\n    >\n      <button\n        class=\"btn btn-sm btn-default m-t-8\"\n        title=\"{{ 'Duplicate' | translate }}\"\n        (click)=\"duplicateApp()\"\n      >\n        {{ 'Duplicate' | translate }}\n      </button>\n    </c8y-ui-empty-state>\n  </ng-container>\n</ng-template>\n" }]
        }], ctorParameters: () => [{ type: i1.BsModalRef }, { type: i2.WizardModalService }, { type: i3.EcosystemService }], propDecorators: { apps: [{
                type: Input
            }], updateType: [{
                type: Input
            }], pluginName: [{
                type: Input
            }], appsDisabled: [{
                type: Input
            }] } });

class PluginListItemComponent {
    constructor() {
        this.hideSource = false;
        this.isItemSelected = new EventEmitter();
    }
    onChange(event) {
        this.plugin.selected = !this.plugin.selected;
        this.isItemSelected.next(event);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: PluginListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: PluginListItemComponent, selector: "c8y-plugin-list-item", inputs: { plugin: "plugin", selectable: "selectable", hideSource: "hideSource" }, outputs: { isItemSelected: "isItemSelected" }, ngImport: i0, template: "<c8y-li-checkbox\n  class=\"p-r-16 p-l-0\"\n  (change)=\"onChange($event.target.checked)\"\n  *ngIf=\"selectable\"\n  [disabled]=\"plugin.installed\"\n  [selected]=\"plugin.selected\"\n></c8y-li-checkbox>\n<c8y-li-icon class=\"p-l-0\">\n  <i class=\"c8y-plugin-icon\">\n    <span>{{ plugin.name?.substr(0, 2) }}</span>\n  </i>\n</c8y-li-icon>\n<div>\n  <div [ngClass]=\"{ 'p-r-8': selectable }\">\n    <p>\n      <span class=\"text-medium\">{{ plugin.name }}</span>\n      <em class=\"text-muted small m-l-8\">{{ plugin.version }}</em>\n      <span *ngIf=\"plugin.installed\">\n        <i\n          class=\"text-success\"\n          [c8yIcon]=\"'check-circle'\"\n        ></i>\n        <em\n          class=\"text-muted small\"\n          translate\n        >\n          Installed`plugins`\n        </em>\n      </span>\n    </p>\n    <p class=\"small l-h-tight\">{{ plugin.description }}</p>\n  </div>\n\n  <span\n    class=\"label label-info a-s-start m-t-8\"\n    *ngIf=\"selectable && !hideSource\"\n  >\n    {{ plugin.contextPath }}\n  </span>\n</div>\n", dependencies: [{ kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: i2.ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: PluginListItemComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-plugin-list-item', template: "<c8y-li-checkbox\n  class=\"p-r-16 p-l-0\"\n  (change)=\"onChange($event.target.checked)\"\n  *ngIf=\"selectable\"\n  [disabled]=\"plugin.installed\"\n  [selected]=\"plugin.selected\"\n></c8y-li-checkbox>\n<c8y-li-icon class=\"p-l-0\">\n  <i class=\"c8y-plugin-icon\">\n    <span>{{ plugin.name?.substr(0, 2) }}</span>\n  </i>\n</c8y-li-icon>\n<div>\n  <div [ngClass]=\"{ 'p-r-8': selectable }\">\n    <p>\n      <span class=\"text-medium\">{{ plugin.name }}</span>\n      <em class=\"text-muted small m-l-8\">{{ plugin.version }}</em>\n      <span *ngIf=\"plugin.installed\">\n        <i\n          class=\"text-success\"\n          [c8yIcon]=\"'check-circle'\"\n        ></i>\n        <em\n          class=\"text-muted small\"\n          translate\n        >\n          Installed`plugins`\n        </em>\n      </span>\n    </p>\n    <p class=\"small l-h-tight\">{{ plugin.description }}</p>\n  </div>\n\n  <span\n    class=\"label label-info a-s-start m-t-8\"\n    *ngIf=\"selectable && !hideSource\"\n  >\n    {{ plugin.contextPath }}\n  </span>\n</div>\n" }]
        }], propDecorators: { plugin: [{
                type: Input
            }], selectable: [{
                type: Input
            }], hideSource: [{
                type: Input
            }], isItemSelected: [{
                type: Output
            }] } });

class PluginListComponent {
    constructor(ecosystemService, bsModalService, pluginsService, alertService, translateService, gainsightService, humanizeAppNamePipe) {
        this.ecosystemService = ecosystemService;
        this.bsModalService = bsModalService;
        this.pluginsService = pluginsService;
        this.alertService = alertService;
        this.translateService = translateService;
        this.gainsightService = gainsightService;
        this.humanizeAppNamePipe = humanizeAppNamePipe;
        this.CURRENT_LOCATION = location.href;
        this.emptyListText = '';
        this.hideSource = false;
        /**
         * Shows the install button for each plugin separately. Currently used in package-details view.
         */
        this.installable = false;
        this.selectedItems = new EventEmitter();
        this.remotePlugins$ = new BehaviorSubject({});
        this.selectedPlugins = {};
        this.updatingPluginId = { install: '', uninstall: '' };
        this.appsDisabled = new Set();
    }
    updateSelectedItems(selected, plugin) {
        this.selectedPlugins[plugin.id] = selected ? plugin : undefined;
        const onlyInstalledPlugins = Object.values(this.selectedPlugins).filter(Boolean);
        this.selectedItems.emit(onlyInstalledPlugins);
    }
    async installPlugin(plugin) {
        await this.updateAppRemotes(plugin, 'install');
    }
    async uninstallPlugin(plugin) {
        await this.updateAppRemotes(plugin, 'uninstall');
    }
    async updateAppRemotes(plugin, updateType) {
        this.updatingPluginId[updateType] = plugin?.id;
        let initialState;
        try {
            const apps = await this.getAppsForUpdate(plugin, updateType);
            initialState = {
                apps,
                updateType,
                pluginName: plugin.name,
                appsDisabled: this.appsDisabled
            };
        }
        catch (e) {
            this.alertService.addServerFailure(e);
            this.updatingPluginId[updateType] = '';
            return;
        }
        let selectedApps;
        try {
            selectedApps = await this.selectApps(initialState);
            if (!selectedApps) {
                this.updatingPluginId[updateType] = '';
                return;
            }
        }
        catch {
            // unreached
        }
        if (updateType === 'install') {
            const licensesVerifiedByUser = await this.ecosystemService.verifyLicenses([plugin]);
            if (!licensesVerifiedByUser) {
                this.updatingPluginId[updateType] = '';
                return;
            }
        }
        for (const app of selectedApps) {
            try {
                if (updateType === 'install') {
                    const versionIsCompatible = await this.ecosystemService.verifyPluginVersionsCompatibility([plugin], app);
                    if (!versionIsCompatible) {
                        continue;
                    }
                }
                await this.handleRemotesUpdate(app, plugin, updateType);
                const humanizedAppName = await firstValueFrom(this.humanizeAppNamePipe.transform(app));
                const successText = updateType === 'install'
                    ? this.translateService.instant(gettext('Plugin installed to application "{{ appName }}".'), {
                        appName: humanizedAppName
                    })
                    : this.translateService.instant(gettext('Plugin uninstalled from application "{{ appName }}".'), { appName: humanizedAppName });
                this.alertService.success(successText);
                this.onUpdateEventHandleGS(plugin, app, updateType);
            }
            catch (error) {
                this.onUpdateEventHandleGS(plugin, app, updateType, error);
            }
        }
        this.updatingPluginId[updateType] = '';
    }
    onUpdateEventHandleGS(plugin, app, updateType, error) {
        const pluginCustomEventInfo = pick(plugin, [
            'name',
            'contextPath',
            'module',
            'version',
            'type',
            'id'
        ]);
        const gsEventResult = updateType === 'install'
            ? PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.PLUGIN_INSTALLED
            : PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.PLUGIN_REMOVED;
        const eventData = {
            component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.PLUGIN_LIST,
            result: error || gsEventResult,
            url: this.CURRENT_LOCATION,
            ...pluginCustomEventInfo,
            targetApplicationName: app.name,
            targetApplicationContextPath: app.contextPath,
            ...(error && { error })
        };
        this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_PLUGINS, eventData);
    }
    async getAppsForUpdate(plugin, updateType) {
        let apps = (await this.ecosystemService.getWebApplications()).filter(app => this.ecosystemService.isOwner(app) && app.type !== ApplicationType.EXTERNAL);
        if (updateType === 'install') {
            this.appsDisabled.clear();
            for (const app of apps) {
                if (this.isPluginInstalledInApp(plugin, app)) {
                    this.appsDisabled.add(app.id);
                }
            }
        }
        if (updateType === 'uninstall') {
            const installedApps = [];
            for (const app of apps) {
                if (this.isPluginInstalledInApp(plugin, app)) {
                    installedApps.push(app);
                }
            }
            apps = installedApps;
        }
        return apps;
    }
    isPluginInstalledInApp(plugin, app) {
        const appRemotes = this.pluginsService.getMFRemotes(app) || {};
        for (const [remoteName, modules] of Object.entries(appRemotes)) {
            const pluginFromThisPackageIsInstalled = this.getPluginContextPathWithoutVersion(remoteName) === plugin.contextPath;
            const specificPluginModuleIsInstalled = modules.some(module => module === plugin.module);
            if (pluginFromThisPackageIsInstalled && specificPluginModuleIsInstalled) {
                return true;
            }
        }
        return false;
    }
    getPluginContextPathWithoutVersion(remote) {
        return remote.split('@')[0];
    }
    async handleRemotesUpdate(application, plugin, updateType) {
        try {
            // When remotes object is not set in the configuration object of an application.
            // Fallback to setInitialRemotes is triggered.
            const { remotes, excludedRemotes } = await (updateType === 'install'
                ? this.pluginsService.addRemotes(application, plugin)
                : this.pluginsService.removeRemotes(application, this.getAllPluginsToRemove(plugin)));
            if (!application.config) {
                application.config = {};
            }
            application.config.remotes = remotes;
            application.config.excludedRemotes = excludedRemotes;
            const actualRemotes = this.pluginsService.getMFRemotes(application);
            return this.emitRemotes(actualRemotes);
        }
        catch (er) {
            if (er) {
                this.alertService.addServerFailure(er);
            }
            throw er;
        }
    }
    getAllPluginsToRemove(plugin) {
        return this.package.applicationVersions.map(av => ({
            id: `${plugin.contextPath}@${av.version}/${plugin.module}`,
            idLatest: `${plugin.contextPath}/${plugin.module}`,
            module: plugin.module,
            path: plugin.path
        }));
    }
    emitRemotes(remotes) {
        this.remotePlugins$.next(remotes);
        return { ...this.remotePlugins$.value };
    }
    async selectApps(initialState) {
        try {
            return await this.bsModalService.show(AppsToUpdateRemotesSelectComponent, {
                class: 'modal-sm',
                ariaDescribedby: 'modal-body',
                ariaLabelledBy: 'modal-title',
                initialState,
                ignoreBackdropClick: true,
                keyboard: false
            }).content.result;
        }
        catch (er) {
            return;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: PluginListComponent, deps: [{ token: i3.EcosystemService }, { token: i1.BsModalService }, { token: i2.PluginsService }, { token: i2.AlertService }, { token: i4.TranslateService }, { token: i2.GainsightService }, { token: i2.HumanizeAppNamePipe }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: PluginListComponent, selector: "c8y-plugin-list", inputs: { plugins$: "plugins$", emptyListText: "emptyListText", selectable: "selectable", hideSource: "hideSource", installable: "installable", package: "package" }, outputs: { selectedItems: "selectedItems" }, ngImport: i0, template: "<c8y-list-group class=\"bg-inherit\">\n  <ng-container *ngIf=\"(plugins$ | async)?.length !== 0; else emptyList\">\n    <ng-container *ngFor=\"let plugin of plugins$ | async\">\n      <c8y-li [ngClass]=\"{ disabled: plugin.installed }\" class=\"bg-inherit\">\n        <c8y-plugin-list-item\n          (isItemSelected)=\"updateSelectedItems($event, plugin)\"\n          [plugin]=\"plugin\"\n          [selectable]=\"selectable\"\n          [hideSource]=\"hideSource\"\n          class=\"d-flex\"\n        ></c8y-plugin-list-item>\n        <div class=\"p-l-40 m-t-4\">\n          <button\n            *ngIf=\"installable\"\n            (click)=\"uninstallPlugin(plugin)\"\n            [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.uninstall }\"\n            [disabled]=\"updatingPluginId.uninstall && plugin.id !== updatingPluginId.uninstall\"\n            class=\"btn btn-danger btn-sm m-l-4\"\n            title=\"{{ 'Uninstall plugin' | translate }}\"\n            data-cy=\"plugin-list--uninstall-plugin-button\"\n            translate\n          >\n            Uninstall plugin\n          </button>\n          <button\n            *ngIf=\"installable\"\n            (click)=\"installPlugin(plugin)\"\n            [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.install }\"\n            [disabled]=\"updatingPluginId.install && plugin.id !== updatingPluginId.install\"\n            class=\"btn btn-default btn-sm m-l-8\"\n            title=\"{{ 'Install plugin' | translate }}\"\n            data-cy=\"plugin-list--install-plugin-button\"\n            translate\n          >\n            Install plugin\n          </button>\n        </div>\n      </c8y-li>\n    </ng-container>\n  </ng-container>\n</c8y-list-group>\n<ng-template #emptyList>\n  <div class=\"c8y-empty-state text-left\" *ngIf=\"emptyListText\">\n    <h1 c8yIcon=\"plugin\"></h1>\n    <p>\n      {{ emptyListText | translate }}\n    </p>\n  </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: i2.ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: PluginListItemComponent, selector: "c8y-plugin-list-item", inputs: ["plugin", "selectable", "hideSource"], outputs: ["isItemSelected"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: PluginListComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-plugin-list', template: "<c8y-list-group class=\"bg-inherit\">\n  <ng-container *ngIf=\"(plugins$ | async)?.length !== 0; else emptyList\">\n    <ng-container *ngFor=\"let plugin of plugins$ | async\">\n      <c8y-li [ngClass]=\"{ disabled: plugin.installed }\" class=\"bg-inherit\">\n        <c8y-plugin-list-item\n          (isItemSelected)=\"updateSelectedItems($event, plugin)\"\n          [plugin]=\"plugin\"\n          [selectable]=\"selectable\"\n          [hideSource]=\"hideSource\"\n          class=\"d-flex\"\n        ></c8y-plugin-list-item>\n        <div class=\"p-l-40 m-t-4\">\n          <button\n            *ngIf=\"installable\"\n            (click)=\"uninstallPlugin(plugin)\"\n            [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.uninstall }\"\n            [disabled]=\"updatingPluginId.uninstall && plugin.id !== updatingPluginId.uninstall\"\n            class=\"btn btn-danger btn-sm m-l-4\"\n            title=\"{{ 'Uninstall plugin' | translate }}\"\n            data-cy=\"plugin-list--uninstall-plugin-button\"\n            translate\n          >\n            Uninstall plugin\n          </button>\n          <button\n            *ngIf=\"installable\"\n            (click)=\"installPlugin(plugin)\"\n            [ngClass]=\"{ 'btn-pending': plugin.id === updatingPluginId.install }\"\n            [disabled]=\"updatingPluginId.install && plugin.id !== updatingPluginId.install\"\n            class=\"btn btn-default btn-sm m-l-8\"\n            title=\"{{ 'Install plugin' | translate }}\"\n            data-cy=\"plugin-list--install-plugin-button\"\n            translate\n          >\n            Install plugin\n          </button>\n        </div>\n      </c8y-li>\n    </ng-container>\n  </ng-container>\n</c8y-list-group>\n<ng-template #emptyList>\n  <div class=\"c8y-empty-state text-left\" *ngIf=\"emptyListText\">\n    <h1 c8yIcon=\"plugin\"></h1>\n    <p>\n      {{ emptyListText | translate }}\n    </p>\n  </div>\n</ng-template>\n" }]
        }], ctorParameters: () => [{ type: i3.EcosystemService }, { type: i1.BsModalService }, { type: i2.PluginsService }, { type: i2.AlertService }, { type: i4.TranslateService }, { type: i2.GainsightService }, { type: i2.HumanizeAppNamePipe }], propDecorators: { plugins$: [{
                type: Input
            }], emptyListText: [{
                type: Input
            }], selectable: [{
                type: Input
            }], hideSource: [{
                type: Input
            }], installable: [{
                type: Input
            }], package: [{
                type: Input
            }], selectedItems: [{
                type: Output
            }] } });

class OnlyLatestPluginVersionPipe {
    transform(value, disabled) {
        if (disabled) {
            return value;
        }
        return value.pipe(map(list => list.filter(plugin => !!plugin.tags?.includes('latest'))));
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: OnlyLatestPluginVersionPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
    static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: OnlyLatestPluginVersionPipe, name: "onlyLatestPluginVersion" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: OnlyLatestPluginVersionPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'onlyLatestPluginVersion'
                }]
        }] });

class InstallPluginComponent {
    constructor(bsModalRef, modal, ecosystemService) {
        this.bsModalRef = bsModalRef;
        this.modal = modal;
        this.ecosystemService = ecosystemService;
        this.filterTerm$ = new BehaviorSubject('');
        this.filteredPlugins$ = new BehaviorSubject([]);
        this.selectedPlugins = [];
        this.result = new Promise((resolve, reject) => {
            this._install = resolve;
            this._cancel = reject;
        });
        this.onlyLatestPluginVersion = true;
    }
    ngOnInit() {
        this.filteredPlugins$ = combineLatest([this.plugins$, this.filterTerm$]).pipe(map(([plugins, filterTerm]) => filterTerm.trim().length === 0
            ? plugins
            : plugins.filter((plugin) => this.ecosystemService.filterContainString(plugin.name, filterTerm))));
    }
    cancel() {
        this.bsModalRef.hide();
        this._cancel();
    }
    install() {
        this._install(this.selectedPlugins);
        this.bsModalRef.hide();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: InstallPluginComponent, deps: [{ token: i1.BsModalRef }, { token: i2.ModalService }, { token: i3.EcosystemService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: InstallPluginComponent, selector: "c8y-install-plugin", inputs: { plugins$: "plugins$" }, ngImport: i0, template: "<div class=\"viewport-modal\">\n  <div class=\"modal-header dialog-header\">\n    <i [c8yIcon]=\"'plugin'\"></i>\n    <div id=\"modal-title\" class=\"modal-title h4\" translate>Available plugins</div>\n  </div>\n  <div class=\"p-t-8 p-16 text-center separator-bottom flex-no-shrink\">\n    <p class=\"text-medium m-b-8\" translate>Select the compatible plugins to install</p>\n    <label class=\"c8y-switch\">\n      <input type=\"checkbox\" [(ngModel)]=\"onlyLatestPluginVersion\" />\n      <span></span>\n      <span translate>Only latest version of plugins</span>\n    </label>\n    <c8y-filter (onSearch)=\"this.filterTerm$.next($event)\"></c8y-filter>\n  </div>\n  <div class=\"modal-inner-scroll\" id=\"modal-body\">\n    <c8y-plugin-list\n      (selectedItems)=\"selectedPlugins = $event\"\n      [emptyListText]=\"'No plugins available' | translate\"\n      [plugins$]=\"filteredPlugins$ | onlyLatestPluginVersion: !onlyLatestPluginVersion\"\n      [selectable]=\"true\"\n      class=\"m-t-16\"\n    ></c8y-plugin-list>\n  </div>\n\n  <div class=\"modal-footer\">\n    <button\n      (click)=\"cancel()\"\n      class=\"btn btn-default\"\n      title=\"{{ 'Cancel' | translate }}\"\n      data-cy=\"install-plugin--cancel-button\"\n      type=\"button\"\n    >\n      {{ 'Cancel' | translate }}\n    </button>\n    <button\n      (click)=\"install()\"\n      [disabled]=\"selectedPlugins.length === 0\"\n      class=\"btn btn-primary\"\n      title=\"{{ 'Install' | translate }}\"\n      data-cy=\"install-plugin--install-button\"\n      type=\"button\"\n    >\n      {{ 'Install' | translate }}\n      <span class=\"badge\" *ngIf=\"selectedPlugins.length as length\">{{ length }}</span>\n    </button>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.FilterInputComponent, selector: "c8y-filter", inputs: ["icon"], outputs: ["onSearch"] }, { kind: "component", type: PluginListComponent, selector: "c8y-plugin-list", inputs: ["plugins$", "emptyListText", "selectable", "hideSource", "installable", "package"], outputs: ["selectedItems"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: OnlyLatestPluginVersionPipe, name: "onlyLatestPluginVersion" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: InstallPluginComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-install-plugin', template: "<div class=\"viewport-modal\">\n  <div class=\"modal-header dialog-header\">\n    <i [c8yIcon]=\"'plugin'\"></i>\n    <div id=\"modal-title\" class=\"modal-title h4\" translate>Available plugins</div>\n  </div>\n  <div class=\"p-t-8 p-16 text-center separator-bottom flex-no-shrink\">\n    <p class=\"text-medium m-b-8\" translate>Select the compatible plugins to install</p>\n    <label class=\"c8y-switch\">\n      <input type=\"checkbox\" [(ngModel)]=\"onlyLatestPluginVersion\" />\n      <span></span>\n      <span translate>Only latest version of plugins</span>\n    </label>\n    <c8y-filter (onSearch)=\"this.filterTerm$.next($event)\"></c8y-filter>\n  </div>\n  <div class=\"modal-inner-scroll\" id=\"modal-body\">\n    <c8y-plugin-list\n      (selectedItems)=\"selectedPlugins = $event\"\n      [emptyListText]=\"'No plugins available' | translate\"\n      [plugins$]=\"filteredPlugins$ | onlyLatestPluginVersion: !onlyLatestPluginVersion\"\n      [selectable]=\"true\"\n      class=\"m-t-16\"\n    ></c8y-plugin-list>\n  </div>\n\n  <div class=\"modal-footer\">\n    <button\n      (click)=\"cancel()\"\n      class=\"btn btn-default\"\n      title=\"{{ 'Cancel' | translate }}\"\n      data-cy=\"install-plugin--cancel-button\"\n      type=\"button\"\n    >\n      {{ 'Cancel' | translate }}\n    </button>\n    <button\n      (click)=\"install()\"\n      [disabled]=\"selectedPlugins.length === 0\"\n      class=\"btn btn-primary\"\n      title=\"{{ 'Install' | translate }}\"\n      data-cy=\"install-plugin--install-button\"\n      type=\"button\"\n    >\n      {{ 'Install' | translate }}\n      <span class=\"badge\" *ngIf=\"selectedPlugins.length as length\">{{ length }}</span>\n    </button>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.BsModalRef }, { type: i2.ModalService }, { type: i3.EcosystemService }], propDecorators: { plugins$: [{
                type: Input
            }] } });

class LabelCellRendererComponent {
    constructor(context) {
        this.context = context;
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: LabelCellRendererComponent, deps: [{ token: i2.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: LabelCellRendererComponent, selector: "c8y-label-cell-renderer", ngImport: i0, template: "<span class=\"label label-info\">{{ context.value }}</span>\n" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: LabelCellRendererComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-label-cell-renderer', template: "<span class=\"label label-info\">{{ context.value }}</span>\n" }]
        }], ctorParameters: () => [{ type: i2.CellRendererContext }] });

class OrphanedStatusCellRendererComponent {
    constructor(context) {
        this.context = context;
        this.label = this.getLabel(context.value);
    }
    getLabel(statusValue) {
        switch (statusValue) {
            case ApplicationPluginStatus.OUTDATED:
                return {
                    value: statusValue,
                    text: gettext('OUTDATED`plugin status`'),
                    class: 'label-warning'
                };
            case ApplicationPluginStatus.ORPHANED:
                return {
                    value: statusValue,
                    text: gettext('ORPHANED`plugin status`'),
                    class: 'label-danger'
                };
            case ApplicationPluginStatus.REVOKED:
                return {
                    value: statusValue,
                    text: gettext('REVOKED`plugin status`'),
                    class: 'label-danger'
                };
            case ApplicationPluginStatus.LATEST:
                return {
                    value: statusValue,
                    text: gettext('LATEST`plugin status`'),
                    class: 'label-success'
                };
            case ApplicationPluginStatus.AUTO:
                return {
                    value: statusValue,
                    text: gettext('AUTO`plugin status`'),
                    class: 'label-success'
                };
            default:
                return null;
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: OrphanedStatusCellRendererComponent, deps: [{ token: i2.CellRendererContext }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: OrphanedStatusCellRendererComponent, selector: "c8y-orphaned-status-cell-renderer", ngImport: i0, template: "<span\n  *ngIf=\"label\"\n  class=\"label\"\n  [ngClass]=\"label.class\"\n  [title]=\"label.text | translate\"\n>\n  {{ label.text | translate }}\n</span>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: OrphanedStatusCellRendererComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-orphaned-status-cell-renderer', template: "<span\n  *ngIf=\"label\"\n  class=\"label\"\n  [ngClass]=\"label.class\"\n  [title]=\"label.text | translate\"\n>\n  {{ label.text | translate }}\n</span>\n" }]
        }], ctorParameters: () => [{ type: i2.CellRendererContext }] });

class UpdatePluginOfAppComponent {
    constructor(bsModalRef, pluginsService, alert, ecosystemService, gainsightService) {
        this.bsModalRef = bsModalRef;
        this.pluginsService = pluginsService;
        this.alert = alert;
        this.ecosystemService = ecosystemService;
        this.gainsightService = gainsightService;
        this.CURRENT_LOCATION = location.href;
        this.result = new Promise((resolve, reject) => {
            this._install = resolve;
            this._cancel = reject;
        });
        this.updateAll = true;
    }
    async update() {
        const remotes = this.pluginsService.getMFRemotes(this.app);
        const oldRemotePath = `${this.plugin.contextPath}@${this.plugin.version}`;
        const newRemotePath = `${this.plugin.contextPath}@${this.applicationVersion.version}`;
        let oldRemoteModules = [...(remotes[oldRemotePath] || [])];
        if (!oldRemoteModules.length) {
            this.alert.warning(gettext('Could not change the version of plugin.'));
            this.cancel();
            return;
        }
        const result = await this.ecosystemService.verifyLicenses([this.plugin]);
        if (!result) {
            this.alert.warning(gettext('Plugin update aborted by user.'));
            this.cancel();
            return;
        }
        let remoteModulesOfNewVersion = [...(remotes[newRemotePath] || [])];
        let olderVersions = {};
        if (this.updateAll) {
            olderVersions = Object.keys(remotes)
                .filter(key => key.startsWith(`${this.plugin.contextPath}@`))
                .reduceRight((prev, curr) => {
                prev[curr] = undefined;
                return prev;
            }, {});
            oldRemoteModules = Object.keys(olderVersions)
                .map(version => remotes[version])
                .reduceRight((prev, curr) => {
                prev.push(...curr);
                return prev;
            }, []);
            remoteModulesOfNewVersion.push(...oldRemoteModules);
        }
        else {
            remoteModulesOfNewVersion.push(this.plugin.module);
            olderVersions[oldRemotePath] = oldRemoteModules.filter(module => module !== this.plugin.module);
            if (!olderVersions[oldRemotePath].length) {
                olderVersions[oldRemotePath] = undefined;
            }
        }
        remoteModulesOfNewVersion = uniq(remoteModulesOfNewVersion);
        const newRemotes = {
            ...remotes,
            ...olderVersions,
            [newRemotePath]: remoteModulesOfNewVersion
        };
        try {
            await this.pluginsService.updateRemotesInAppConfig(this.app, newRemotes);
            this.alert.success(gettext(`Switched the version of plugin.`));
            this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.INSTALLED_PLUGINS, {
                component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.UPDATE_PLUGIN_OF_APP,
                action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.CHANGE_PLUGIN_VERSION,
                result: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.PLUGIN_VERSION_CHANGED,
                url: this.CURRENT_LOCATION
            });
        }
        catch (e) {
            this.alert.addServerFailure(e);
            this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.INSTALLED_PLUGINS, {
                component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.UPDATE_PLUGIN_OF_APP,
                action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.CHANGE_PLUGIN_VERSION,
                result: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.SERVER_FAILURE,
                url: this.CURRENT_LOCATION
            });
        }
        this.bsModalRef.hide();
        this._install();
    }
    cancel() {
        this.bsModalRef.hide();
        this._cancel();
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: UpdatePluginOfAppComponent, deps: [{ token: i1.BsModalRef }, { token: i2.PluginsService }, { token: i2.AlertService }, { token: i3.EcosystemService }, { token: i2.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: UpdatePluginOfAppComponent, selector: "c8y-update-plugin-of-app", ngImport: i0, template: "<div class=\"viewport-modal\">\n  <div class=\"modal-header dialog-header\">\n    <i [c8yIcon]=\"'c8y-modules'\"></i>\n    <h4 *ngIf=\"!downgrade\" id=\"modal-title\" translate>Update plugin</h4>\n    <h4 *ngIf=\"downgrade\" id=\"modal-title\" translate>Downgrade plugin</h4>\n  </div>\n  <div class=\"inner-scroll\" id=\"modal-body\">\n    <div class=\"p-16\">\n      <div class=\"d-block fit-w bg-gray-white\">\n        <c8y-package-version-select\n          [packageContextPath]=\"plugin?.contextPath\"\n          [(ngModel)]=\"applicationVersion\"\n        ></c8y-package-version-select>\n        <div\n          *ngIf=\"plugin?.version && plugin.version === applicationVersion?.version\"\n          class=\"alert alert-info\"\n          role=\"alert\"\n        >\n          <span translate ngNonBindable [translateParams]=\"applicationVersion\">\n            Select another version, as {{ version }} is currently used.\n          </span>\n        </div>\n      </div>\n\n      <div class=\"form-group\">\n        <label class=\"c8y-checkbox\">\n          <input [(ngModel)]=\"updateAll\" type=\"checkbox\" />\n          <span></span>\n          <span translate ngNonBindable [translateParams]=\"plugin\">\n            Set version for all plugins using the same context path \"{{ contextPath }}\".\n          </span>\n        </label>\n      </div>\n    </div>\n  </div>\n  <div class=\"modal-footer\">\n    <button\n      class=\"btn btn-default\"\n      title=\"{{ 'Cancel' | translate }}\"\n      type=\"button\"\n      (click)=\"cancel()\"\n    >\n      {{ 'Cancel' | translate }}\n    </button>\n    <button\n      class=\"btn btn-primary\"\n      title=\"{{ 'Set version' | translate }}\"\n      [disabled]=\"!applicationVersion || plugin?.version === applicationVersion?.version\"\n      (click)=\"update()\"\n    >\n      {{ 'Set version' | translate }}\n    </button>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.PackageVersionSelectComponent, selector: "c8y-package-version-select", inputs: ["label", "packageContextPath", "packageId"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: UpdatePluginOfAppComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-update-plugin-of-app', template: "<div class=\"viewport-modal\">\n  <div class=\"modal-header dialog-header\">\n    <i [c8yIcon]=\"'c8y-modules'\"></i>\n    <h4 *ngIf=\"!downgrade\" id=\"modal-title\" translate>Update plugin</h4>\n    <h4 *ngIf=\"downgrade\" id=\"modal-title\" translate>Downgrade plugin</h4>\n  </div>\n  <div class=\"inner-scroll\" id=\"modal-body\">\n    <div class=\"p-16\">\n      <div class=\"d-block fit-w bg-gray-white\">\n        <c8y-package-version-select\n          [packageContextPath]=\"plugin?.contextPath\"\n          [(ngModel)]=\"applicationVersion\"\n        ></c8y-package-version-select>\n        <div\n          *ngIf=\"plugin?.version && plugin.version === applicationVersion?.version\"\n          class=\"alert alert-info\"\n          role=\"alert\"\n        >\n          <span translate ngNonBindable [translateParams]=\"applicationVersion\">\n            Select another version, as {{ version }} is currently used.\n          </span>\n        </div>\n      </div>\n\n      <div class=\"form-group\">\n        <label class=\"c8y-checkbox\">\n          <input [(ngModel)]=\"updateAll\" type=\"checkbox\" />\n          <span></span>\n          <span translate ngNonBindable [translateParams]=\"plugin\">\n            Set version for all plugins using the same context path \"{{ contextPath }}\".\n          </span>\n        </label>\n      </div>\n    </div>\n  </div>\n  <div class=\"modal-footer\">\n    <button\n      class=\"btn btn-default\"\n      title=\"{{ 'Cancel' | translate }}\"\n      type=\"button\"\n      (click)=\"cancel()\"\n    >\n      {{ 'Cancel' | translate }}\n    </button>\n    <button\n      class=\"btn btn-primary\"\n      title=\"{{ 'Set version' | translate }}\"\n      [disabled]=\"!applicationVersion || plugin?.version === applicationVersion?.version\"\n      (click)=\"update()\"\n    >\n      {{ 'Set version' | translate }}\n    </button>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.BsModalRef }, { type: i2.PluginsService }, { type: i2.AlertService }, { type: i3.EcosystemService }, { type: i2.GainsightService }] });

class ApplicationPluginsComponent {
    constructor(activatedRoute, ecosystemService, bsModalService, pluginsService, alertService, gainsightService) {
        this.activatedRoute = activatedRoute;
        this.ecosystemService = ecosystemService;
        this.bsModalService = bsModalService;
        this.pluginsService = pluginsService;
        this.alertService = alertService;
        this.gainsightService = gainsightService;
        this.PRODUCT_EXPERIENCE = PRODUCT_EXPERIENCE_ECOSYSTEM;
        this.CURRENT_LOCATION = location.href;
        this.remotePlugins$ = new BehaviorSubject({});
        this.allAvailablePlugins$ = new BehaviorSubject([]);
        this.selfPlugins$ = new BehaviorSubject([]);
        this.installedPlugins$ = combineLatest([
            this.remotePlugins$.pipe(map(remotes => PluginsService.convertInstalledRemotesToIds(remotes))),
            this.allAvailablePlugins$
        ]).pipe(map(([remotePlugins, allPlugins]) => this.getInstalledPlugins(allPlugins, remotePlugins)), shareReplay(1));
        this.orphanedPlugins$ = this.installedPlugins$.pipe(map(plugins => plugins.filter(p => p.status === ApplicationPluginStatus.ORPHANED)));
        // only use the installedPlugins$ and selfPlugins$ as triggers
        this.isStandard$ = combineLatest([this.installedPlugins$, this.selfPlugins$]).pipe(map(() => this.isStandard(this.app)));
        this.title = gettext('Installed plugins');
        this.loadMoreItemsLabel = gettext('Load more packages');
        this.loadingItemsLabel = gettext('Loading packages…');
        this.actionControls = this.getActionControls();
        this.bulkActionControls = this.getBulkActionControls();
        this.headerActionControls = [];
        this.noResultsMessage = gettext('No plugins to display.');
        this.noDataMessage = gettext('No plugins installed.');
        this.noResultsSubtitle = gettext('Refine your search terms or check your spelling.');
        this.noDataSubtitle = gettext("This application doesn't have any plugin. Click below to install.");
        this.pagination = {
            pageSize: 10,
            currentPage: 1
        };
        this.displayOptions = {
            bordered: false,
            striped: true,
            filter: true,
            gridHeader: true,
            hover: true
        };
        this.columns = [
            {
                name: 'name',
                header: gettext('Plugin name'),
                path: 'name',
                filterable: true
            },
            {
                name: 'Version',
                header: gettext('Version'),
                path: 'version',
                filterable: false
            },
            {
                name: 'Tag',
                header: gettext('Tag`noun`'),
                path: 'installedViaTag',
                filterable: false,
                cellRendererComponent: LabelCellRendererComponent
            },
            {
                name: 'description',
                header: gettext('Description'),
                path: 'description',
                filterable: false,
                cellCSSClassName: 'small'
            },
            {
                name: 'contextPath',
                header: gettext('Source'),
                path: 'contextPath',
                filterable: false,
                cellRendererComponent: LabelCellRendererComponent
            },
            {
                name: 'scope',
                header: gettext('Scope'),
                path: 'scope',
                filterable: false,
                visible: false,
                cellRendererComponent: LabelCellRendererComponent
            },
            {
                name: 'status',
                header: gettext('Status'),
                path: 'status',
                filterable: false,
                cellRendererComponent: OrphanedStatusCellRendererComponent
            }
        ];
        this.destroy$ = new Subject();
    }
    ngOnInit() {
        this.addInstallButtonToHeaderActionControls();
        this.loadData();
    }
    async loadData() {
        this.isLoading = true;
        await this.getApplicationMO();
        await this.getApplicationMFRemotes(this.app);
        await this.getAllApplicationsMFExports(this.app);
        await this.getAllSelfMFExports(this.app);
        this.isLoading = false;
    }
    async resetToDefault() {
        this.isLoading = true;
        await this.pluginsService.resetRemotes(this.app);
        await this.loadData();
        this.alertService.success(gettext('The application was reset to its default plugins.'));
    }
    async installPlugins() {
        let currentPlugin = null;
        try {
            this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.INSTALLED_PLUGINS, {
                component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.APPLICATION_PLUGINS,
                action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.INSTALL_PLUGINS_INITIATED,
                url: this.CURRENT_LOCATION,
                targetApplicationName: this.app.name,
                targetApplicationContextPath: this.app.contextPath
            });
            const pluginsToAdd = await this.bsModalService.show(InstallPluginComponent, {
                class: 'modal-sm',
                ariaDescribedby: 'modal-body',
                ariaLabelledBy: 'modal-title',
                initialState: this.getInstallModalInitState(),
                ignoreBackdropClick: true
            }).content.result;
            const licensesVerifiedByUser = await this.ecosystemService.verifyLicenses(pluginsToAdd);
            if (!licensesVerifiedByUser) {
                return;
            }
            const verifyVersionCompatibility = await this.ecosystemService.verifyPluginVersionsCompatibility(pluginsToAdd, this.app);
            if (!verifyVersionCompatibility) {
                return;
            }
            this.isLoading = true;
            await this.handleRemotesInstallation(pluginsToAdd);
            this.alertService.success(gettext('Plugins installed.'));
            pluginsToAdd.forEach(plugin => {
                currentPlugin = plugin;
                this.triggerPluginEvent(plugin, PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.PLUGIN_INSTALLED);
            });
        }
        catch (ex) {
            if (ex) {
                this.alertService.addServerFailure(ex);
                this.triggerPluginEvent(currentPlugin, PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.SERVER_FAILURE);
            }
        }
        finally {
            this.isLoading = false;
        }
    }
    async removePlugins(plugins) {
        let currentPlugin = null;
        try {
            this.isLoading = true;
            const installedPlugins = await firstValueFrom(this.installedPlugins$);
            const pluginsToRemove = installedPlugins.filter(p => plugins.includes(p.id));
            const updatedRemotes = await this.pluginsService.removeRemotes(this.app, plugins.map(id => installedPlugins.find(p => p.id === id)));
            this.emitRemotes(updatedRemotes);
            this.isLoading = false;
            this.dataGrid.cancel();
            this.alertService.success(gettext('Plugins removed.'));
            pluginsToRemove.forEach(plugin => {
                currentPlugin = plugin;
                this.triggerPluginEvent(plugin, PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.PLUGIN_REMOVED);
            });
        }
        catch (ex) {
            if (ex) {
                this.alertService.addServerFailure(ex);
                this.triggerPluginEvent(currentPlugin, PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.SERVER_FAILURE);
            }
        }
        finally {
            this.isLoading = false;
        }
    }
    async cleanupOrphanedPlugins(plugins) {
        const pluginIds = plugins.map(p => p.id);
        await this.removePlugins(pluginIds);
    }
    getActionControls() {
        return [
            {
                type: 'customUpdate',
                text: gettext('Update'),
                icon: 'caret-square-o-up',
                showIf: plugin => {
                    return (plugin.status === ApplicationPluginStatus.OUTDATED ||
                        plugin.status === ApplicationPluginStatus.REVOKED);
                },
                callback: plugin => this.updatePlugin(this.app, plugin)
            },
            {
                type: 'customDowngrade',
                text: gettext('Downgrade'),
                icon: 'caret-square-o-down',
                showIf: (plugin) => {
                    if (plugin.scope === PluginsExportScopes.SELF ||
                        plugin.scope === PluginsExportScopes.SELF_OPTIONAL) {
                        return false;
                    }
                    return plugin.status === ApplicationPluginStatus.LATEST;
                },
                callback: plugin => this.updatePlugin(this.app, plugin, true)
            }
        ];
    }
    getBulkActionControls() {
        return [
            {
                type: 'customDelete',
                text: gettext('Remove'),
                icon: 'trash',
                callback: plugins => this.removePlugins(plugins)
            }
        ];
    }
    async updatePlugin(app, plugin, downgrade = false) {
        try {
            await this.bsModalService.show(UpdatePluginOfAppComponent, {
                class: 'modal-sm',
                ariaDescribedby: 'modal-body',
                ariaLabelledBy: 'modal-title',
                initialState: {
                    app,
                    plugin,
                    downgrade
                },
                ignoreBackdropClick: true
            }).content.result;
            this.refresh();
        }
        catch (er) {
            return;
        }
    }
    refresh() {
        this.loadData();
    }
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
    isStandard(app) {
        return (
        // ensure that every remote from the manifest is in the config
        this.everyRemoteFromManifestIsInConfig(app) &&
            // should not have any excluded remotes
            Object.keys(app?.config?.excludedRemotes || {}).length === 0 &&
            // ensure that every remote from the config is in the manifest
            this.everyRemoteFromConfigIsInManifest(app));
    }
    everyRemoteFromManifestIsInConfig(app) {
        const manifestRemotes = app?.manifest?.remotes;
        const configRemotes = app?.config?.remotes;
        if (!manifestRemotes || !configRemotes) {
            return true;
        }
        return Object.keys(manifestRemotes).every(contextPath => {
            return (Array.isArray(configRemotes[contextPath]) &&
                Array.isArray(manifestRemotes[contextPath]) &&
                manifestRemotes[contextPath].every(module => {
                    return configRemotes[contextPath].includes(module);
                }));
        });
    }
    everyRemoteFromConfigIsInManifest(app) {
        const manifestRemotes = app?.manifest?.remotes || {};
        const configRemotes = app?.config?.remotes;
        if (!configRemotes) {
            return true;
        }
        return Object.keys(configRemotes).every(contextPath => {
            return (Array.isArray(configRemotes[contextPath]) &&
                Array.isArray(manifestRemotes[contextPath]) &&
                configRemotes[contextPath].every(module => {
                    return manifestRemotes[contextPath].includes(module);
                }));
        });
    }
    addInstallButtonToHeaderActionControls() {
        if (this.appId) {
            this.headerActionControls = [
                {
                    text: gettext('Install plugins'),
                    callback: () => {
                        this.installPlugins();
                    },
                    icon: 'plus-circle',
                    type: 'custom'
                }
            ];
        }
    }
    async handleRemotesInstallation(plugins) {
        const updatedRemotes = await this.pluginsService.addRemotes(this.app, plugins);
        return this.emitRemotes(updatedRemotes);
    }
    emitRemotes(pluginsConfig) {
        const { remotes, excludedRemotes } = pluginsConfig;
        // needed for first time adding/removing a plugin
        if (!this.app.config) {
            this.app.config = {};
        }
        this.app.config.remotes = remotes;
        this.app.config.excludedRemotes = excludedRemotes;
        const actualRemotes = this.pluginsService.getMFRemotes(this.app);
        this.remotePlugins$.next(actualRemotes);
        return { ...this.remotePlugins$.value };
    }
    async getApplicationMO() {
        let id = this.appId;
        if (!id) {
            const { id: routeId } = this.activatedRoute.snapshot.parent.data.contextData;
            id = routeId;
        }
        try {
            this.app = await this.ecosystemService.getApplication(id);
        }
        catch (er) {
            if (er) {
                this.alertService.addServerFailure(er);
            }
        }
        return this.app;
    }
    async getApplicationMFExports(app) {
        const applicationExports = this.pluginsService.getMFExports(app, [], true);
        return applicationExports;
    }
    async getApplicationMFRemotes(app) {
        const appConfigRemotes = this.pluginsService.getMFRemotes(app);
        this.remotePlugins$.next(appConfigRemotes || {});
    }
    async getAllApplicationsMFExports(app) {
        const exportedByCurrentApp = await this.getApplicationMFExports(app);
        const allAppsMFExports = await this.pluginsService.getAllMFExports(true);
        this.allAvailablePlugins$.next([...allAppsMFExports, ...exportedByCurrentApp]);
    }
    async getAllSelfMFExports(app) {
        const exportedByCurrentApp = await this.getApplicationMFExports(app);
        this.selfPlugins$.next(exportedByCurrentApp.filter(({ scope }) => scope === 'self'));
    }
    getInstallModalInitState() {
        return {
            plugins$: combineLatest([this.allAvailablePlugins$, this.installedPlugins$]).pipe(map(([allPlugins, installedPlugins]) => {
                // to not mutate the original array and objects contained in it
                const allPluginsAsNewObjects = allPlugins.map(p => ({ ...p }));
                for (const plugin of installedPlugins) {
                    let installedPlugin = allPluginsAsNewObjects.find(p => p.id === plugin.id);
                    if (!installedPlugin && plugin.installedViaTag) {
                        installedPlugin = allPluginsAsNewObjects.find(p => p.contextPath === plugin.contextPath &&
                            p.module === plugin.module &&
                            p.tags?.includes(plugin.installedViaTag));
                    }
                    if (installedPlugin) {
                        installedPlugin.installed = true;
                        continue;
                    }
                }
                return allPluginsAsNewObjects.map(p => ({ ...p, installed: !!p.installed }));
            }), shareReplay(1))
        };
    }
    getOrphanedPlugins(orphanedPluginIds, allPlugins) {
        const orphanedPlugins = orphanedPluginIds.map(p => this.extractDetails(p));
        const orphanedPluginsUpdated = orphanedPlugins.map(p => {
            const pluginWithMatchingTag = allPlugins.find(tmp => tmp.contextPath === p.contextPath &&
                tmp.module === p.module &&
                tmp.tags?.includes(p.version || 'latest'));
            if (pluginWithMatchingTag) {
                return {
                    ...pluginWithMatchingTag,
                    id: p.id,
                    status: ApplicationPluginStatus.AUTO,
                    installedViaTag: p.version || 'latest'
                };
            }
            const pluginInDifferentVersion = allPlugins.find(tmp => tmp.contextPath === p.contextPath && tmp.module === p.module);
            if (pluginInDifferentVersion) {
                return {
                    ...pluginInDifferentVersion,
                    version: p.version,
                    id: p.id,
                    status: ApplicationPluginStatus.OUTDATED
                };
            }
            return p;
        });
        return orphanedPluginsUpdated;
    }
    splitOrphanedPluginsIntoOrphanedAndRevokedPlugins(allPlugins, orphanedPlugins) {
        const revokedPlugins = new Array();
        const actuallyOrphanedPlugins = new Array();
        for (const plugin of orphanedPlugins) {
            const foundFamiliarPlugin = allPlugins.find(plugin1 => plugin.contextPath === plugin1.contextPath && plugin.module === plugin1.module);
            if (foundFamiliarPlugin) {
                revokedPlugins.push(Object.assign({}, foundFamiliarPlugin, plugin, {
                    status: ApplicationPluginStatus.REVOKED
                }));
            }
            else {
                actuallyOrphanedPlugins.push(plugin);
            }
        }
        return { revokedPlugins, actuallyOrphanedPlugins };
    }
    getInstalledPlugins(allPlugins, remotePlugins) {
        const availablePlugins = allPlugins
            .filter(plugin => remotePlugins.includes(plugin.id))
            .map(plugin => Object.assign(plugin, {
            status: plugin.tags?.includes('latest')
                ? ApplicationPluginStatus.LATEST
                : ApplicationPluginStatus.OUTDATED
        }));
        const orphanedPluginIds = remotePlugins.filter(r => !availablePlugins.find(plugin => plugin.id === r));
        const orphanedPlugins = this.getOrphanedPlugins(orphanedPluginIds, allPlugins);
        const notActuallyOrphanedPlugins = orphanedPlugins.filter(p => p.status === ApplicationPluginStatus.AUTO);
        const orphanedOrRevokedPlugins = orphanedPlugins.filter(p => p.status !== ApplicationPluginStatus.AUTO);
        const { actuallyOrphanedPlugins, revokedPlugins } = this.splitOrphanedPluginsIntoOrphanedAndRevokedPlugins(allPlugins, orphanedOrRevokedPlugins);
        return [
            ...availablePlugins,
            ...notActuallyOrphanedPlugins,
            ...revokedPlugins,
            ...actuallyOrphanedPlugins
        ];
    }
    extractDetails(pluginId) {
        const contextPath = this.getStringMatchingRegex(pluginId, /^[^@]*(@|\/)/);
        const version = this.getStringMatchingRegex(pluginId, /@.*\//);
        const module = this.getStringMatchingRegex(pluginId, /\/.*$/);
        const unavailable = gettext('unavailable`plugin`');
        return {
            id: pluginId,
            idLatest: `${contextPath}/${module}`,
            path: '',
            module,
            name: module,
            status: ApplicationPluginStatus.ORPHANED,
            contextPath: contextPath,
            description: unavailable,
            version: version
        };
    }
    getStringMatchingRegex(str, regex) {
        const matches = str.match(regex);
        const value = matches ? matches[0] : '';
        return value.replace(/(@|\/)/g, '');
    }
    triggerPluginEvent(plugin, result) {
        const pluginInfo = pick(plugin, [
            'name',
            'contextPath',
            'module',
            'version',
            'type',
            'id'
        ]);
        this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.INSTALLED_PLUGINS, {
            component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.APPLICATION_PLUGINS,
            result,
            url: this.CURRENT_LOCATION,
            ...pluginInfo,
            targetApplicationName: this.app.name,
            targetApplicationContextPath: this.app.contextPath
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsComponent, deps: [{ token: i1$1.ActivatedRoute }, { token: i3.EcosystemService }, { token: i1.BsModalService }, { token: i2.PluginsService }, { token: i2.AlertService }, { token: i2.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
    static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.9", type: ApplicationPluginsComponent, selector: "c8y-app-plugins", inputs: { appId: "appId" }, viewQueries: [{ propertyName: "dataGrid", first: true, predicate: DataGridComponent, descendants: true }], ngImport: i0, template: "<c8y-title>{{ app | humanizeAppName | async }}</c8y-title>\n\n<c8y-breadcrumb>\n  <c8y-breadcrumb-item\n    [icon]=\"'c8y-atom'\"\n    [label]=\"'Ecosystem' | translate\"\n  ></c8y-breadcrumb-item>\n  <c8y-breadcrumb-item\n    [icon]=\"'c8y-modules'\"\n    [label]=\"'Applications' | translate\"\n    [path]=\"'ecosystem/application/applications'\"\n  ></c8y-breadcrumb-item>\n  <c8y-breadcrumb-item [label]=\"app | humanizeAppName | async\"></c8y-breadcrumb-item>\n  <c8y-breadcrumb-item [label]=\"'Plugins' | translate\"></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n  [placement]=\"'right'\"\n  *ngIf=\"!(isStandard$ | async)\"\n>\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Reset to default plugins' | translate }}\"\n    [ngClass]=\"{ 'btn-pending': isLoading }\"\n    (click)=\"resetToDefault()\"\n  >\n    <i c8yIcon=\"undo\"></i>\n    {{ 'Reset to default' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Install plugins' | translate }}\"\n    (click)=\"installPlugins()\"\n    [ngClass]=\"{ 'btn-pending': isLoading }\"\n  >\n    <i c8yIcon=\"plus-circle\"></i>\n    {{ 'Install plugins' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<ng-container *ngIf=\"orphanedPlugins$ | async as orphanedPlugins\">\n  <c8y-action-bar-item\n    *ngIf=\"orphanedPlugins?.length\"\n    [placement]=\"'right'\"\n  >\n    <button\n      class=\"btn btn-link\"\n      title=\"{{ 'Clean up orphaned plugins' | translate }}\"\n      (click)=\"cleanupOrphanedPlugins(orphanedPlugins)\"\n      [ngClass]=\"{ 'btn-pending': isLoading }\"\n    >\n      <i c8yIcon=\"erase\"></i>\n      {{ 'Clean up orphaned plugins' | translate }}\n    </button>\n  </c8y-action-bar-item>\n</ng-container>\n\n<div class=\"content-fullpage d-flex d-col border-top\">\n  <c8y-data-grid\n    class=\"d-contents\"\n    [title]=\"title\"\n    [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n    [loadingItemsLabel]=\"loadingItemsLabel\"\n    [displayOptions]=\"displayOptions\"\n    [columns]=\"columns\"\n    [rows]=\"installedPlugins$ | async\"\n    [pagination]=\"pagination\"\n    [selectable]=\"true\"\n    [actionControls]=\"actionControls\"\n    [bulkActionControls]=\"bulkActionControls\"\n    [headerActionControls]=\"headerActionControls\"\n    (onReload)=\"refresh()\"\n  >\n    <c8y-ui-empty-state\n      [icon]=\"stats?.size > 0 ? 'search' : 'plugin'\"\n      [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n      [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\"\n      *emptyStateContext=\"let stats\"\n      [horizontal]=\"stats?.size > 0\"\n    >\n      <p *ngIf=\"stats?.size === 0\">\n        <button\n          class=\"btn btn-primary btn-sm\"\n          title=\"{{ 'Install plugins' | translate }}\"\n          (click)=\"installPlugins()\"\n          [ngClass]=\"{ 'btn-pending': isLoading }\"\n          translate\n        >\n          Install plugins\n        </button>\n      </p>\n    </c8y-ui-empty-state>\n  </c8y-data-grid>\n</div>\n", dependencies: [{ kind: "component", type: i2.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i2.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i2.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.EmptyStateContextDirective, selector: "[emptyStateContext]" }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "columns", "rows", "pagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows"], outputs: ["rowMouseOver", "rowMouseLeave", "rowClick", "onConfigChange", "onBeforeFilter", "onBeforeSearch", "onFilter", "itemsSelect", "onReload", "onAddCustomColumn", "onRemoveCustomColumn", "onColumnFilterReset", "onSort", "onPageSizeChange", "onColumnReordered", "onColumnVisibilityChange"] }, { kind: "component", type: i2.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.HumanizeAppNamePipe, name: "humanizeAppName" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsComponent, decorators: [{
            type: Component,
            args: [{ selector: 'c8y-app-plugins', template: "<c8y-title>{{ app | humanizeAppName | async }}</c8y-title>\n\n<c8y-breadcrumb>\n  <c8y-breadcrumb-item\n    [icon]=\"'c8y-atom'\"\n    [label]=\"'Ecosystem' | translate\"\n  ></c8y-breadcrumb-item>\n  <c8y-breadcrumb-item\n    [icon]=\"'c8y-modules'\"\n    [label]=\"'Applications' | translate\"\n    [path]=\"'ecosystem/application/applications'\"\n  ></c8y-breadcrumb-item>\n  <c8y-breadcrumb-item [label]=\"app | humanizeAppName | async\"></c8y-breadcrumb-item>\n  <c8y-breadcrumb-item [label]=\"'Plugins' | translate\"></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n  [placement]=\"'right'\"\n  *ngIf=\"!(isStandard$ | async)\"\n>\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Reset to default plugins' | translate }}\"\n    [ngClass]=\"{ 'btn-pending': isLoading }\"\n    (click)=\"resetToDefault()\"\n  >\n    <i c8yIcon=\"undo\"></i>\n    {{ 'Reset to default' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n  <button\n    class=\"btn btn-link\"\n    title=\"{{ 'Install plugins' | translate }}\"\n    (click)=\"installPlugins()\"\n    [ngClass]=\"{ 'btn-pending': isLoading }\"\n  >\n    <i c8yIcon=\"plus-circle\"></i>\n    {{ 'Install plugins' | translate }}\n  </button>\n</c8y-action-bar-item>\n\n<ng-container *ngIf=\"orphanedPlugins$ | async as orphanedPlugins\">\n  <c8y-action-bar-item\n    *ngIf=\"orphanedPlugins?.length\"\n    [placement]=\"'right'\"\n  >\n    <button\n      class=\"btn btn-link\"\n      title=\"{{ 'Clean up orphaned plugins' | translate }}\"\n      (click)=\"cleanupOrphanedPlugins(orphanedPlugins)\"\n      [ngClass]=\"{ 'btn-pending': isLoading }\"\n    >\n      <i c8yIcon=\"erase\"></i>\n      {{ 'Clean up orphaned plugins' | translate }}\n    </button>\n  </c8y-action-bar-item>\n</ng-container>\n\n<div class=\"content-fullpage d-flex d-col border-top\">\n  <c8y-data-grid\n    class=\"d-contents\"\n    [title]=\"title\"\n    [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n    [loadingItemsLabel]=\"loadingItemsLabel\"\n    [displayOptions]=\"displayOptions\"\n    [columns]=\"columns\"\n    [rows]=\"installedPlugins$ | async\"\n    [pagination]=\"pagination\"\n    [selectable]=\"true\"\n    [actionControls]=\"actionControls\"\n    [bulkActionControls]=\"bulkActionControls\"\n    [headerActionControls]=\"headerActionControls\"\n    (onReload)=\"refresh()\"\n  >\n    <c8y-ui-empty-state\n      [icon]=\"stats?.size > 0 ? 'search' : 'plugin'\"\n      [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n      [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\"\n      *emptyStateContext=\"let stats\"\n      [horizontal]=\"stats?.size > 0\"\n    >\n      <p *ngIf=\"stats?.size === 0\">\n        <button\n          class=\"btn btn-primary btn-sm\"\n          title=\"{{ 'Install plugins' | translate }}\"\n          (click)=\"installPlugins()\"\n          [ngClass]=\"{ 'btn-pending': isLoading }\"\n          translate\n        >\n          Install plugins\n        </button>\n      </p>\n    </c8y-ui-empty-state>\n  </c8y-data-grid>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1$1.ActivatedRoute }, { type: i3.EcosystemService }, { type: i1.BsModalService }, { type: i2.PluginsService }, { type: i2.AlertService }, { type: i2.GainsightService }], propDecorators: { appId: [{
                type: Input
            }], dataGrid: [{
                type: ViewChild,
                args: [DataGridComponent, { static: false }]
            }] } });

class ApplicationPluginsGuard {
    constructor(ecosystemService) {
        this.ecosystemService = ecosystemService;
    }
    canActivate(route) {
        const app = route.data.contextData || route.parent.data.contextData;
        if (!app) {
            return false;
        }
        const manifest = app.manifest;
        if (!manifest) {
            return false;
        }
        return (app.type === ApplicationType.HOSTED &&
            this.ecosystemService.isOwner(app) &&
            !this.ecosystemService.isPackage(app) &&
            // apps like e.g. the public-options should not have the plugins tab
            !manifest.noAppSwitcher);
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsGuard, deps: [{ token: i3.EcosystemService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsGuard }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsGuard, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i3.EcosystemService }] });

class ApplicationPluginsModule {
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsModule, declarations: [ApplicationPluginsComponent,
            PluginListItemComponent,
            InstallPluginComponent,
            PluginListComponent,
            AppsToUpdateRemotesSelectComponent,
            AppStatePipe,
            LabelCellRendererComponent,
            OrphanedStatusCellRendererComponent,
            UpdatePluginOfAppComponent,
            OnlyLatestPluginVersionPipe], imports: [CoreModule, SharedEcosystemModule], exports: [ApplicationPluginsComponent,
            PluginListItemComponent,
            InstallPluginComponent,
            PluginListComponent,
            AppsToUpdateRemotesSelectComponent,
            AppStatePipe,
            LabelCellRendererComponent,
            OrphanedStatusCellRendererComponent,
            UpdatePluginOfAppComponent] }); }
    static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsModule, providers: [
            ApplicationPluginsGuard,
            hookRoute([
                {
                    path: 'plugins',
                    component: ApplicationPluginsComponent,
                    icon: 'plugin',
                    label: gettext('Plugins'),
                    context: ViewContext.Application,
                    priority: 3,
                    canActivate: [ApplicationPluginsGuard]
                }
            ])
        ], imports: [CoreModule, SharedEcosystemModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: ApplicationPluginsModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [CoreModule, SharedEcosystemModule],
                    declarations: [
                        ApplicationPluginsComponent,
                        PluginListItemComponent,
                        InstallPluginComponent,
                        PluginListComponent,
                        AppsToUpdateRemotesSelectComponent,
                        AppStatePipe,
                        LabelCellRendererComponent,
                        OrphanedStatusCellRendererComponent,
                        UpdatePluginOfAppComponent,
                        OnlyLatestPluginVersionPipe
                    ],
                    exports: [
                        ApplicationPluginsComponent,
                        PluginListItemComponent,
                        InstallPluginComponent,
                        PluginListComponent,
                        AppsToUpdateRemotesSelectComponent,
                        AppStatePipe,
                        LabelCellRendererComponent,
                        OrphanedStatusCellRendererComponent,
                        UpdatePluginOfAppComponent
                    ],
                    providers: [
                        ApplicationPluginsGuard,
                        hookRoute([
                            {
                                path: 'plugins',
                                component: ApplicationPluginsComponent,
                                icon: 'plugin',
                                label: gettext('Plugins'),
                                context: ViewContext.Application,
                                priority: 3,
                                canActivate: [ApplicationPluginsGuard]
                            }
                        ])
                    ]
                }]
        }] });

/**
 * Generated bundle index. Do not edit.
 */

export { AppStatePipe, ApplicationPluginsComponent, ApplicationPluginsGuard, ApplicationPluginsModule, AppsToUpdateRemotesSelectComponent, InstallPluginComponent, LabelCellRendererComponent, OrphanedStatusCellRendererComponent, PluginListComponent, PluginListItemComponent, UpdatePluginOfAppComponent };
//# sourceMappingURL=c8y-ngx-components-ecosystem-application-plugins.mjs.map
