Skip to content

Commit

Permalink
chore(edit-content): add docs #29875
Browse files Browse the repository at this point in the history
  • Loading branch information
nicobytes committed Oct 23, 2024
1 parent 5fe8784 commit 2bff355
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 33 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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) {
Expand All @@ -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();
Expand All @@ -135,33 +194,76 @@ 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,
content: file.content
});
}

/**
* 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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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();

Expand All @@ -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,
Expand Down Expand Up @@ -133,6 +150,10 @@ export const FormFileEditorStore = signalStore(

patchState(store, state);
},
/**
* Uploads the file content to the server.
*
*/
uploadFile: rxMethod<{
name: string;
content: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -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'
};
}

0 comments on commit 2bff355

Please sign in to comment.