From 2bff35529e91dbcc43b44e44a5667f62dbf9967c Mon Sep 17 00:00:00 2001 From: Nicolas Molina <hi@nicobytes.com> Date: Tue, 22 Oct 2024 20:23:50 -0400 Subject: [PATCH] chore(edit-content): add docs #29875 --- .../utils/editor.ts | 29 ----- .../dot-form-file-editor.component.ts | 102 ++++++++++++++++++ .../store/form-file-editor.store.ts | 29 ++++- .../utils/editor.ts | 53 +++++++++ 4 files changed, 180 insertions(+), 33 deletions(-) delete mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-binary-field/utils/editor.ts create mode 100644 core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/utils/editor.ts diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-binary-field/utils/editor.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-binary-field/utils/editor.ts deleted file mode 100644 index 708fd1b66f51..000000000000 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-binary-field/utils/editor.ts +++ /dev/null @@ -1,29 +0,0 @@ -export function extractFileExtension(fileName: string): string { - const includesDot = fileName.includes('.'); - - if (!includesDot) { - return ''; - } - - return fileName.split('.').pop() || ''; -} - -export function getInfoByLang(extension: string) { - if (extension === 'vtl') { - return { - lang: 'html', - mimeType: 'text/x-velocity', - extension: '.vtl' - }; - } - - const language = monaco.languages - .getLanguages() - .find((language) => language.extensions?.includes(`.${extension}`)); - - return { - lang: language?.id || 'text', - mimeType: language?.mimetypes?.[0] || 'text/plain', - extension: language?.extensions?.[0] || '.txt' - }; -} diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-form-file-editor/dot-form-file-editor.component.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-form-file-editor/dot-form-file-editor.component.ts index 9aa91cdbc874..95809e99459d 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-form-file-editor/dot-form-file-editor.component.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-form-file-editor/dot-form-file-editor.component.ts @@ -51,16 +51,49 @@ type DialogProps = { providers: [FormFileEditorStore] }) export class DotFormFileEditorComponent implements OnInit { + /** + * Injects the FormFileEditorStore into the component. + * + * @readonly + * @type {FormFileEditorStore} + */ readonly store = inject(FormFileEditorStore); + /** + * A private and readonly instance of FormBuilder injected into the component. + * This instance is used to create and manage forms within the component. + */ readonly #formBuilder = inject(FormBuilder); + /** + * A reference to the dynamic dialog instance. + * This is a read-only property that is injected using the `DynamicDialogRef` token. + */ readonly #dialogRef = inject(DynamicDialogRef); + /** + * A read-only private property that holds the configuration for the dynamic dialog. + * This configuration is injected using the `DynamicDialogConfig` class with a generic type of `DialogProps`. + */ readonly #dialogConfig = inject(DynamicDialogConfig<DialogProps>); + /** + * Form group for the file editor component. + * + * This form contains the following controls: + * - `name`: A required string field that must match the pattern of a valid file name (e.g., "filename.extension"). + * - `content`: An optional string field for the file content. + * + * @readonly + */ readonly form = this.#formBuilder.nonNullable.group({ name: ['', [Validators.required, Validators.pattern(/^[^.]+\.[^.]+$/)]], content: [''] }); + /** + * Reference to the MonacoEditorComponent instance within the view. + * This is used to interact with the Monaco Editor component in the template. + * + * @type {MonacoEditorComponent} + */ $editorRef = viewChild.required(MonacoEditorComponent); constructor() { @@ -102,6 +135,23 @@ export class DotFormFileEditorComponent implements OnInit { }); } + /** + * Initializes the component by extracting data from the dialog configuration + * and setting up the form and store with the provided values. + * + * @returns {void} + * + * @memberof DotFormFileEditorComponent + * + * @method ngOnInit + * + * @description + * This method is called once the component is initialized. It retrieves the + * dialog configuration data and initializes the form with the uploaded file + * if available. It also sets up the store with the provided Monaco editor + * options, file name edit permission, uploaded file, accepted files, and + * upload type. + */ ngOnInit(): void { const data = this.#dialogConfig?.data as DialogProps; if (!data) { @@ -123,6 +173,15 @@ export class DotFormFileEditorComponent implements OnInit { }); } + /** + * Handles the form submission event. + * + * This method performs the following actions: + * 1. Checks if the form is invalid. If so, marks the form as dirty and updates its validity status. + * 2. If the form is valid, retrieves the raw values from the form and triggers the file upload process via the store. + * + * @returns {void} + */ onSubmit(): void { if (this.form.invalid) { this.form.markAsDirty(); @@ -135,26 +194,62 @@ export class DotFormFileEditorComponent implements OnInit { this.store.uploadFile(values); } + /** + * Getter for the 'name' field control from the form. + * + * @returns The form control associated with the 'name' field. + */ get nameField() { return this.form.controls.name; } + /** + * Getter for the 'content' form control. + * + * @returns The 'content' form control from the form group. + */ get contentField() { return this.form.controls.content; } + /** + * Disables the form and sets the editor to read-only mode. + * + * This method disables the form associated with the component and updates the editor's options + * to make it read-only. It is useful for preventing further user interaction with the form and editor. + * + * @private + */ #disableEditor() { this.form.disable(); const editor = this.$editorRef().editor; editor.updateOptions({ readOnly: true }); } + /** + * Enables the form and sets the editor to be editable. + * + * This method performs the following actions: + * 1. Enables the form associated with this component. + * 2. Retrieves the editor instance from the `$editorRef` method. + * 3. Updates the editor options to make it writable (readOnly: false). + */ #enableEditor() { this.form.enable(); const editor = this.$editorRef().editor; editor.updateOptions({ readOnly: false }); } + /** + * Initializes the form values with the provided uploaded file data. + * + * @param {UploadedFile} param0 - The uploaded file object containing source and file information. + * @param {string} param0.source - The source of the file, which can be 'temp' or another value. + * @param {File} param0.file - The file object containing file details. + * @param {string} param0.file.fileName - The name of the file if the source is 'temp'. + * @param {string} param0.file.title - The title of the file if the source is not 'temp'. + * @param {string} param0.file.content - The content of the file. + */ #initValuesForm({ source, file }: UploadedFile): void { this.form.patchValue({ name: source === 'temp' ? file.fileName : file.title, @@ -162,6 +257,13 @@ export class DotFormFileEditorComponent implements OnInit { }); } + /** + * Cancels the current file upload and closes the dialog. + * + * @remarks + * This method is used to terminate the ongoing file upload process and + * close the associated dialog reference. + */ cancelUpload(): void { this.#dialogRef.close(); } diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-form-file-editor/store/form-file-editor.store.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-form-file-editor/store/form-file-editor.store.ts index 6ad8952732b9..22dacea3f112 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-form-file-editor/store/form-file-editor.store.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-form-file-editor/store/form-file-editor.store.ts @@ -10,12 +10,9 @@ import { switchMap, tap } from 'rxjs/operators'; import { ComponentStatus, DotHttpErrorResponse } from '@dotcms/dotcms-models'; -import { - extractFileExtension, - getInfoByLang -} from '../../../../dot-edit-content-binary-field/utils/editor'; import { UPLOAD_TYPE, UploadedFile } from '../../../models'; import { DotFileFieldUploadService } from '../../../services/upload-file/upload-file.service'; +import { extractFileExtension, getInfoByLang } from '../../../utils/editor'; import { DEFAULT_MONACO_CONFIG } from '../dot-form-file-editor.conts'; type FileInfo = { @@ -74,6 +71,16 @@ export const FormFileEditorStore = signalStore( const uploadService = inject(DotFileFieldUploadService); return { + /** + * Sets the file name and updates the file's metadata in the store. + * + * @param name - The new name of the file. + * + * This method performs the following actions: + * 1. Extracts the file extension from the provided name. + * 2. Retrieves file information based on the extracted extension. + * 3. Updates the store with the new file name and its associated metadata, including MIME type, extension, and language. + */ setFileName(name: string) { const file = store.file(); @@ -90,6 +97,16 @@ export const FormFileEditorStore = signalStore( } }); }, + /** + * Initializes the file editor state with the provided options. + * + * @param params - The parameters for initializing the file editor. + * @param params.monacoOptions - Partial options for configuring the Monaco editor. + * @param params.allowFileNameEdit - Flag indicating if the file name can be edited. + * @param params.uploadedFile - The uploaded file information, or null if no file is uploaded. + * @param params.acceptedFiles - Array of accepted file types. + * @param params.uploadType - The type of upload being performed. + */ initLoad({ monacoOptions, allowFileNameEdit, @@ -133,6 +150,10 @@ export const FormFileEditorStore = signalStore( patchState(store, state); }, + /** + * Uploads the file content to the server. + * + */ uploadFile: rxMethod<{ name: string; content: string; diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/utils/editor.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/utils/editor.ts new file mode 100644 index 000000000000..b1e189198080 --- /dev/null +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/utils/editor.ts @@ -0,0 +1,53 @@ +/** + * Extracts the file extension from a given file name. + * + * @param fileName - The name of the file from which to extract the extension. + * @returns The file extension if present, otherwise an empty string. + */ +export function extractFileExtension(fileName: string): string { + const includesDot = fileName.includes('.'); + + if (!includesDot) { + return ''; + } + + return fileName.split('.').pop() || ''; +} + +/** + * Retrieves language information based on the provided file extension. + * + * @param extension - The file extension to get the language information for. + * @returns An object containing the language id, MIME type, and extension. + * + * @example + * ```typescript + * const info = getInfoByLang('vtl'); + * console.log(info); + * // Output: { lang: 'html', mimeType: 'text/x-velocity', extension: '.vtl' } + * ``` + * + * @remarks + * If the extension is 'vtl', it returns a predefined set of values. + * Otherwise, it searches through the Monaco Editor languages to find a match. + * If no match is found, it defaults to 'text' for the language id, 'text/plain' for the MIME type, and '.txt' for the extension. + */ +export function getInfoByLang(extension: string) { + if (extension === 'vtl') { + return { + lang: 'html', + mimeType: 'text/x-velocity', + extension: '.vtl' + }; + } + + const language = monaco.languages + .getLanguages() + .find((language) => language.extensions?.includes(`.${extension}`)); + + return { + lang: language?.id || 'text', + mimeType: language?.mimetypes?.[0] || 'text/plain', + extension: language?.extensions?.[0] || '.txt' + }; +}