From 15724e52ff2864cba1559cea2f2074ea96a4f885 Mon Sep 17 00:00:00 2001 From: Nicolas Molina Date: Wed, 25 Sep 2024 12:57:00 -0400 Subject: [PATCH] feat(editor-content): enable links #29872 --- .../dot-file-field-preview.component.html | 29 +++ .../dot-file-field-preview.component.scss | 16 +- .../dot-file-field-preview.component.ts | 93 +++++++- .../dot-file-field-ui-message.component.scss | 1 + ...dot-edit-content-file-field.component.html | 2 +- .../dot-edit-content-file-field.component.ts | 18 +- .../dot-edit-content-file-field.const.ts | 6 +- .../models/index.ts | 5 + .../store/file-field.store.ts | 204 +++++++++++------- .../utils/index.ts | 2 - 10 files changed, 282 insertions(+), 94 deletions(-) diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field-preview/dot-file-field-preview.component.html b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field-preview/dot-file-field-preview.component.html index 53ca070f3268..d3b04b77a7a3 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field-preview/dot-file-field-preview.component.html +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field-preview/dot-file-field-preview.component.html @@ -1,5 +1,6 @@ @let previewFile = $previewFile(); @let metadata = $metadata(); +@let downloadLink = $downloadLink();
@@ -34,12 +35,21 @@ } }
+ +
+ @for (sourceLink of $resourceLinks(); track $index) { +
+ {{ sourceLink.key | dm }}: + +
+ } ({ alias: 'previewFile' }); removeFile = output(); $showDialog = signal(false); @@ -46,7 +57,79 @@ export class DotFileFieldPreviewComponent { return getFileMetadata(previewFile.file); }); + $downloadLink = computed(() => { + const previewFile = this.$previewFile(); + if (previewFile.source === 'contentlet') { + const file = previewFile.file; + + return `/contentAsset/raw-data/${file.inode}/asset?byInode=true&force_download=true`; + } + + return null; + }); + + $resourceLinks = signal([]); + + ngOnInit() { + const previewFile = this.$previewFile(); + + if (previewFile.source === 'contentlet') { + this.fetchResourceLinks(previewFile.file); + } + } + toggleShowDialog() { this.$showDialog.set(!this.$showDialog()); } + + downloadAsset(link: string): void { + window.open(link, '_self'); + } + + private fetchResourceLinks(contentlet: DotCMSContentlet): void { + this.#dotResourceLinksService + .getFileResourceLinks({ + fieldVariable: 'asset', + inodeOrIdentifier: contentlet.identifier + }) + .pipe( + catchError(() => { + return of({ + configuredImageURL: '', + text: '', + versionPath: '', + idPath: '' + }); + }) + ) + .subscribe(({ configuredImageURL, text, versionPath, idPath }) => { + const fileLink = configuredImageURL + ? `${window.location.origin}${configuredImageURL}` + : ''; + + const options = [ + { + key: 'FileLink', + value: fileLink, + }, + { + key: 'VersionPath', + value: versionPath, + }, + { + key: 'IdPath', + value: idPath, + } + ]; + + if (contentlet.baseType === DotCMSBaseTypesContentTypes.FILEASSET) { + options.push({ + key: 'Resource-Link', + value: text, + }); + } + + this.$resourceLinks.set(options); + }); + } } diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field-ui-message/dot-file-field-ui-message.component.scss b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field-ui-message/dot-file-field-ui-message.component.scss index fccd0d7f5e15..fbd0b6ef596d 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field-ui-message/dot-file-field-ui-message.component.scss +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/components/dot-file-field-ui-message/dot-file-field-ui-message.component.scss @@ -33,4 +33,5 @@ .text { text-align: center; line-height: 140%; + font-size: $font-size-default; } diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/dot-edit-content-file-field.component.html b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/dot-edit-content-file-field.component.html index 8de4c3bce53e..d8de8e40c5bc 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/dot-edit-content-file-field.component.html +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/dot-edit-content-file-field.component.html @@ -10,7 +10,7 @@ void) { this.onChange = fn; @@ -111,6 +111,16 @@ export class DotEditContentFileFieldComponent implements ControlValueAccessor, O this.store.handleUploadFile(file); } + fileSelected(files: FileList) { + const file = files[0]; + + if (!file) { + return; + } + + this.store.handleUploadFile(file); + } + private handleFileDropError({ errorsType }: DropZoneFileValidity): void { const errorType = errorsType[0]; const uiMessage = getUiMessage(errorType); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/dot-edit-content-file-field.const.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/dot-edit-content-file-field.const.ts index 0f9c5f932871..796aa5997f6f 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/dot-edit-content-file-field.const.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/dot-edit-content-file-field.const.ts @@ -18,7 +18,7 @@ export const INPUT_CONFIG: ConfigActions = { allowCreateFile: true, allowGenerateImg: false, acceptedFiles: [], - maxFileSize: 1024 + maxFileSize: null }, Image: { allowExistingFile: true, @@ -26,7 +26,7 @@ export const INPUT_CONFIG: ConfigActions = { allowCreateFile: false, allowGenerateImg: true, acceptedFiles: ['image/*'], - maxFileSize: 0 + maxFileSize: null }, Binary: { allowExistingFile: false, @@ -34,6 +34,6 @@ export const INPUT_CONFIG: ConfigActions = { allowCreateFile: true, allowGenerateImg: true, acceptedFiles: [], - maxFileSize: 0 + maxFileSize: null } }; diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/models/index.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/models/index.ts index fd20a59884d7..23ca92371b74 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/models/index.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/models/index.ts @@ -29,3 +29,8 @@ export type PreviewFile = source: 'contentlet'; file: DotCMSContentlet; }; + + export interface DotPreviewResourceLink { + key: string; + value: string; + } \ No newline at end of file diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/store/file-field.store.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/store/file-field.store.ts index fcfcd74a870f..da9afd1535be 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/store/file-field.store.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/store/file-field.store.ts @@ -5,11 +5,12 @@ import { pipe } from 'rxjs'; import { computed, inject } from '@angular/core'; -import { switchMap, tap } from 'rxjs/operators'; +import { filter, switchMap, tap } from 'rxjs/operators'; import { DotUploadFileService } from '@dotcms/data-access'; import { DotCMSContentlet, DotCMSTempFile } from '@dotcms/dotcms-models'; +import { DotEditContentService } from '../../../services/dot-edit-content.service'; import { INPUT_CONFIG } from '../dot-edit-content-file-field.const'; import { INPUT_TYPES, FILE_STATUS, UIMessage, PreviewFile } from '../models'; import { getUiMessage } from '../utils/messages'; @@ -29,7 +30,7 @@ export interface FileFieldState { allowCreateFile: boolean; uiMessage: UIMessage; acceptedFiles: string[]; - maxFileSize: number; + maxFileSize: number | null; fieldVariable: string; previewFile: PreviewFile | null; } @@ -49,7 +50,7 @@ const initialState: FileFieldState = { allowCreateFile: false, uiMessage: getUiMessage('DEFAULT'), acceptedFiles: [], - maxFileSize: 0, + maxFileSize: null, fieldVariable: '', previewFile: null }; @@ -68,84 +69,131 @@ export const FileFieldStore = signalStore( return currentStatus === 'uploading'; }) })), - withMethods((store, fileService = inject(DotUploadFileService)) => ({ - initLoad: (initState: { - inputType: FileFieldState['inputType']; - fieldVariable: FileFieldState['fieldVariable']; - }) => { - const { inputType, fieldVariable } = initState; + withMethods( + ( + store, + fileService = inject(DotUploadFileService), + contentService = inject(DotEditContentService) + ) => ({ + initLoad: (initState: { + inputType: FileFieldState['inputType']; + fieldVariable: FileFieldState['fieldVariable']; + }) => { + const { inputType, fieldVariable } = initState; - const actions = INPUT_CONFIG[inputType] || {}; + const actions = INPUT_CONFIG[inputType] || {}; - patchState(store, { - inputType, - fieldVariable, - ...actions - }); - }, - setValue: (value: string) => { - patchState(store, { value }); - }, - setUIMessage: (uiMessage: UIMessage) => { - const acceptedFiles = store.acceptedFiles(); - const maxFileSize = store.maxFileSize(); + patchState(store, { + inputType, + fieldVariable, + ...actions + }); + }, + setUIMessage: (uiMessage: UIMessage) => { + const acceptedFiles = store.acceptedFiles(); + const maxFileSize = store.maxFileSize(); - patchState(store, { - uiMessage: { - ...uiMessage, - args: [acceptedFiles.join(', '), `${maxFileSize}`] - } - }); - }, - removeFile: () => { - patchState(store, { - contentlet: null, - tempFile: null, - value: '', - fileStatus: 'init' - }); - }, - setDropZoneState: (state: boolean) => { - patchState(store, { - dropZoneActive: state - }); - }, - setUploading: () => { - patchState(store, { - dropZoneActive: false, - fileStatus: 'uploading' - }); - }, - handleUploadFile: rxMethod( - pipe( - tap(() => - patchState(store, { - dropZoneActive: false, - fileStatus: 'uploading' + patchState(store, { + uiMessage: { + ...uiMessage, + args: [`${maxFileSize}`, acceptedFiles.join(', ')] + } + }); + }, + removeFile: () => { + patchState(store, { + contentlet: null, + tempFile: null, + value: '', + fileStatus: 'init', + uiMessage: getUiMessage('DEFAULT') + }); + }, + setDropZoneState: (state: boolean) => { + patchState(store, { + dropZoneActive: state + }); + }, + setUploading: () => { + patchState(store, { + dropZoneActive: false, + fileStatus: 'uploading' + }); + }, + handleUploadFile: rxMethod( + pipe( + tap(() => { + patchState(store, { + dropZoneActive: false, + fileStatus: 'uploading' + }); + }), + filter((file) => { + const maxFileSize = store.maxFileSize(); + + if (maxFileSize && file.size > maxFileSize) { + patchState(store, { + fileStatus: 'init', + dropZoneActive: true, + uiMessage: { + ...getUiMessage('MAX_FILE_SIZE_EXCEEDED'), + args: [`${maxFileSize}`] + } + }); + + return false; + } + + return true; + }), + switchMap((file) => { + return fileService.uploadDotAsset(file).pipe( + tapResponse({ + next: (file) => { + patchState(store, { + tempFile: null, + contentlet: file, + fileStatus: 'preview', + value: file.identifier, + previewFile: { source: 'contentlet', file } + }); + }, + error: () => { + patchState(store, { + fileStatus: 'init', + uiMessage: getUiMessage('SERVER_ERROR') + }); + } + }) + ); }) - ), - switchMap((file) => { - return fileService.uploadDotAsset(file).pipe( - tapResponse({ - next: (file) => { - patchState(store, { - tempFile: null, - contentlet: file, - fileStatus: 'preview', - value: file.identifier, - previewFile: { source: 'contentlet', file: file } - }); - }, - error: () => { - patchState(store, { - fileStatus: 'init', - uiMessage: getUiMessage('SERVER_ERROR') - }); - } - }) - ); - }) + ) + ), + getAssetData: rxMethod( + pipe( + switchMap((identifier) => { + return contentService.getContentById(identifier).pipe( + tapResponse({ + next: (file) => { + patchState(store, { + tempFile: null, + contentlet: file, + fileStatus: 'preview', + value: file.identifier, + previewFile: { source: 'contentlet', file } + }); + }, + error: () => { + patchState(store, { + fileStatus: 'init', + uiMessage: getUiMessage('SERVER_ERROR') + }); + } + }) + ); + }) + ) ) - ) - })) + }) + ) ); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/utils/index.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/utils/index.ts index cfb667ae0067..8460e5c042c1 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/utils/index.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-file-field/utils/index.ts @@ -1,8 +1,6 @@ import { DotCMSContentlet, DotFileMetadata } from '@dotcms/dotcms-models'; export const getFileMetadata = (contentlet: DotCMSContentlet): DotFileMetadata => { - console.log('contentlet', contentlet); - const { metaData } = contentlet; const metadata = metaData || contentlet[`assetMetaData`];