Skip to content

Commit

Permalink
feat(editor-content): init setup for image and file component #29871
Browse files Browse the repository at this point in the history
  • Loading branch information
nicobytes committed Sep 16, 2024
1 parent cfdc612 commit 69f5886
Show file tree
Hide file tree
Showing 18 changed files with 432 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,15 @@
@case (fieldTypes.FILE) {
<dot-edit-content-file-field
[formControlName]="field.variable"
[attr.data-testId]="'field-' + field.variable" />
[attr.data-testId]="'field-' + field.variable"
[field]="field"
/>
}
@case (fieldTypes.IMAGE) {
<dot-edit-content-file-field
[formControlName]="field.variable"
[attr.data-testId]="'field-' + field.variable"
[field]="field"/>
}
}
@if (field.hint) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { DotEditContentCalendarFieldComponent } from '../../fields/dot-edit-cont
import { DotEditContentCategoryFieldComponent } from '../../fields/dot-edit-content-category-field/dot-edit-content-category-field.component';
import { DotEditContentCheckboxFieldComponent } from '../../fields/dot-edit-content-checkbox-field/dot-edit-content-checkbox-field.component';
import { DotEditContentCustomFieldComponent } from '../../fields/dot-edit-content-custom-field/dot-edit-content-custom-field.component';
import { DotEditContentFileFieldComponent } from '../../fields/dot-edit-content-file-field/dot-edit-content-file-field.component';
import { DotEditContentHostFolderFieldComponent } from '../../fields/dot-edit-content-host-folder-field/dot-edit-content-host-folder-field.component';
import { DotEditContentJsonFieldComponent } from '../../fields/dot-edit-content-json-field/dot-edit-content-json-field.component';
import { DotEditContentKeyValueComponent } from '../../fields/dot-edit-content-key-value/dot-edit-content-key-value.component';
Expand Down Expand Up @@ -69,6 +70,8 @@ declare module '@tiptap/core' {
const FIELD_TYPES_COMPONENTS: Record<FIELD_TYPES, Type<unknown> | DotEditFieldTestBed> = {
// We had to use unknown because components have different types.
[FIELD_TYPES.TEXT]: DotEditContentTextFieldComponent,
[FIELD_TYPES.FILE]: DotEditContentFileFieldComponent,
[FIELD_TYPES.IMAGE]: DotEditContentFileFieldComponent,
[FIELD_TYPES.TEXTAREA]: DotEditContentTextAreaComponent,
[FIELD_TYPES.SELECT]: DotEditContentSelectFieldComponent,
[FIELD_TYPES.RADIO]: DotEditContentRadioFieldComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const defaultResolutionFn: FnResolutionValue = (contentlet, field) =>
export const resolutionValue: Record<FIELD_TYPES, FnResolutionValue> = {
[FIELD_TYPES.BINARY]: defaultResolutionFn,
[FIELD_TYPES.FILE]: defaultResolutionFn,
[FIELD_TYPES.IMAGE]: defaultResolutionFn,
[FIELD_TYPES.BLOCK_EDITOR]: defaultResolutionFn,
[FIELD_TYPES.CHECKBOX]: defaultResolutionFn,
[FIELD_TYPES.CONSTANT]: defaultResolutionFn,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Preview</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component } from '@angular/core';

@Component({
selector: 'dot-file-field-preview',
standalone: true,
imports: [],
providers: [],
templateUrl: './dot-file-field-preview.component.html',
styleUrls: ['./dot-file-field-preview.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class DotFileFieldPreviewComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div
[ngClass]="$uiMessage().severity"
class="icon-container"
data-testId="ui-message-icon-container">
<i [ngClass]="$uiMessage().icon" data-testId="ui-message-icon" class="icon"></i>
</div>
<div class="text">
<span [innerHTML]="$uiMessage().message" data-testId="ui-message-span"></span>
<ng-content></ng-content>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@use "variables" as *;

:host {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: $spacing-3;
height: 100%;
padding: $spacing-3;
}

.icon-container {
border-radius: 50%;
padding: $spacing-3;

.icon {
font-size: $font-size-xxl;
width: auto;
}

&.info {
color: $color-palette-primary-500;
background: $color-palette-primary-200;
}

&.error {
color: $color-alert-yellow;
background: $color-alert-yellow-light;
}
}

.text {
text-align: center;
line-height: 140%;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NgClass } from '@angular/common';
import { ChangeDetectionStrategy, Component, input } from '@angular/core';

import { UIMessage } from '../../models';

@Component({
selector: 'dot-file-field-ui-message',
standalone: true,
imports: [NgClass],
templateUrl: './dot-file-field-ui-message.component.html',
styleUrls: ['./dot-file-field-ui-message.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DotFileFieldUiMessageComponent {
$uiMessage = input.required<UIMessage>({ alias: 'uiMessage' });
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,83 @@
<h1>Hello</h1>
<h1>{{ $value() }}</h1>
<div
class="file-field__container"
[class.file-field__container--empty]="store.isEmpty()"
[class.file-field__container--uploading]="store.isUploading()">
@switch (store.fileStatus()) {
@case ('init') {
<div
[class.file-field__drop-zone--active]="store.dropZoneActive()"
class="file-field__drop-zone">
<dot-drop-zone data-testId="dropzone">
@if (store.uiMessage()) {
<dot-file-field-ui-message [uiMessage]="store.uiMessage()">
<button
class="file-field__drop-zone-btn"
data-testId="choose-file-btn"
type="button">
{{ 'dot.file.field.action.choose.file' | dm }}
</button>
</dot-file-field-ui-message>
}
</dot-drop-zone>
<input #inputFile data-testId="file-field__file-input" type="file" />
</div>

<div class="file-field__actions">
@if (store.allowURLImport()) {
<p-button
[label]="'dot.file.field.action.import.from.url' | dm"
data-testId="action-url-btn"
icon="pi pi-link"
styleClass="p-button-link p-button-sm" />
}
@if (store.allowExistingFile()) {
<p-button
[label]="'dot.file.field.action.select.existing.file' | dm"
data-testId="action-editor-btn"
icon="pi pi-file"
styleClass="p-button-link p-button-sm" />
}
@if (store.allowCreateFile()) {
<p-button
[label]="'dot.file.field.action.create.new.file' | dm"
data-testId="action-editor-btn"
icon="pi pi-code"
styleClass="p-button-link p-button-sm" />
}
@if (store.allowGenerateImg()) {
<p-button
[disabled]="!store.isAIPluginInstalled()"
tooltipPosition="bottom"
data-testId="action-ai-btn"
styleClass="p-button-link p-button-sm pointer-events-auto">
<svg
fill="none"
height="22"
viewBox="0 0 18 22"
width="18"
xmlns="http://www.w3.org/2000/svg">
<path
d="M9.48043 13.2597L5.40457 14.5046C5.29885 14.5368 5.20602 14.6037 5.13999 14.6952C5.07396 14.7868 5.03828 14.8981 5.03828 15.0124C5.03828 15.1268 5.07396 15.238 5.13999 15.3296C5.20602 15.4211 5.29885 15.488 5.40457 15.5203L9.48043 16.7651L10.6799 20.9949C10.711 21.1046 10.7755 21.2009 10.8637 21.2695C10.9519 21.338 11.0591 21.375 11.1693 21.375C11.2795 21.375 11.3867 21.338 11.4749 21.2695C11.5631 21.2009 11.6276 21.1046 11.6586 20.9949L12.8586 16.7651L16.9345 15.5203C17.0402 15.488 17.133 15.4211 17.1991 15.3296C17.2651 15.238 17.3008 15.1268 17.3008 15.0124C17.3008 14.8981 17.2651 14.7868 17.1991 14.6952C17.133 14.6037 17.0402 14.5368 16.9345 14.5046L12.8586 13.2597L11.6586 9.02989C11.6276 8.92018 11.5631 8.82385 11.4749 8.75533C11.3867 8.6868 11.2795 8.64977 11.1693 8.64977C11.0591 8.64977 10.9519 8.6868 10.8637 8.75533C10.7754 8.82385 10.711 8.92018 10.6799 9.02989L9.48043 13.2597Z"
fill="#426BF0" />
<path
d="M14.4668 5.66732L16.6779 4.99138C16.7836 4.95914 16.8764 4.89224 16.9424 4.8007C17.0084 4.70916 17.0441 4.59789 17.0441 4.48355C17.0441 4.3692 17.0084 4.25794 16.9424 4.16639C16.8764 4.07485 16.7836 4.00795 16.6779 3.97571L14.4668 3.3003L13.8154 1.00513C13.7844 0.895414 13.7199 0.799084 13.6317 0.730559C13.5435 0.662034 13.4362 0.625 13.3261 0.625C13.2159 0.625 13.1086 0.662034 13.0204 0.730559C12.9322 0.799084 12.8677 0.895414 12.8367 1.00513L12.1859 3.3003L9.9743 3.97571C9.86858 4.00794 9.77575 4.07483 9.70972 4.16638C9.6437 4.25792 9.60801 4.3692 9.60801 4.48355C9.60801 4.5979 9.6437 4.70917 9.70972 4.80072C9.77575 4.89226 9.86858 4.95915 9.9743 4.99138L12.1859 5.66732L12.8367 7.96196C12.8677 8.07168 12.9322 8.16801 13.0204 8.23653C13.1086 8.30506 13.2159 8.34209 13.3261 8.34209C13.4362 8.34209 13.5435 8.30506 13.6317 8.23653C13.7199 8.16801 13.7844 8.07168 13.8154 7.96196L14.4668 5.66732Z"
fill="#426BF0" />
<path
d="M3.24925 6.62823L1.01825 7.57256C0.924385 7.61231 0.844063 7.68016 0.787521 7.76748C0.730978 7.8548 0.700781 7.95761 0.700781 8.06282C0.700781 8.16802 0.730978 8.27083 0.787521 8.35815C0.844063 8.44547 0.924385 8.51333 1.01825 8.55307L3.24925 9.4974L4.1592 11.8127C4.19751 11.9101 4.2629 11.9935 4.34704 12.0522C4.43118 12.1109 4.53026 12.1422 4.63163 12.1422C4.733 12.1422 4.83208 12.1109 4.91622 12.0522C5.00036 11.9935 5.06576 11.9101 5.10406 11.8127L6.01402 9.4974L8.24456 8.55307C8.33841 8.51332 8.41873 8.44546 8.47527 8.35815C8.53181 8.27083 8.56201 8.16801 8.56201 8.06282C8.56201 7.95762 8.53181 7.8548 8.47527 7.76749C8.41873 7.68017 8.33841 7.61231 8.24456 7.57256L6.01402 6.62823L5.10406 4.31342C5.06576 4.21602 5.00036 4.13266 4.91622 4.07399C4.83208 4.01531 4.733 3.98397 4.63163 3.98397C4.53026 3.98397 4.43118 4.01531 4.34704 4.07399C4.2629 4.13266 4.19751 4.21602 4.1592 4.31342L3.24925 6.62823Z"
fill="#426BF0" />
</svg>
<span class="label-ai">
{{ 'dot.file.field.action.generate.with.dotai' | dm }}
</span>
</p-button>
}
</div>
}
@case ('uploading') {
<dot-spinner data-testId="loading" />
}
@case ('preview') {
<dot-file-field-preview />
}
}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
container-name: binaryField;
}

.binary-field__container {
.file-field__container {
display: flex;
justify-content: center;
align-items: center;
Expand All @@ -17,16 +17,16 @@
height: 14.4rem;
min-width: 12.5rem;

&:has(.binary-field__actions:empty) {
gap: 0; // Remove gap when there are no actions, is cleaner than removing the div by logic
&:has(.file-field__actions:empty) {
gap: 0;
}
}

.binary-field__container--uploading {
.file-field__container--uploading {
border: $field-border-size dashed $color-palette-gray-400;
}

.binary-field__actions {
.file-field__actions {
display: flex;
flex-direction: column;
gap: $spacing-3;
Expand All @@ -51,7 +51,7 @@
}
}

.binary-field__drop-zone {
.file-field__drop-zone {
border: $field-border-size dashed $input-border-color;
border-radius: $border-radius-md;
height: 100%;
Expand All @@ -60,7 +60,7 @@
margin-right: $spacing-1;
}

.binary-field__drop-zone-btn {
.file-field__drop-zone-btn {
border: none;
background: none;
color: $color-palette-primary-500;
Expand All @@ -71,7 +71,7 @@
cursor: pointer;
}

.binary-field__drop-zone--active {
.file-field__drop-zone--active {
border-radius: $border-radius-md;
border-color: $color-palette-secondary-500;
background: $white;
Expand All @@ -82,17 +82,18 @@ input[type="file"] {
display: none;
}

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

.binary-field__drop-zone {
.file-field__drop-zone {
width: 100%;
margin: 0;
margin-bottom: $spacing-1;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Spectator, createComponentFactory, mockProvider } from '@ngneat/spectator/jest';

import { provideHttpClient } from '@angular/common/http';

import { DotMessageService } from '@dotcms/data-access';

import { DotEditContentFileFieldComponent } from './dot-edit-content-file-field.component';
import { FileFileStore } from './store/file-field.store';

describe('DotEditContentFileFieldComponent', () => {
let spectator: Spectator<DotEditContentFileFieldComponent>;
const createComponent = createComponentFactory({
component: DotEditContentFileFieldComponent,
detectChanges: false,
componentProviders: [
FileFileStore
],
providers: [
provideHttpClient(),
mockProvider(DotMessageService)
]
});

beforeEach(() => spectator = createComponent());

it('should be created', () => {
expect(spectator.component).toBeTruthy();
});
});
Loading

0 comments on commit 69f5886

Please sign in to comment.