Skip to content

Commit

Permalink
#22018 Paste images to create external images blocks (#1981)
Browse files Browse the repository at this point in the history
* fix: paste image

* clean up

* clean up v2

* feedback
  • Loading branch information
rjvelazco authored May 12, 2022
1 parent 4fb1bb8 commit 6ad90e0
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 46 deletions.
49 changes: 24 additions & 25 deletions libs/block-editor/src/lib/extensions/imageUpload.extension.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Plugin, PluginKey } from 'prosemirror-state';
import { ComponentRef, Injector, ViewContainerRef } from '@angular/core';
import { Extension, getNodeType } from '@tiptap/core';
import { Extension } from '@tiptap/core';
import { DotImageService } from './services/dot-image/dot-image.service';
import { EditorView } from 'prosemirror-view';
import { LoaderComponent, MessageType } from './components/loader/loader.component';
Expand All @@ -14,7 +14,7 @@ export const ImageUpload = (injector: Injector, viewContainerRef: ViewContainerR

addProseMirrorPlugins() {
const dotImageService = injector.get(DotImageService);

const editor = this.editor;
function areImageFiles(event: ClipboardEvent | DragEvent): boolean {
let files: FileList;
if (event.type === 'drop') {
Expand All @@ -23,6 +23,7 @@ export const ImageUpload = (injector: Injector, viewContainerRef: ViewContainerR
//paste
files = (event as ClipboardEvent).clipboardData.files;
}

if (files.length > 0) {
for (let i = 0; i < files.length; i++) {
if (!files[i].type.startsWith('image/')) {
Expand Down Expand Up @@ -56,39 +57,37 @@ export const ImageUpload = (injector: Injector, viewContainerRef: ViewContainerR
}

function uploadImages(view: EditorView, files: File[], position: number) {
const { schema } = view.state;

setPlaceHolder(view, position, files[0].name);

const placeHolderName = files[0].name;
setPlaceHolder(view, position, placeHolderName);
dotImageService
.publishContent(files)
.pipe(take(1))
.subscribe(
(dotAssets: DotCMSContentlet[]) => {
const tr = view.state.tr;
const data = dotAssets[0][Object.keys(dotAssets[0])[0]];
const imageNode = getNodeType('dotImage', schema).create({
data: data
});
view.dispatch(
tr
.replaceRangeWith(position, position, imageNode)
.setMeta(PlaceholderPlugin, {
remove: { id: data.name }
})
);
const node = {
attrs: {
data
},
type: 'dotImage'
};
editor.commands.insertContentAt(position, node);
},
(error) => {
alert(error.message);
view.dispatch(
view.state.tr.setMeta(PlaceholderPlugin, {
remove: { id: files[0].name }
})
);
}
(error) => alert(error.message),
() => removePlaceHolder(placeHolderName)
);
}

function removePlaceHolder(id: string) {
const { view } = editor;
const { state } = view;
view.dispatch(
state.tr.setMeta(PlaceholderPlugin, {
remove: { id }
})
);
}

/**
* Get position from cursor current position when pasting an image
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Injectable } from '@angular/core';
import { uploadBinaryFile } from '@dotcms/utils';
import { from, Observable } from 'rxjs';
import { pluck, switchMap } from 'rxjs/operators';
import { uploadFile } from '@dotcms/utils';
import { from, Observable, throwError } from 'rxjs';
import { catchError, pluck, switchMap } from 'rxjs/operators';
import { DotCMSContentlet, DotCMSTempFile } from '@dotcms/dotcms-models';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class DotImageService {
constructor(private http: HttpClient) {}

publishContent(data: File | File[], maxSize?: string): Observable<DotCMSContentlet[]> {
publishContent(data: string | File | File[], maxSize?: string): Observable<DotCMSContentlet[]> {
return this.setTempResource(data, maxSize).pipe(
switchMap((response: DotCMSTempFile | DotCMSTempFile[]) => {
const files = Array.isArray(response) ? response : [response];
Expand All @@ -34,14 +34,23 @@ export class DotImageService {
}
)
.pipe(pluck('entity', 'results')) as Observable<DotCMSContentlet[]>;
})
}),
catchError((error) => throwError(error))
);
}

private setTempResource(
data: File | File[],
file: string | File | File[],
maxSize?: string
): Observable<DotCMSTempFile | DotCMSTempFile[]> {
return from(uploadBinaryFile(data, () => {}, maxSize));
return from(
uploadFile({
file,
progressCallBack: () => {
/**/
},
maxSize
})
);
}
}
39 changes: 25 additions & 14 deletions libs/utils/src/lib/services/dot-temp-file.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ export const fallbackErrorMessages = {
401: '401 Unauthorized Error'
};

export interface UploadTempFileProps<T = string | File | File[]> {
file: T;
progressCallBack?;
maxSize?: string;
}

const TEMP_API_URL = '/api/v1/temp';

/**
Expand All @@ -15,11 +21,15 @@ const TEMP_API_URL = '/api/v1/temp';
* @param maxSize
*
*/
export function uploadFile(file: string | File, maxSize?: string): Promise<DotCMSTempFile> {
export function uploadFile({
file,
progressCallBack,
maxSize
}: UploadTempFileProps): Promise<DotCMSTempFile> {
if (typeof file === 'string') {
return uploadFileByURL(file);
} else {
return uploadBinaryFile(file, maxSize) as Promise<DotCMSTempFile>;
return uploadBinaryFile({ file, progressCallBack, maxSize }) as Promise<DotCMSTempFile>;
}
}

Expand Down Expand Up @@ -52,19 +62,18 @@ function uploadFileByURL(url: string): Promise<DotCMSTempFile> {
* @param maxSize
*
*/
export function uploadBinaryFile(
data: File | File[],
progressCallBack?,
maxSize?: string
): Promise<DotCMSTempFile | DotCMSTempFile[]> {
export function uploadBinaryFile({
file: data,
progressCallBack,
maxSize
}: UploadTempFileProps<File | File[]>): Promise<DotCMSTempFile | DotCMSTempFile[]> {
let path = TEMP_API_URL;
path += maxSize ? `?maxFileLength=${maxSize}` : '';
const formData = new FormData();

const files = Array.isArray(data) ? data : [data];
files.forEach((file: File) => {
formData.append('files', file);
});

files.forEach((file: File) => formData.append('files', file));

return dotRequest(
path,
Expand All @@ -75,23 +84,25 @@ export function uploadBinaryFile(
},
progressCallBack
)
.then(async (request: XMLHttpRequest) => {
.then((request: XMLHttpRequest) => {
if (request.status === 200) {
const data = JSON.parse(request.response).tempFiles;
return data.length > 1 ? data : data[0];
} else {
throw request;
}
})
.catch((request) => {
.catch((request: XMLHttpRequest) => {
throw errorHandler(JSON.parse(request.response), request.status);
});
}

function dotRequest(
url: string,
opts: DotHttpRequestOptions,
progressCallBack: (progress: number) => {}
progressCallBack: (progress: number) => {
/* */
}
): Promise<XMLHttpRequest> {
return new Promise((res, rej) => {
const xhr = new XMLHttpRequest();
Expand All @@ -111,7 +122,7 @@ function dotRequest(
});
}

function errorHandler(response: any, status: number): DotHttpErrorResponse {
function errorHandler(response: Record<string, string>, status: number): DotHttpErrorResponse {
let message = '';
try {
message = response.message || fallbackErrorMessages[status];
Expand Down

0 comments on commit 6ad90e0

Please sign in to comment.