UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

239 lines (233 loc) 18 kB
import * as i0 from '@angular/core'; import { Injectable, Input, Component } from '@angular/core'; import * as i2 from '@c8y/ngx-components'; import { gettext, C8yValidators, CoreModule, MarkdownToHtmlPipe } from '@c8y/ngx-components'; import * as i1 from '@angular/forms'; import { Validators, ReactiveFormsModule } from '@angular/forms'; import * as i2$1 from '@c8y/client'; import * as i3 from '@ngx-translate/core'; import * as i4 from '@angular/common'; import { AsyncPipe } from '@angular/common'; class MarkdownWidgetService { constructor(fileService, inventory, binary, alert, translate) { this.fileService = fileService; this.inventory = inventory; this.binary = binary; this.alert = alert; this.translate = translate; } async getFile(markdownBinaryId) { if (!markdownBinaryId) { return null; } try { const { data: markdownBinaryMo } = await this.inventory.detail(markdownBinaryId); const file = await this.fileService.getFile(markdownBinaryMo); return file; } catch (e) { const text = this.translate.instant(gettext('Unable to retrieve binary with ID: {{ markdownBinaryId }}'), { markdownBinaryId }); this.alert.danger(text, e?.data); } return null; } async uploadFile(file) { const { data: mo } = await this.binary.create(file); return mo.id; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MarkdownWidgetService, deps: [{ token: i2.FilesService }, { token: i2$1.InventoryService }, { token: i2$1.InventoryBinaryService }, { token: i2.AlertService }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MarkdownWidgetService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MarkdownWidgetService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i2.FilesService }, { type: i2$1.InventoryService }, { type: i2$1.InventoryBinaryService }, { type: i2.AlertService }, { type: i3.TranslateService }] }); class MarkdownWidgetConfigComponent { constructor(formBuilder, form, alert, markdownService) { this.formBuilder = formBuilder; this.form = form; this.alert = alert; this.markdownService = markdownService; this.uploadChoice = 'uploadUrl'; this.loading = false; } async onBeforeSave(config) { if (this.formGroup.invalid) { return false; } if (this.uploadChoice === 'uploadUrl') { Object.assign(config, { contentUrl: this.formGroup.value.contentUrl, markdownBinaryId: null }); return true; } const fileFromForm = this.getFileFromFormValue(this.formGroup.value); if (fileFromForm && fileFromForm !== this.fileFromConfig) { try { const markdownBinaryId = await this.markdownService.uploadFile(fileFromForm); Object.assign(config, { markdownBinaryId, contentUrl: null }); return true; } catch (e) { this.alert.danger(gettext('Unable to upload Markdown file.'), e?.data); return false; } } if (!fileFromForm) { Object.assign(config, { contentUrl: '/readme.md', markdownBinaryId: null }); } return true; } async ngOnInit() { this.initForm(); if (this.config.markdownBinaryId) { this.uploadChoice = 'uploadBinary'; this.fileFromConfig = await this.markdownService.getFile(this.config.markdownBinaryId); this.formGroup.patchValue({ droppedFile: [{ file: this.fileFromConfig, name: this.fileFromConfig.name }] }); } } onChange(value) { this.uploadChoice = value; this.formGroup.controls['uploadChoice'].patchValue(value); } getFileFromFormValue(formValue) { const binary = formValue?.droppedFile || []; return binary[0]?.file || null; } initForm() { this.formGroup = this.formBuilder.group({ contentUrl: ['', [Validators.maxLength(2000)]], droppedFile: [ null, [ Validators.minLength(1), Validators.maxLength(1), C8yValidators.filesValidator({ maximumFileSizeInKb: 1000 }) ] ], uploadChoice: [this.config.markdownBinaryId ? 'uploadBinary' : 'uploadUrl', []] }, { validators: this.requireEitherBinaryOrUrl() }); this.form.form.addControl('config', this.formGroup); this.formGroup.patchValue(this.config); } requireEitherBinaryOrUrl() { return (control) => { const url = control.get(`contentUrl`); const uploadBinary = control.get(`droppedFile`); const urlDefined = url && url.value !== undefined && url.value !== null; const uploadBinaryDefined = uploadBinary && uploadBinary.value !== undefined && uploadBinary.value !== null; const errors = {}; if (this.uploadChoice === 'uploadBinary' && !uploadBinaryDefined) { // sets error const error = { required: true }; uploadBinary.setErrors(Object.assign({}, uploadBinary.errors || {}, error)); Object.assign(errors, error); } else { // remove previous error this.removeErrors(uploadBinary, ['required']); } if (this.uploadChoice === 'uploadUrl' && (!urlDefined || url.value === '')) { // sets error const error = { required: true }; url.setErrors(Object.assign({}, url.errors || {}, error)); Object.assign(errors, error); } else { // remove previous error this.removeErrors(url, ['required']); } return Object.keys(errors).length ? errors : null; }; } removeErrors(control, errors) { if (!control || !control.errors) { return false; } let removedError = false; for (const error of errors) { if (control.errors[error]) { removedError = true; delete control.errors[error]; } } if (removedError) { control.setErrors(Object.keys(control.errors).length ? Object.assign({}, control.errors) : null); } return removedError; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MarkdownWidgetConfigComponent, deps: [{ token: i1.FormBuilder }, { token: i1.NgForm }, { token: i2.AlertService }, { token: MarkdownWidgetService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: MarkdownWidgetConfigComponent, isStandalone: true, selector: "c8y-markdown-widget-config", inputs: { config: "config" }, ngImport: i0, template: "<fieldset class=\"c8y-fieldset\">\n <legend>{{ 'Source' | translate }}</legend>\n <form [formGroup]=\"formGroup\" class=\"\">\n <div class=\"form-group\">\n <label title=\"{{ 'Upload a binary' | translate }}\" class=\"c8y-radio radio-inline\">\n <input\n #radio\n formControlName=\"uploadChoice\"\n type=\"radio\"\n value=\"uploadBinary\"\n name=\"uploadChoice\"\n (change)=\"onChange($event.target.value)\"\n />\n <span></span>\n <span>{{ 'Upload a binary' | translate }}</span>\n </label>\n <label title=\"{{ 'Provide a file path' | translate }}\" class=\"c8y-radio radio-inline m-l-8\">\n <input\n #radio\n formControlName=\"uploadChoice\"\n type=\"radio\"\n value=\"uploadUrl\"\n name=\"uploadChoice\"\n (change)=\"onChange($event.target.value)\"\n />\n <span></span>\n <span>\n {{ 'Provide a file path' | translate }}\n </span>\n </label>\n </div>\n <ng-container [ngSwitch]=\"uploadChoice\">\n <div *ngSwitchCase=\"'uploadBinary'\">\n <c8y-form-group class=\"m-b-8\">\n <c8y-drop-area\n formControlName=\"droppedFile\"\n class=\"drop-area-sm\"\n [title]=\"'Drop file or click to browse' | translate\"\n [maxAllowedFiles]=\"1\"\n [accept]=\"'md'\"\n ></c8y-drop-area>\n </c8y-form-group>\n </div>\n <div *ngSwitchCase=\"'uploadUrl'\">\n <c8y-form-group class=\"m-b-8\">\n <div class=\"m-b-4 p-b-8\">\n <div class=\"input-group\">\n <span class=\"input-group-addon\">\n <i c8yIcon=\"globe\"></i>\n </span>\n <input\n type=\"text\"\n class=\"form-control\"\n formControlName=\"contentUrl\"\n placeholder=\"{{ 'e.g.' | translate }} http://example.com/binary.zip\"\n />\n </div>\n </div>\n </c8y-form-group>\n </div>\n </ng-container>\n </form>\n</fieldset>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i2.DropAreaComponent, selector: "c8y-drop-area", inputs: ["formControl", "title", "message", "icon", "loadingMessage", "forceHideList", "alwaysShow", "clickToOpen", "loading", "progress", "maxAllowedFiles", "files", "maxFileSizeInMegaBytes", "accept"], outputs: ["dropped"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i2.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i2.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MarkdownWidgetConfigComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-markdown-widget-config', standalone: true, imports: [CoreModule, ReactiveFormsModule], template: "<fieldset class=\"c8y-fieldset\">\n <legend>{{ 'Source' | translate }}</legend>\n <form [formGroup]=\"formGroup\" class=\"\">\n <div class=\"form-group\">\n <label title=\"{{ 'Upload a binary' | translate }}\" class=\"c8y-radio radio-inline\">\n <input\n #radio\n formControlName=\"uploadChoice\"\n type=\"radio\"\n value=\"uploadBinary\"\n name=\"uploadChoice\"\n (change)=\"onChange($event.target.value)\"\n />\n <span></span>\n <span>{{ 'Upload a binary' | translate }}</span>\n </label>\n <label title=\"{{ 'Provide a file path' | translate }}\" class=\"c8y-radio radio-inline m-l-8\">\n <input\n #radio\n formControlName=\"uploadChoice\"\n type=\"radio\"\n value=\"uploadUrl\"\n name=\"uploadChoice\"\n (change)=\"onChange($event.target.value)\"\n />\n <span></span>\n <span>\n {{ 'Provide a file path' | translate }}\n </span>\n </label>\n </div>\n <ng-container [ngSwitch]=\"uploadChoice\">\n <div *ngSwitchCase=\"'uploadBinary'\">\n <c8y-form-group class=\"m-b-8\">\n <c8y-drop-area\n formControlName=\"droppedFile\"\n class=\"drop-area-sm\"\n [title]=\"'Drop file or click to browse' | translate\"\n [maxAllowedFiles]=\"1\"\n [accept]=\"'md'\"\n ></c8y-drop-area>\n </c8y-form-group>\n </div>\n <div *ngSwitchCase=\"'uploadUrl'\">\n <c8y-form-group class=\"m-b-8\">\n <div class=\"m-b-4 p-b-8\">\n <div class=\"input-group\">\n <span class=\"input-group-addon\">\n <i c8yIcon=\"globe\"></i>\n </span>\n <input\n type=\"text\"\n class=\"form-control\"\n formControlName=\"contentUrl\"\n placeholder=\"{{ 'e.g.' | translate }} http://example.com/binary.zip\"\n />\n </div>\n </div>\n </c8y-form-group>\n </div>\n </ng-container>\n </form>\n</fieldset>\n" }] }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i1.NgForm }, { type: i2.AlertService }, { type: MarkdownWidgetService }], propDecorators: { config: [{ type: Input }] } }); class MarkdownWidgetViewComponent { constructor(appState, client, markdownWidgetService) { this.appState = appState; this.client = client; this.markdownWidgetService = markdownWidgetService; this.headers = { 'Content-Type': 'text/markdown', responseType: 'blob' }; } async ngOnInit() { this.contextPath = this.appState.state.app.contextPath; if (this.config.markdownBinaryId) { const readmeContent = await (await this.markdownWidgetService.getFile(this.config.markdownBinaryId)).text(); this.markdown = readmeContent; } else if (this.config.contentUrl?.toLowerCase() === '/readme.md') { this.markdown = await this.getReadmeFileContent(); } else { this.setContentFromUrl(this.config.contentUrl); } } setContentFromUrl(url) { const req = new XMLHttpRequest(); req.onreadystatechange = () => this.render(req); req.addEventListener('load', () => this.render(req)); req.open('GET', url); req.responseType = 'text'; req.setRequestHeader('Accept', 'text/html'); req.send(); } async render(req) { if (req.readyState === 4 && req.status === 200) { this.markdown = req.response; } } async getReadmeFileContent() { const readmeFile = await this.getReadmeFile(); if (readmeFile.status === 200) { return await readmeFile.text(); } return ''; } async getReadmeFile() { const options = { method: 'GET', headers: this.headers }; const result = await this.client.fetch(`/apps/${this.contextPath}${this.config.contentUrl}`, options); return result; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MarkdownWidgetViewComponent, deps: [{ token: i2.AppStateService }, { token: i2$1.FetchClient }, { token: MarkdownWidgetService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: MarkdownWidgetViewComponent, isStandalone: true, selector: "c8y-markdown-widget-view", inputs: { config: "config" }, ngImport: i0, template: "<div id=\"helpContent\" class=\"p-16 p-t-0 markdown-content\" [innerHTML]=\"markdown | markdownToHtml | async\"></div>\n", dependencies: [{ kind: "pipe", type: MarkdownToHtmlPipe, name: "markdownToHtml" }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MarkdownWidgetViewComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-markdown-widget-view', standalone: true, imports: [MarkdownToHtmlPipe, AsyncPipe], template: "<div id=\"helpContent\" class=\"p-16 p-t-0 markdown-content\" [innerHTML]=\"markdown | markdownToHtml | async\"></div>\n" }] }], ctorParameters: () => [{ type: i2.AppStateService }, { type: i2$1.FetchClient }, { type: MarkdownWidgetService }], propDecorators: { config: [{ type: Input }] } }); /** * Generated bundle index. Do not edit. */ export { MarkdownWidgetConfigComponent, MarkdownWidgetService, MarkdownWidgetViewComponent }; //# sourceMappingURL=c8y-ngx-components-widgets-implementations-markdown.mjs.map