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'
+    };
+}