UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

1 lines • 32 kB
{"version":3,"file":"c8y-ngx-components-widgets-implementations-markdown.mjs","sources":["../../widgets/implementations/markdown/markdown-widget.model.ts","../../widgets/implementations/markdown/markdown-widget.service.ts","../../widgets/implementations/markdown/markdown-widget-config/markdown-widget-config.component.ts","../../widgets/implementations/markdown/markdown-widget-config/markdown-widget-config.component.html","../../widgets/implementations/markdown/markdown-widget-view/markdown-widget-view.component.ts","../../widgets/implementations/markdown/markdown-widget-view/markdown-widget-view.component.html","../../widgets/implementations/markdown/c8y-ngx-components-widgets-implementations-markdown.ts"],"sourcesContent":["import { FormControl, FormGroup } from '@angular/forms';\n\nexport interface MarkdownWidgetConfig {\n markdownBinaryId: string | null;\n contentUrl: string | null;\n markdownContent: string | null;\n}\n\nexport const MarkdownSourceType = {\n WRITE: 'writeMarkdown',\n UPLOAD: 'uploadBinary',\n URL: 'uploadUrl'\n} as const;\n\nexport type MarkdownSourceType = (typeof MarkdownSourceType)[keyof typeof MarkdownSourceType];\n\nexport interface DroppedFileItem {\n file: File;\n name: string;\n}\n\nexport type MarkdownWidgetFormGroup = FormGroup<{\n contentUrl: FormControl<string>;\n droppedFile: FormControl<DroppedFileItem[] | null>;\n uploadChoice: FormControl<MarkdownSourceType>;\n}>;\n","import { Injectable } from '@angular/core';\nimport {\n FetchClient,\n IFetchOptions,\n IManagedObjectBinary,\n InventoryBinaryService,\n InventoryService\n} from '@c8y/client';\nimport { AlertService, AppStateService, FilesService } from '@c8y/ngx-components';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport { TranslateService } from '@ngx-translate/core';\n\n@Injectable({ providedIn: 'root' })\nexport class MarkdownWidgetService {\n private readonly headers = { 'Content-Type': 'text/markdown' };\n\n constructor(\n private fileService: FilesService,\n private inventory: InventoryService,\n private binary: InventoryBinaryService,\n private alert: AlertService,\n private translate: TranslateService,\n private fetchClient: FetchClient,\n private appStateService: AppStateService\n ) {}\n\n /**\n * Retrieves a markdown file from the inventory by its binary ID.\n * @param markdownBinaryId - The ID of the binary managed object.\n * @returns The file if found, otherwise null.\n */\n async getFile(markdownBinaryId: string | null): Promise<File> {\n if (!markdownBinaryId) {\n return null;\n }\n\n try {\n const { data: markdownBinaryMo } = await this.inventory.detail(markdownBinaryId);\n const file = await this.fileService.getFile(markdownBinaryMo as IManagedObjectBinary);\n return file;\n } catch (e) {\n const text = this.translate.instant(\n gettext('Unable to retrieve binary with ID: {{ markdownBinaryId }}'),\n { markdownBinaryId }\n );\n this.alert.danger(text, e?.data);\n }\n\n return null;\n }\n\n /**\n * Uploads a markdown file to the inventory as a binary.\n * @param file - The file to upload.\n * @returns The ID of the created binary managed object.\n */\n async uploadFile(file: File): Promise<string> {\n const { data: mo } = await this.binary.create(file);\n return mo.id;\n }\n\n /**\n * Fetches markdown content from a URL.\n * For internal URLs (e.g., `/readme.md`), uses FetchClient with the app's context path.\n * For external URLs, uses XMLHttpRequest to avoid CORS issues with auth headers.\n * @param url - The URL to fetch content from.\n * @returns The markdown content as a string, or empty string on error.\n */\n async getContentFromUrl(url: string): Promise<string> {\n if (url?.toLowerCase() === '/readme.md') {\n return this.getContentFromInternalUrl(url);\n }\n return this.getContentFromExternalUrl(url);\n }\n\n private async getContentFromInternalUrl(url: string): Promise<string> {\n try {\n const contextPath = this.appStateService.state.app.contextPath;\n const options: IFetchOptions = {\n method: 'GET',\n headers: this.headers\n };\n const response = await this.fetchClient.fetch(`/apps/${contextPath}${url}`, options);\n if (response.status === 200) {\n return response.text();\n }\n } catch {\n // ignore error, return empty string\n }\n return '';\n }\n\n private getContentFromExternalUrl(url: string): Promise<string> {\n return new Promise(resolve => {\n const req = new XMLHttpRequest();\n req.onreadystatechange = () => {\n if (req.readyState === 4) {\n if (req.status === 200) {\n resolve(req.response);\n } else {\n resolve('');\n }\n }\n };\n req.onerror = () => resolve('');\n req.open('GET', url);\n req.responseType = 'text';\n req.setRequestHeader('Accept', 'text/html');\n req.send();\n });\n }\n}\n","import { Component, inject, Input, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';\nimport { gettext } from '@c8y/ngx-components/gettext';\nimport {\n AlertService,\n C8yTranslatePipe,\n C8yValidators,\n DropAreaComponent,\n EmptyStateComponent,\n FormGroupComponent,\n IconDirective,\n MarkdownToHtmlPipe,\n OnBeforeSave\n} from '@c8y/ngx-components';\nimport {\n AbstractControl,\n FormBuilder,\n FormsModule,\n NgForm,\n ReactiveFormsModule,\n ValidationErrors,\n ValidatorFn,\n Validators\n} from '@angular/forms';\nimport {\n DroppedFileItem,\n MarkdownSourceType,\n MarkdownWidgetConfig,\n MarkdownWidgetFormGroup\n} from '../markdown-widget.model';\nimport { MarkdownWidgetService } from '../markdown-widget.service';\nimport { WidgetConfigService } from '@c8y/ngx-components/context-dashboard';\nimport { AsyncPipe } from '@angular/common';\nimport { BehaviorSubject, Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { EditorComponent } from '@c8y/ngx-components/editor';\n\n@Component({\n selector: 'c8y-markdown-widget-config',\n templateUrl: './markdown-widget-config.component.html',\n standalone: true,\n imports: [\n ReactiveFormsModule,\n FormsModule,\n AsyncPipe,\n C8yTranslatePipe,\n MarkdownToHtmlPipe,\n FormGroupComponent,\n DropAreaComponent,\n EmptyStateComponent,\n IconDirective,\n EditorComponent\n ]\n})\nexport class MarkdownWidgetConfigComponent implements OnInit, OnDestroy, OnBeforeSave {\n @Input() config: MarkdownWidgetConfig;\n @ViewChild('markdownPreview')\n set markdownPreviewTemplate(template: TemplateRef<any>) {\n this.widgetConfigService.setPreview(template || null);\n }\n\n readonly MarkdownSourceType = MarkdownSourceType;\n\n formGroup: MarkdownWidgetFormGroup;\n fileFromConfig: File;\n uploadChoice: MarkdownSourceType = MarkdownSourceType.URL;\n previewMarkdown$ = new BehaviorSubject<string>('');\n editorContent = '';\n\n private widgetConfigService = inject(WidgetConfigService);\n private destroy$ = new Subject<void>();\n\n constructor(\n private formBuilder: FormBuilder,\n private form: NgForm,\n private alert: AlertService,\n private markdownService: MarkdownWidgetService\n ) {}\n\n async onBeforeSave(config?: MarkdownWidgetConfig): Promise<boolean> {\n if (this.uploadChoice === MarkdownSourceType.WRITE) {\n Object.assign(config, {\n markdownContent: this.editorContent,\n contentUrl: null,\n markdownBinaryId: null\n });\n return true;\n }\n\n if (this.formGroup.invalid) {\n return false;\n }\n\n if (this.uploadChoice === MarkdownSourceType.URL) {\n Object.assign(config, {\n contentUrl: this.formGroup.value.contentUrl,\n markdownBinaryId: null,\n markdownContent: null\n });\n return true;\n }\n\n const fileFromForm = this.getFileFromFormValue(this.formGroup.value);\n if (fileFromForm && fileFromForm !== this.fileFromConfig) {\n try {\n const markdownBinaryId = await this.markdownService.uploadFile(fileFromForm);\n Object.assign(config, { markdownBinaryId, contentUrl: null, markdownContent: null });\n return true;\n } catch (e) {\n this.alert.danger(gettext('Unable to upload Markdown file.'), e?.data);\n return false;\n }\n }\n if (!fileFromForm) {\n Object.assign(config, {\n contentUrl: '/readme.md',\n markdownBinaryId: null,\n markdownContent: null\n });\n }\n return true;\n }\n\n async ngOnInit() {\n // Determine initial mode from config\n if (this.config.markdownContent) {\n this.uploadChoice = MarkdownSourceType.WRITE;\n } else if (this.config.markdownBinaryId) {\n this.uploadChoice = MarkdownSourceType.UPLOAD;\n }\n\n this.initForm();\n\n // Load initial content based on mode\n switch (this.uploadChoice) {\n case MarkdownSourceType.WRITE:\n this.editorContent = this.config.markdownContent;\n this.previewMarkdown$.next(this.config.markdownContent);\n break;\n case MarkdownSourceType.UPLOAD:\n this.fileFromConfig = await this.markdownService.getFile(this.config.markdownBinaryId);\n this.formGroup.patchValue({\n droppedFile: [{ file: this.fileFromConfig, name: this.fileFromConfig.name }]\n });\n await this.updatePreviewFromFile(this.fileFromConfig);\n break;\n case MarkdownSourceType.URL:\n if (this.config.contentUrl) {\n this.previewMarkdown$.next(\n await this.markdownService.getContentFromUrl(this.config.contentUrl)\n );\n }\n break;\n }\n\n this.formGroup.valueChanges.pipe(takeUntil(this.destroy$)).subscribe(async value => {\n await this.updatePreview(value);\n });\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n onChange(value: MarkdownSourceType) {\n this.uploadChoice = value;\n\n // Ensure dropped file has 'name' property for drop area to display filename\n const droppedFile = this.formGroup.value.droppedFile;\n if (value === MarkdownSourceType.UPLOAD && droppedFile?.[0]?.file) {\n const normalizedFile = droppedFile.map(item => ({\n ...item,\n name: item.name || item.file?.name\n }));\n this.formGroup.controls['droppedFile'].setValue(normalizedFile);\n }\n\n this.formGroup.updateValueAndValidity();\n }\n\n onEditorChange(content: string) {\n this.editorContent = content;\n this.previewMarkdown$.next(content);\n }\n\n private async updatePreview(formValue: Partial<MarkdownWidgetFormGroup['value']>): Promise<void> {\n const choice = formValue.uploadChoice || this.uploadChoice;\n switch (choice) {\n case MarkdownSourceType.WRITE:\n if (!this.editorContent) {\n this.editorContent = this.previewMarkdown$.getValue();\n }\n this.previewMarkdown$.next(this.editorContent);\n break;\n case MarkdownSourceType.UPLOAD:\n const file = this.getFileFromFormValue(formValue);\n file ? await this.updatePreviewFromFile(file) : this.previewMarkdown$.next('');\n break;\n case MarkdownSourceType.URL:\n if (formValue.contentUrl) {\n this.previewMarkdown$.next(\n await this.markdownService.getContentFromUrl(formValue.contentUrl)\n );\n } else {\n this.previewMarkdown$.next('');\n }\n break;\n }\n }\n\n private async updatePreviewFromFile(file: File): Promise<void> {\n try {\n this.previewMarkdown$.next(await file.text());\n } catch {\n this.previewMarkdown$.next('');\n }\n }\n\n private getFileFromFormValue(formValue: Partial<MarkdownWidgetFormGroup['value']>): File | null {\n const binary = formValue?.droppedFile || [];\n return binary[0]?.file || null;\n }\n\n private initForm(): void {\n this.formGroup = this.formBuilder.group(\n {\n contentUrl: this.formBuilder.nonNullable.control('', [Validators.maxLength(2000)]),\n droppedFile: this.formBuilder.control<DroppedFileItem[] | null>(null, [\n Validators.minLength(1),\n Validators.maxLength(1),\n C8yValidators.filesValidator({ maximumFileSizeInKb: 1000 })\n ]),\n uploadChoice: this.formBuilder.nonNullable.control<MarkdownSourceType>(this.uploadChoice)\n },\n { validators: this.requireValidSource() }\n ) as MarkdownWidgetFormGroup;\n this.form.form.addControl('config', this.formGroup);\n this.formGroup.patchValue(this.config);\n }\n\n private requireValidSource(): ValidatorFn {\n return (control: AbstractControl): ValidationErrors | null => {\n const url = control.get('contentUrl');\n const droppedFile = control.get('droppedFile');\n\n // Write mode - always valid, editor content handled separately\n if (this.uploadChoice === MarkdownSourceType.WRITE) {\n url.setErrors(null);\n droppedFile.setErrors(null);\n return null;\n }\n\n // Clear required errors on inactive controls, set on active if empty\n if (this.uploadChoice === MarkdownSourceType.URL) {\n this.clearRequiredError(droppedFile);\n if (!url.value) {\n url.setErrors({ ...url.errors, required: true });\n return { required: true };\n }\n this.clearRequiredError(url);\n }\n\n if (this.uploadChoice === MarkdownSourceType.UPLOAD) {\n this.clearRequiredError(url);\n if (!droppedFile.value) {\n droppedFile.setErrors({ ...droppedFile.errors, required: true });\n return { required: true };\n }\n this.clearRequiredError(droppedFile);\n }\n\n return null;\n };\n }\n\n private clearRequiredError(control: AbstractControl): void {\n if (control?.errors?.required) {\n const { required: _, ...rest } = control.errors;\n control.setErrors(Object.keys(rest).length ? rest : null);\n }\n }\n}\n","<fieldset class=\"c8y-fieldset\">\n <legend>{{ 'Source' | translate }}</legend>\n <form [formGroup]=\"formGroup\">\n <div class=\"form-group\">\n <label\n class=\"c8y-radio radio-inline\"\n title=\"{{ 'Write Markdown' | translate }}\"\n >\n <input\n name=\"uploadChoice\"\n type=\"radio\"\n [value]=\"MarkdownSourceType.WRITE\"\n formControlName=\"uploadChoice\"\n (change)=\"onChange(MarkdownSourceType.WRITE)\"\n />\n <span></span>\n <span>{{ 'Write Markdown' | translate }}</span>\n </label>\n <label\n class=\"c8y-radio radio-inline m-l-8\"\n title=\"{{ 'Upload a binary' | translate }}\"\n >\n <input\n name=\"uploadChoice\"\n type=\"radio\"\n [value]=\"MarkdownSourceType.UPLOAD\"\n formControlName=\"uploadChoice\"\n (change)=\"onChange(MarkdownSourceType.UPLOAD)\"\n />\n <span></span>\n <span>{{ 'Upload a binary' | translate }}</span>\n </label>\n <label\n class=\"c8y-radio radio-inline m-l-8\"\n title=\"{{ 'Provide a file path' | translate }}\"\n >\n <input\n name=\"uploadChoice\"\n type=\"radio\"\n [value]=\"MarkdownSourceType.URL\"\n formControlName=\"uploadChoice\"\n (change)=\"onChange(MarkdownSourceType.URL)\"\n />\n <span></span>\n <span>{{ 'Provide a file path' | translate }}</span>\n </label>\n </div>\n @switch (uploadChoice) {\n @case (MarkdownSourceType.WRITE) {\n <c8y-editor\n class=\"d-block\"\n style=\"height: 300px\"\n [ngModel]=\"editorContent\"\n (ngModelChange)=\"onEditorChange($event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [editorOptions]=\"{\n language: 'markdown',\n tabSize: 2,\n insertSpaces: true,\n minimap: { enabled: false },\n wordWrap: 'on'\n }\"\n ></c8y-editor>\n }\n @case (MarkdownSourceType.UPLOAD) {\n <c8y-form-group class=\"m-b-24\">\n <c8y-drop-area\n class=\"drop-area-sm\"\n [title]=\"'Drop file or click to browse' | translate\"\n formControlName=\"droppedFile\"\n [maxAllowedFiles]=\"1\"\n [accept]=\"'md'\"\n ></c8y-drop-area>\n </c8y-form-group>\n }\n @case (MarkdownSourceType.URL) {\n <c8y-form-group class=\"m-b-24\">\n <div class=\"input-group\">\n <span class=\"input-group-addon\">\n <i c8yIcon=\"globe\"></i>\n </span>\n <input\n class=\"form-control\"\n placeholder=\"{{ 'e.g.' | translate }} http://example.com/binary.zip\"\n type=\"text\"\n formControlName=\"contentUrl\"\n />\n </div>\n </c8y-form-group>\n }\n }\n </form>\n</fieldset>\n\n<ng-template #markdownPreview>\n @if (previewMarkdown$ | async; as previewMarkdown) {\n <div\n class=\"p-16 p-t-0 markdown-content fit-h overflow-auto\"\n [innerHTML]=\"previewMarkdown | markdownToHtml | async\"\n ></div>\n } @else {\n <div class=\"fit-h d-flex d-col j-c-center a-i-center\">\n <c8y-ui-empty-state\n [icon]=\"'file-text'\"\n [title]=\"'No content to preview' | translate\"\n [subtitle]=\"\n 'Write Markdown, upload a file, or provide a URL to see the preview' | translate\n \"\n [horizontal]=\"false\"\n ></c8y-ui-empty-state>\n </div>\n }\n</ng-template>\n","import { Component, Input, OnInit } from '@angular/core';\nimport { MarkdownToHtmlPipe } from '@c8y/ngx-components';\nimport { MarkdownWidgetConfig } from '../markdown-widget.model';\nimport { MarkdownWidgetService } from '../markdown-widget.service';\nimport { AsyncPipe } from '@angular/common';\n\n@Component({\n selector: 'c8y-markdown-widget-view',\n templateUrl: './markdown-widget-view.component.html',\n standalone: true,\n imports: [MarkdownToHtmlPipe, AsyncPipe]\n})\nexport class MarkdownWidgetViewComponent implements OnInit {\n @Input() config: MarkdownWidgetConfig;\n markdown: string;\n\n constructor(private markdownWidgetService: MarkdownWidgetService) {}\n\n async ngOnInit() {\n if (this.config.markdownContent) {\n this.markdown = this.config.markdownContent;\n } else if (this.config.markdownBinaryId) {\n const file = await this.markdownWidgetService.getFile(this.config.markdownBinaryId);\n this.markdown = await file?.text();\n } else if (this.config.contentUrl) {\n this.markdown = await this.markdownWidgetService.getContentFromUrl(this.config.contentUrl);\n }\n }\n}\n","<div id=\"helpContent\" class=\"p-16 p-t-0 markdown-content\" [innerHTML]=\"markdown | markdownToHtml | async\"></div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2","i3.MarkdownWidgetService","i1.MarkdownWidgetService"],"mappings":"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"}