UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

492 lines (482 loc) 35.8 kB
import * as i0 from '@angular/core'; import { Injectable, EventEmitter, Output, Component, ViewChild, NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import * as i1 from '@c8y/ngx-components'; import { Permissions, NavigatorNode, IconDirective, C8yTranslateDirective, FilePickerFormControlComponent, C8yTranslatePipe, BuiltInActionType, Status, TitleComponent, BreadcrumbComponent, BreadcrumbItemComponent, ActionBarItemComponent, IfAllowedDirective, HelpComponent, DataGridComponent, EmptyStateContextDirective, EmptyStateComponent, ColumnDirective, CellRendererDefDirective, DatePipe, BytesPipe, CoreModule, DropAreaModule, hookNavigator, hookRoute } from '@c8y/ngx-components'; import { gettext } from '@c8y/ngx-components/gettext'; import * as i1$1 from '@c8y/client'; import { QueriesUtil } from '@c8y/client'; import * as i5 from '@ngx-translate/core'; import * as i4 from 'ngx-bootstrap/modal'; import { combineLatest, Subject } from 'rxjs'; import { take, takeUntil } from 'rxjs/operators'; import { has, transform } from 'lodash-es'; import { NgIf } from '@angular/common'; import { FilePreviewComponent, FilePreviewModule } from '@c8y/ngx-components/file-preview'; class FilesRepositoryGuard { constructor(permissions) { this.permissions = permissions; } /** * Checks if files repository should be active, * i.e. whether the current tenant can read or admin files in repository. * * @returns True, if the feature should be active. */ canActivate() { return (this.permissions.hasRole(Permissions.ROLE_INVENTORY_READ) || this.permissions.hasAllRoles([ Permissions.ROLE_MANAGED_OBJECT_READ, Permissions.ROLE_BINARY_READ ])); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryGuard, deps: [{ token: i1.Permissions }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryGuard, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryGuard, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.Permissions }] }); class FilesRepositoryNavigationFactory { constructor(filesRepositoryGuard) { this.filesRepositoryGuard = filesRepositoryGuard; this.navs = []; } async get() { if (this.filesRepositoryGuard.canActivate()) { if (!this.navs.length) { this.navs.push(new NavigatorNode({ parent: gettext('Management'), label: gettext('Files repository'), icon: 'c8y-archive', path: 'files', routerLinkExact: false, priority: 1000 })); } } return this.navs; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryNavigationFactory, deps: [{ token: FilesRepositoryGuard }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryNavigationFactory, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryNavigationFactory, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: FilesRepositoryGuard }] }); const PRODUCT_EXPERIENCE_FILE_REPOSITORY = { EVENTS: { FILE_REPOSITORY_UPLOAD: 'filesRepositoryUpload' }, COMPONENTS: { FILE_REPOSITORY_UPLOAD_COMPONENT: 'files-repository-upload' }, RESULTS: { UPLOAD_ITEM_SUCCESS: 'fileUploadSuccess', UPLOAD_ITEM_FAILED: 'fileUploadFailed' } }; class FilesRepositoryUploadComponent { constructor(alertService, gainsightService, filesService) { this.alertService = alertService; this.gainsightService = gainsightService; this.filesService = filesService; /** Emits an event when modal is closed. `uploaded` indicates if any files were uploaded. */ this.onClose = new EventEmitter(); this.isLoading = false; this.dropFilesHereMessage = gettext('Drop files here'); } async upload() { this.isLoading = true; this.uploadProgress$ = combineLatest(this.filesToUpload.map(file => this.filesService.uploadFileWithProgress$(file))); this.uploadSubscription = this.uploadProgress$.subscribe(uploadProgress => { this.uploadProgress = uploadProgress; }, e => { if (e) { this.alertService.addServerFailure(e); this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_FILE_REPOSITORY.EVENTS.FILE_REPOSITORY_UPLOAD, { component: PRODUCT_EXPERIENCE_FILE_REPOSITORY.COMPONENTS.FILE_REPOSITORY_UPLOAD_COMPONENT, action: PRODUCT_EXPERIENCE_FILE_REPOSITORY.RESULTS.UPLOAD_ITEM_FAILED }); } this.isLoading = false; }, () => { this.alertService.success(gettext('File(s) uploaded.')); this.onClose.emit({ uploaded: true }); this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_FILE_REPOSITORY.EVENTS.FILE_REPOSITORY_UPLOAD, { component: PRODUCT_EXPERIENCE_FILE_REPOSITORY.COMPONENTS.FILE_REPOSITORY_UPLOAD_COMPONENT, action: PRODUCT_EXPERIENCE_FILE_REPOSITORY.RESULTS.UPLOAD_ITEM_SUCCESS }); }); } onFileDroppedEvent(event) { if (event && event.length > 0) { this.filesToUpload = event; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryUploadComponent, deps: [{ token: i1.AlertService }, { token: i1.GainsightService }, { token: i1.FilesService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: FilesRepositoryUploadComponent, isStandalone: true, selector: "c8y-files-repository-upload", outputs: { onClose: "onClose" }, ngImport: i0, template: "<div class=\"c8y-viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i c8yIcon=\"upload\"></i>\n <h4\n id=\"modal-title\"\n translate\n >\n Upload files\n </h4>\n </div>\n <div class=\"modal-inner-scroll\">\n <div\n class=\"modal-body\"\n id=\"modal-body\"\n >\n <c8y-file-picker-form-control\n #filePicker\n [uploadInProgress]=\"isLoading\"\n (dropped)=\"onFileDroppedEvent($event)\"\n [uploadProgress]=\"uploadProgress\"\n ></c8y-file-picker-form-control>\n </div>\n </div>\n <div class=\"card-footer separator d-flex j-c-center\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"onClose.emit({ uploaded: false })\"\n [disabled]=\"isLoading\"\n translate\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary btn-form\"\n title=\"{{ 'Upload' | translate }}\"\n type=\"button\"\n (click)=\"upload()\"\n [disabled]=\"!filePicker.valid || isLoading\"\n translate\n data-cy=\"c8y-files-repository-upload--upload\"\n >\n Upload\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: FilePickerFormControlComponent, selector: "c8y-file-picker-form-control", inputs: ["accept", "maxAllowedFiles", "minRequiredFiles", "disableValidators", "uploadInProgress", "uploadProgress", "validateExtensionOnDrag"], outputs: ["dropped"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryUploadComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-files-repository-upload', imports: [IconDirective, C8yTranslateDirective, FilePickerFormControlComponent, C8yTranslatePipe], template: "<div class=\"c8y-viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i c8yIcon=\"upload\"></i>\n <h4\n id=\"modal-title\"\n translate\n >\n Upload files\n </h4>\n </div>\n <div class=\"modal-inner-scroll\">\n <div\n class=\"modal-body\"\n id=\"modal-body\"\n >\n <c8y-file-picker-form-control\n #filePicker\n [uploadInProgress]=\"isLoading\"\n (dropped)=\"onFileDroppedEvent($event)\"\n [uploadProgress]=\"uploadProgress\"\n ></c8y-file-picker-form-control>\n </div>\n </div>\n <div class=\"card-footer separator d-flex j-c-center\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"onClose.emit({ uploaded: false })\"\n [disabled]=\"isLoading\"\n translate\n >\n Cancel\n </button>\n <button\n class=\"btn btn-primary btn-form\"\n title=\"{{ 'Upload' | translate }}\"\n type=\"button\"\n (click)=\"upload()\"\n [disabled]=\"!filePicker.valid || isLoading\"\n translate\n data-cy=\"c8y-files-repository-upload--upload\"\n >\n Upload\n </button>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.AlertService }, { type: i1.GainsightService }, { type: i1.FilesService }], propDecorators: { onClose: [{ type: Output }] } }); class FilesRepositoryService { constructor(inventoryService) { this.inventoryService = inventoryService; this.baseQuery = { __has: 'c8y_IsBinary' }; this.queriesUtil = new QueriesUtil(); } getPagination() { return { pageSize: 10, currentPage: 1 }; } hasApplicationStorageFragment(file) { return has(file, 'c8y_applications_storage'); } getColumns() { return [ { name: 'name', header: gettext('Name'), path: 'name', filterable: true, sortable: true, sortOrder: 'asc' }, { name: 'type', header: gettext('Type'), path: 'type', filterable: true, sortable: true }, { name: 'length', header: gettext('Size'), path: 'length', filterable: false, sortable: true }, { name: 'owner', header: gettext('Owner'), path: 'owner', filterable: true, sortable: true }, { name: 'lastUpdated', header: gettext('Last update'), path: 'lastUpdated', filterable: false, sortable: true } ]; } /** Returns array with items id where item has not c8y_applications_storage fragment. */ getDeletableItemsIds(selectedItemsIds, dataFromDataGrid) { const selectedItemsWithoutApplications = []; dataFromDataGrid.forEach(item => { selectedItemsIds.forEach(selectedItemId => { if (selectedItemId === item.id && !this.hasApplicationStorageFragment(item)) { selectedItemsWithoutApplications.push(selectedItemId); } }); }); return selectedItemsWithoutApplications; } /** Returns the total number of items (with no filters based on columns setup). */ async getTotal() { const filters = { query: this.queriesUtil.buildQuery(this.baseQuery), withTotalElements: true }; return (await this.inventoryService.list(filters)).paging.totalElements; } /** Returns data for current columns and pagination setup. */ async getData(columns, pagination, searchText = '') { // build filters based on columns and pagination const filters = { text: searchText, ...this.getFilters(columns, pagination), withTotalElements: true }; // execute inventory query for the list of managed objects return this.inventoryService.list(filters); } /** Returns filters for given columns and pagination setup. */ getFilters(columns, pagination) { return { query: this.getQueryString(columns), pageSize: pagination.pageSize, currentPage: pagination.currentPage, withChildren: false, withTotalPages: true }; } /** Returns a query string based on columns setup. */ getQueryString(columns) { let fullQuery = this.getQueryObj(columns); fullQuery = this.queriesUtil.addAndFilter(fullQuery, this.baseQuery); return this.queriesUtil.buildQuery(fullQuery); } /** Returns a query object based on columns setup. */ getQueryObj(columns) { return transform(columns, (query, column) => this.addColumnQuery(query, column), { __filter: {}, __orderby: [] }); } /** Extends given query with a part based on the setup of given column. */ addColumnQuery(query, column) { // when a column is marked as filterable if (column.filterable) { // in the case of default filtering form, `filterPredicate` will contain the string entered by a user if (column.filterPredicate) { // so we use it as the expected value, * allow to search for it anywhere in the property query.__filter[column.path] = `*${column.filterPredicate}*`; } // in the case of custom filtering form, we're storing the query in `externalFilterQuery.query` if (column.externalFilterQuery) { query = this.queriesUtil.addAndFilter(query, column.externalFilterQuery.query); } } // when a column is sortable and has a specified sorting order if (column.sortable && column.sortOrder) { // add sorting condition for the configured column `path` query.__orderby.push({ [column.path]: column.sortOrder === 'asc' ? 1 : -1 }); } return query; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryService, deps: [{ token: i1$1.InventoryService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1$1.InventoryService }] }); class FilesRepositoryComponent { constructor(filesRepositoryService, inventoryBinaryService, modalService, alertService, bsModalService, fileService, translateService) { this.filesRepositoryService = filesRepositoryService; this.inventoryBinaryService = inventoryBinaryService; this.modalService = modalService; this.alertService = alertService; this.bsModalService = bsModalService; this.fileService = fileService; this.translateService = translateService; this.destroy$ = new Subject(); this.title = gettext('Files repository'); this.managementTitle = gettext('Management'); this.loadMoreItemsLabel = gettext('Load more files'); this.loadingItemsLabel = gettext('Loading files'); this.isLoading = true; this.displayOptions = { bordered: false, striped: true, filter: true, gridHeader: true, hover: true }; this.columns = this.filesRepositoryService.getColumns(); this.pagination = this.filesRepositoryService.getPagination(); this.infiniteScroll = 'auto'; this.selectable = true; this.actionControls = [ { text: gettext('Delete'), icon: 'trash', type: BuiltInActionType.Delete, showIf: selectedItem => !this.filesRepositoryService.hasApplicationStorageFragment(selectedItem), callback: selectedItem => this.onDeleteItem(selectedItem) }, { text: gettext('Download'), icon: 'download', type: BuiltInActionType.Export, callback: selectedItem => this.onDownloadItem(selectedItem) } ]; this.bulkActionControls = [ { type: BuiltInActionType.Delete, callback: selectedItemIds => this.onDeleteItems(selectedItemIds) } ]; this.refresh = new EventEmitter(); this.noResultsMessage = gettext('No results to display.'); this.noDataMessage = gettext('No files to display.'); this.noResultsSubtitle = gettext('Refine your search terms or check your spelling.'); this.noDataSubtitle = gettext('Add a new file by clicking below.'); // we're setting up `serverSideDataCallback` to execute a method from this component with bound `this` this.serverSideDataCallback = this.onDataSourceModifier.bind(this); } async onDataSourceModifier(dataSourceModifier) { const { res, data, paging } = await this.filesRepositoryService.getData(dataSourceModifier.columns, dataSourceModifier.pagination, dataSourceModifier.searchText); const filteredSize = paging.totalElements; const size = await this.filesRepositoryService.getTotal(); const serverSideDataResult = { res, data, paging, filteredSize, size }; this.isLoading = false; this.returnedDataSize = serverSideDataResult.size; return serverSideDataResult; } async onDeleteItem(selectedItem) { return this.deleteItemsWithConfirmation([selectedItem.id], { title: gettext('Delete file'), body: this.translateService.instant(gettext('You are about to delete file "{{ name }}". Do you want to proceed?'), selectedItem), successText: gettext('File deleted.') }); } async onDeleteItems(selectedItemsIds) { const dataGridDataSourceData = await this.dataGrid.dataSource.data$.pipe(take(1)).toPromise(); const deletableItemsIds = this.filesRepositoryService.getDeletableItemsIds(selectedItemsIds, dataGridDataSourceData); let body; if (deletableItemsIds.length < selectedItemsIds.length) { body = gettext(` You are about to delete the selected files. Note: the selected files of type "c8y_applications_storage_*" won't be deleted though - such files can be deleted only from the "Activity log" of the associated application. Do you want to proceed? `); } else { body = gettext('You are about to delete the selected files. Do you want to proceed?'); } return this.deleteItemsWithConfirmation(deletableItemsIds, { title: gettext('Delete files'), body, successText: gettext('Files deleted.') }); } async onDownloadItem(selectedItem) { return this.fileService.download(selectedItem); } openFileUploadComponent() { const modalOptions = { class: 'modal-sm', ariaDescribedby: 'modal-body', ariaLabelledBy: 'modal-title', ignoreBackdropClick: true }; const modalRef = this.bsModalService.show(FilesRepositoryUploadComponent, modalOptions); modalRef.content.onClose.pipe(takeUntil(this.destroy$)).subscribe(({ uploaded }) => { if (uploaded) { this.refresh.emit(); } modalRef.hide(); }); } async deleteItemsWithConfirmation(selectedItemsIds, options) { try { await this.confirmItemsDeletion(options); this.isLoading = true; const promises = selectedItemsIds.map(selectedItemId => this.inventoryBinaryService.delete(selectedItemId)); await Promise.all(promises); this.alertService.success(options.successText); this.refresh.next(); } catch (ex) { if (ex) { this.alertService.addServerFailure(ex); } } finally { this.isLoading = false; } } async confirmItemsDeletion({ title, body }) { const status = Status.DANGER; const labels = { ok: gettext('Delete'), cancel: gettext('Cancel') }; await this.modalService.confirm(title, body, status, labels); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryComponent, deps: [{ token: FilesRepositoryService }, { token: i1$1.InventoryBinaryService }, { token: i1.ModalService }, { token: i1.AlertService }, { token: i4.BsModalService }, { token: i1.FilesService }, { token: i5.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.19", type: FilesRepositoryComponent, isStandalone: true, selector: "c8y-files-repository", viewQueries: [{ propertyName: "dataGrid", first: true, predicate: DataGridComponent, descendants: true, static: true }], ngImport: i0, template: "<c8y-title>\n {{ title | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-management\"\n [label]=\"managementTitle | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item [label]=\"title | translate\"></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Upload files' | translate }}\"\n *c8yIfAllowed=\"['ROLE_INVENTORY_ADMIN', 'ROLE_INVENTORY_CREATE']; allowAny: true\"\n (click)=\"openFileUploadComponent()\"\n data-cy=\"c8y-files-repository--open-file-upload-component\"\n >\n <i c8yIcon=\"upload\"></i>\n {{ 'Upload files' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/standard-tenant/managing-data/#file-repository\"></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [pagination]=\"pagination\"\n [infiniteScroll]=\"infiniteScroll\"\n [serverSideDataCallback]=\"serverSideDataCallback\"\n [actionControls]=\"actionControls\"\n [selectable]=\"selectable\"\n [showSearch]=\"true\"\n [refresh]=\"refresh\"\n [bulkActionControls]=\"bulkActionControls\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-archive'\"\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\"\n title=\"{{ 'Upload file' | translate }}\"\n type=\"button\"\n (click)=\"openFileUploadComponent()\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Upload file' | translate }}\n </button>\n </p>\n </c8y-ui-empty-state>\n\n <c8y-column name=\"name\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value }}\">\n <div class=\"d-flex j-c-between a-i-center\">\n {{ context.value }}\n <c8y-file-preview\n class=\"m-l-auto\"\n [mo]=\"context.item\"\n >\n <button\n class=\"btn btn-emphasis btn-icon\"\n [title]=\"'Preview file' | translate\"\n type=\"button\"\n customButton\n >\n <i c8yIcon=\"search\"></i>\n </button>\n </c8y-file-preview>\n </div>\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"length\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value }} B\">\n {{ context.value | bytes }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"lastUpdated\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value | c8yDate }}\">\n {{ context.value | c8yDate }}\n </span>\n </ng-container>\n </c8y-column>\n </c8y-data-grid>\n</div>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IfAllowedDirective, selector: "[c8yIfAllowed]", inputs: ["c8yIfAllowed", "c8yIfAllowedAllowAny"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "loading", "columns", "rows", "pagination", "childNodePagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows", "treeGrid", "hideReload", "childNodesProperty", "parentNodeLabelProperty"], outputs: ["rowMouseOver", "rowMouseLeave", "rowClick", "onConfigChange", "onBeforeFilter", "onBeforeSearch", "onFilter", "itemsSelect", "onReload", "onAddCustomColumn", "onRemoveCustomColumn", "onColumnFilterReset", "onSort", "onPageSizeChange", "onColumnReordered", "onColumnVisibilityChange"] }, { kind: "directive", type: EmptyStateContextDirective, selector: "[emptyStateContext]" }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: ColumnDirective, selector: "c8y-column", inputs: ["name"] }, { kind: "directive", type: CellRendererDefDirective, selector: "[c8yCellRendererDef]" }, { kind: "component", type: FilePreviewComponent, selector: "c8y-file-preview", inputs: ["mo", "downloadFn"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }, { kind: "pipe", type: BytesPipe, name: "bytes" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-files-repository', imports: [ TitleComponent, BreadcrumbComponent, BreadcrumbItemComponent, ActionBarItemComponent, IfAllowedDirective, IconDirective, HelpComponent, DataGridComponent, EmptyStateContextDirective, EmptyStateComponent, NgIf, ColumnDirective, CellRendererDefDirective, FilePreviewComponent, C8yTranslatePipe, DatePipe, BytesPipe ], template: "<c8y-title>\n {{ title | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-management\"\n [label]=\"managementTitle | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item [label]=\"title | translate\"></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Upload files' | translate }}\"\n *c8yIfAllowed=\"['ROLE_INVENTORY_ADMIN', 'ROLE_INVENTORY_CREATE']; allowAny: true\"\n (click)=\"openFileUploadComponent()\"\n data-cy=\"c8y-files-repository--open-file-upload-component\"\n >\n <i c8yIcon=\"upload\"></i>\n {{ 'Upload files' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help src=\"/docs/standard-tenant/managing-data/#file-repository\"></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"title\"\n [loadMoreItemsLabel]=\"loadMoreItemsLabel\"\n [loadingItemsLabel]=\"loadingItemsLabel\"\n [displayOptions]=\"displayOptions\"\n [columns]=\"columns\"\n [pagination]=\"pagination\"\n [infiniteScroll]=\"infiniteScroll\"\n [serverSideDataCallback]=\"serverSideDataCallback\"\n [actionControls]=\"actionControls\"\n [selectable]=\"selectable\"\n [showSearch]=\"true\"\n [refresh]=\"refresh\"\n [bulkActionControls]=\"bulkActionControls\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-archive'\"\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\"\n title=\"{{ 'Upload file' | translate }}\"\n type=\"button\"\n (click)=\"openFileUploadComponent()\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Upload file' | translate }}\n </button>\n </p>\n </c8y-ui-empty-state>\n\n <c8y-column name=\"name\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value }}\">\n <div class=\"d-flex j-c-between a-i-center\">\n {{ context.value }}\n <c8y-file-preview\n class=\"m-l-auto\"\n [mo]=\"context.item\"\n >\n <button\n class=\"btn btn-emphasis btn-icon\"\n [title]=\"'Preview file' | translate\"\n type=\"button\"\n customButton\n >\n <i c8yIcon=\"search\"></i>\n </button>\n </c8y-file-preview>\n </div>\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"length\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value }} B\">\n {{ context.value | bytes }}\n </span>\n </ng-container>\n </c8y-column>\n\n <c8y-column name=\"lastUpdated\">\n <ng-container *c8yCellRendererDef=\"let context\">\n <span title=\"{{ context.value | c8yDate }}\">\n {{ context.value | c8yDate }}\n </span>\n </ng-container>\n </c8y-column>\n </c8y-data-grid>\n</div>\n" }] }], ctorParameters: () => [{ type: FilesRepositoryService }, { type: i1$1.InventoryBinaryService }, { type: i1.ModalService }, { type: i1.AlertService }, { type: i4.BsModalService }, { type: i1.FilesService }, { type: i5.TranslateService }], propDecorators: { dataGrid: [{ type: ViewChild, args: [DataGridComponent, { static: true }] }] } }); class FilesRepositoryModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryModule, imports: [RouterModule, CoreModule, DropAreaModule, FilePreviewModule, FilesRepositoryComponent, FilesRepositoryUploadComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryModule, providers: [ FilesRepositoryGuard, hookNavigator(FilesRepositoryNavigationFactory), hookRoute({ path: 'files', component: FilesRepositoryComponent, canActivate: [FilesRepositoryGuard] }, { multi: true }), FilesRepositoryService ], imports: [RouterModule, CoreModule, DropAreaModule, FilePreviewModule, FilesRepositoryComponent, FilesRepositoryUploadComponent] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: FilesRepositoryModule, decorators: [{ type: NgModule, args: [{ imports: [ RouterModule, CoreModule, DropAreaModule, FilePreviewModule, FilesRepositoryComponent, FilesRepositoryUploadComponent ], exports: [], providers: [ FilesRepositoryGuard, hookNavigator(FilesRepositoryNavigationFactory), hookRoute({ path: 'files', component: FilesRepositoryComponent, canActivate: [FilesRepositoryGuard] }, { multi: true }), FilesRepositoryService ] }] }] }); /** * Generated bundle index. Do not edit. */ export { FilesRepositoryComponent, FilesRepositoryGuard, FilesRepositoryModule, FilesRepositoryNavigationFactory, FilesRepositoryService, FilesRepositoryUploadComponent }; //# sourceMappingURL=c8y-ngx-components-files-repository.mjs.map