Skip to content

Commit

Permalink
feat(editor-content): working on preview for text files #29872
Browse files Browse the repository at this point in the history
  • Loading branch information
nicobytes committed Sep 25, 2024
1 parent 15724e5 commit bd896c4
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,46 @@
@let metadata = $metadata();
@let downloadLink = $downloadLink();

<div class="preview-container">
<div class="preview-image__container">
@if (previewFile.source === 'temp') {
<dot-temp-file-thumbnail
[tempFile]="previewFile.file"
[iconSize]="'48px'"
data-testId="temp-file-thumbnail" />
} @else {
<dot-contentlet-thumbnail
fieldVariable="asset"
[iconSize]="'48px'"
[contentlet]="previewFile.file"
[playableVideo]="true"
data-testId="contentlet-thumbnail" />
}
</div>
<div class="preview-metadata__container">
@if (metadata) {
<span class="preview-metadata_header">{{ metadata.title }}</span>
@if (metadata.width && metadata.height) {
<div class="preview-metadata__info">
<i class="pi pi-arrows-alt"></i>
<span>{{ metadata.width }} x {{ metadata.height }}</span>
</div>
<div class="preview-container" [class.preview-container--fade]="metadata?.editableAsText">
@if (metadata?.editableAsText) {
<div class="preview-code_container" data-testId="code-preview">
<code>{{ $content() }}</code>
</div>
} @else {
<div class="preview-image__container">
@if (previewFile.source === 'temp') {
<dot-temp-file-thumbnail
[tempFile]="previewFile.file"
[iconSize]="'48px'"
data-testId="temp-file-thumbnail" />
} @else {
<dot-contentlet-thumbnail
fieldVariable="asset"
[iconSize]="'48px'"
[contentlet]="previewFile.file"
[playableVideo]="true"
data-testId="contentlet-thumbnail" />
}
@if (metadata.fileSize) {
<div class="preview-metadata__info">
<i class="pi pi-file"></i>
<span>{{ metadata.fileSize | dotFileSizeFormat }}</span>
</div>
</div>
<div class="preview-metadata__container">
@if (metadata) {
<span class="preview-metadata_header">{{ metadata.title }}</span>
@if (metadata.width && metadata.height) {
<div class="preview-metadata__info">
<i class="pi pi-arrows-alt"></i>
<span>{{ metadata.width }} x {{ metadata.height }}</span>
</div>
}
@if (metadata.fileSize) {
<div class="preview-metadata__info">
<i class="pi pi-file"></i>
<span>{{ metadata.fileSize | dotFileSizeFormat }}</span>
</div>
}
}
}
</div>
</div>
}

<!-- Actions -->
<div class="preview-resource-links__actions">
<p-button
Expand All @@ -48,7 +55,7 @@
styleClass="p-button-rounded p-button-sm p-button-outlined"
data-testId="download-btn"
icon="pi pi-download"
(click)="downloadAsset(downloadLink)"/>
(click)="downloadAsset(downloadLink)" />
}
</div>
<div class="preview-metadata__actions">
Expand All @@ -63,19 +70,19 @@
<div class="preview-metadata__action--responsive">
<p-button
(click)="toggleShowDialog()"
styleClass="p-button-rounded p-button-text p-button-semi-transparent"
styleClass="p-button-rounded"
data-testId="infor-button-responsive"
icon="pi pi-info" />
@if (downloadLink) {
<p-button
styleClass="p-button-rounded p-button-text p-button-semi-transparent"
styleClass="p-button-rounded"
data-testId="download-btn-responsive"
icon="pi pi-download"
(click)="downloadAsset(downloadLink)" />
}
<p-button
(click)="removeFile.emit()"
styleClass="p-button-rounded p-button-text p-button-semi-transparent"
styleClass="p-button-rounded "
data-testId="remove-button-responsive"
icon="pi pi-trash" />
</div>
Expand Down Expand Up @@ -109,7 +116,7 @@
<span class="file-info__title">{{ sourceLink.key | dm }}:</span>
<div class="file-info__link">
<a [href]="sourceLink.value" target="_blank">
{{ sourceLink.value || ('dot.binary.field.no.link.found' | dm) }}
{{ sourceLink.value || ('dot.file.field.no.link.found' | dm) }}
</a>
<dot-copy-button [copy]="sourceLink.value" />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@
height: 100%;
}

dot-contentlet-thumbnail::ng-deep {
.background-image:not(.svg-thumbnail) {
img {
object-fit: cover;
}
}

img {
object-fit: contain;
}
}

.preview-container {
display: flex;
gap: $spacing-1;
Expand Down Expand Up @@ -63,13 +75,33 @@
}
}

.preview-code_container {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
user-select: none;

code {
background: #ffffff;
color: $color-palette-primary-500;
height: 100%;
width: 100%;
white-space: pre-wrap;
overflow: hidden;
line-height: normal;
}
}

.preview-metadata__action--responsive {
position: absolute;
bottom: $spacing-1;
right: $spacing-1;
display: flex;
flex-direction: column;
gap: $spacing-1;
z-index: 100;
}

.preview-resource-links__actions {
Expand Down Expand Up @@ -139,6 +171,18 @@
gap: $spacing-0;
}

.preview-container--fade::after {
content: "";
background: linear-gradient(0deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
position: absolute;
width: 100%;
height: 50%;
bottom: 0;
left: 0;
border-radius: $border-radius-md;
pointer-events: none;
}

@container preview (min-width: 500px) {
.preview-metadata__container,
.preview-metadata__actions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
inject,
input,
output,
signal, OnInit
signal,
OnInit
} from '@angular/core';

import { ButtonModule } from 'primeng/button';
Expand All @@ -18,12 +19,16 @@ import { catchError } from 'rxjs/operators';

import { DotResourceLinksService } from '@dotcms/data-access';
import { DotCMSBaseTypesContentTypes, DotCMSContentlet } from '@dotcms/dotcms-models';
import { DotTempFileThumbnailComponent, DotFileSizeFormatPipe, DotMessagePipe, DotCopyButtonComponent } from '@dotcms/ui';
import {
DotTempFileThumbnailComponent,
DotFileSizeFormatPipe,
DotMessagePipe,
DotCopyButtonComponent
} from '@dotcms/ui';

import { DotPreviewResourceLink, PreviewFile } from '../../models';
import { getFileMetadata } from '../../utils';


@Component({
selector: 'dot-file-field-preview',
standalone: true,
Expand Down Expand Up @@ -57,6 +62,15 @@ export class DotFileFieldPreviewComponent implements OnInit {
return getFileMetadata(previewFile.file);
});

$content = computed(() => {
const previewFile = this.$previewFile();
if (previewFile.source === 'contentlet') {
return previewFile.file.content;
}

return null;
});

$downloadLink = computed(() => {
const previewFile = this.$previewFile();
if (previewFile.source === 'contentlet') {
Expand Down Expand Up @@ -110,22 +124,22 @@ export class DotFileFieldPreviewComponent implements OnInit {
const options = [
{
key: 'FileLink',
value: fileLink,
value: fileLink
},
{
key: 'VersionPath',
value: versionPath,
value: versionPath
},
{
key: 'IdPath',
value: idPath,
value: idPath
}
];

if (contentlet.baseType === DotCMSBaseTypesContentTypes.FILEASSET) {
options.push({
key: 'Resource-Link',
value: text,
value: text
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<div
class="file-field__container"
[class.file-field__container--empty]="store.isInitOrPreview()"
[class.file-field__container--empty]="store.isInit()"
[class.file-field__container--preview]="store.isPreview()"
[class.file-field__container--uploading]="store.isUploading()">
@switch (store.fileStatus()) {
@case ('init') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,15 @@ input[type="file"] {
}

@container fileField (max-width: 500px) {
.file-field__container--preview,
.file-field__container--empty {
height: auto;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.file-field__container--empty {
height: auto;
}

.file-field__drop-zone {
width: 100%;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
import { DotFileFieldPreviewComponent } from './components/dot-file-field-preview/dot-file-field-preview.component';
import { DotFileFieldUiMessageComponent } from './components/dot-file-field-ui-message/dot-file-field-ui-message.component';
import { INPUT_TYPES } from './models';
import { DotFileFieldUploadService } from './services/upload-file/upload-file.service';
import { FileFieldStore } from './store/file-field.store';
import { getUiMessage } from './utils/messages';

Expand All @@ -41,6 +42,7 @@ import { getUiMessage } from './utils/messages';
DotFileFieldPreviewComponent
],
providers: [
DotFileFieldUploadService,
FileFieldStore,
{
multi: true,
Expand Down Expand Up @@ -80,6 +82,10 @@ export class DotEditContentFileFieldComponent implements ControlValueAccessor, O
}

writeValue(value: string): void {
if (!value) {
return;
}

this.store.getAssetData(value);
}
registerOnChange(fn: (value: string) => void) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export type PreviewFile =
file: DotCMSContentlet;
};

export interface DotPreviewResourceLink {
key: string;
value: string;
}
export interface DotPreviewResourceLink {
key: string;
value: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { of } from 'rxjs';

import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';

import { map, switchMap } from 'rxjs/operators';

import { DotUploadFileService } from '@dotcms/data-access';
import { DotCMSContentlet } from '@dotcms/dotcms-models';

import { DotEditContentService } from '../../../../services/dot-edit-content.service';
import { getFileMetadata, getFileVersion } from '../../utils';

@Injectable()
export class DotFileFieldUploadService {
readonly #fileService = inject(DotUploadFileService);
readonly #contentService = inject(DotEditContentService);
readonly #httpClient = inject(HttpClient);

uploadDotAsset(file: File) {
return this.#fileService
.uploadDotAsset(file)
.pipe(switchMap((contentlet) => this.#addContent(contentlet)));
}

getContentById(identifier: string) {
return this.#contentService
.getContentById(identifier)
.pipe(switchMap((contentlet) => this.#addContent(contentlet)));
}

#addContent(contentlet: DotCMSContentlet) {
const { editableAsText } = getFileMetadata(contentlet);
const contentURL = getFileVersion(contentlet);

if (editableAsText && contentURL) {
return this.#getContentFile(contentURL).pipe(
map((content) => ({ ...contentlet, content }))
);
}

return of(contentlet);
}

#getContentFile(contentURL: string) {
return this.#httpClient.get(contentURL, { responseType: 'text' });
}
}
Loading

0 comments on commit bd896c4

Please sign in to comment.