Browse Source

Improve TS for custom file upload option (#6578)

Fix D&D file upload TS
markdanial-patch-1
Artur Arseniev 6 months ago
committed by GitHub
parent
commit
1c8506eb7b
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      packages/core/src/asset_manager/config/config.ts
  2. 7
      packages/core/src/asset_manager/index.ts
  3. 17
      packages/core/src/asset_manager/types.ts
  4. 13
      packages/core/src/asset_manager/view/FileUploader.ts
  5. 9
      packages/core/src/dom_components/view/ComponentImageView.ts
  6. 22
      packages/core/src/utils/Droppable.ts

4
packages/core/src/asset_manager/config/config.ts

@ -1,3 +1,5 @@
import { UploadFileFn } from '../types';
export interface AssetManagerConfig { export interface AssetManagerConfig {
/** /**
* Default assets. * Default assets.
@ -83,7 +85,7 @@ export interface AssetManagerConfig {
* // ...send somewhere * // ...send somewhere
* } * }
*/ */
uploadFile?: (ev: DragEvent) => void; uploadFile?: UploadFileFn;
/** /**
* In the absence of 'uploadFile' or 'upload' assets will be embedded as Base64. * In the absence of 'uploadFile' or 'upload' assets will be embedded as Base64.
* @default true * @default true

7
packages/core/src/asset_manager/index.ts

@ -40,13 +40,10 @@ import { ProjectData } from '../storage_manager';
import defConfig, { AssetManagerConfig } from './config/config'; import defConfig, { AssetManagerConfig } from './config/config';
import Asset from './model/Asset'; import Asset from './model/Asset';
import Assets from './model/Assets'; import Assets from './model/Assets';
import AssetsEvents, { AssetOpenOptions } from './types'; import AssetsEvents, { AssetAddInput, AssetOpenOptions, AssetProps } from './types';
import AssetsView from './view/AssetsView'; import AssetsView from './view/AssetsView';
import FileUploaderView from './view/FileUploader'; import FileUploaderView from './view/FileUploader';
// TODO
type AssetProps = Record<string, any>;
const assetCmd = 'open-assets'; const assetCmd = 'open-assets';
export default class AssetManager extends ItemManagerModule<AssetManagerConfig, Assets> { export default class AssetManager extends ItemManagerModule<AssetManagerConfig, Assets> {
@ -153,7 +150,7 @@ export default class AssetManager extends ItemManagerModule<AssetManagerConfig,
* }); * });
* assetManager.add([{ src: 'img2.jpg' }, { src: 'img2.png' }]); * assetManager.add([{ src: 'img2.jpg' }, { src: 'img2.png' }]);
*/ */
add(asset: string | AssetProps | (string | AssetProps)[], opts: AddOptions = {}) { add(asset: AssetAddInput | AssetAddInput[], opts: AddOptions = {}) {
// Put the model at the beginning // Put the model at the beginning
if (typeof opts.at == 'undefined') { if (typeof opts.at == 'undefined') {
opts.at = 0; opts.at = 0;

17
packages/core/src/asset_manager/types.ts

@ -1,7 +1,10 @@
import ComponentView from '../dom_components/view/ComponentView';
import Asset from './model/Asset'; import Asset from './model/Asset';
export type AssetEvent = `${AssetsEvents}`; export type AssetEvent = `${AssetsEvents}`;
export type AssetAddInput = string | AssetProps | Asset;
export interface AssetOpenOptions { export interface AssetOpenOptions {
select?: (asset: Asset, complete: boolean) => void; select?: (asset: Asset, complete: boolean) => void;
types?: string[]; types?: string[];
@ -9,6 +12,20 @@ export interface AssetOpenOptions {
target?: any; target?: any;
} }
export interface AssetProps {
src: string;
[key: string]: unknown;
}
export interface UploadFileOptions {
componentView?: ComponentView;
file?: File;
}
export type UploadFileClb = (result: { data: (AssetProps | string)[] }) => void;
export type UploadFileFn = (ev: DragEvent, clb?: UploadFileClb, opts?: UploadFileOptions) => Promise<void> | undefined;
/**{START_EVENTS}*/ /**{START_EVENTS}*/
export enum AssetsEvents { export enum AssetsEvents {
/** /**

13
packages/core/src/asset_manager/view/FileUploader.ts

@ -4,6 +4,7 @@ import EditorModel from '../../editor/model/Editor';
import fetch from '../../utils/fetch'; import fetch from '../../utils/fetch';
import html from '../../utils/html'; import html from '../../utils/html';
import { AssetManagerConfig } from '../config/config'; import { AssetManagerConfig } from '../config/config';
import { UploadFileClb, UploadFileOptions } from '../types';
type FileUploaderTemplateProps = { type FileUploaderTemplateProps = {
pfx: string; pfx: string;
@ -53,7 +54,7 @@ export default class FileUploaderView extends View {
constructor(opts: any = {}) { constructor(opts: any = {}) {
super(opts); super(opts);
this.options = opts; this.options = opts;
const c = opts.config || {}; const c = (opts.config || {}) as AssetManagerConfig & { pStylePrefix?: string; disableUpload?: boolean };
this.module = opts.module; this.module = opts.module;
this.config = c; this.config = c;
// @ts-ignore // @ts-ignore
@ -113,7 +114,7 @@ export default class FileUploaderView extends View {
* @param {string} text Response text * @param {string} text Response text
* @private * @private
*/ */
onUploadResponse(text: string, clb?: (json: any) => void) { onUploadResponse(text: string, clb?: UploadFileClb) {
const { module, config, target } = this; const { module, config, target } = this;
let json; let json;
try { try {
@ -138,9 +139,9 @@ export default class FileUploaderView extends View {
* @return {Promise} * @return {Promise}
* @private * @private
* */ * */
uploadFile(e: DragEvent, clb?: () => void) { uploadFile(e: DragEvent, clb?: UploadFileClb, opts?: UploadFileOptions) {
// @ts-ignore opts; // Options are not used here but can be used by the custom uploadFile function
const files = e.dataTransfer ? e.dataTransfer.files : e.target.files; const files = e.dataTransfer ? e.dataTransfer.files : ((e.target as any)?.files as FileList);
const { config } = this; const { config } = this;
const { beforeUpload } = config; const { beforeUpload } = config;
@ -293,7 +294,7 @@ export default class FileUploaderView extends View {
return this; return this;
} }
static embedAsBase64(e: DragEvent, clb?: () => void) { static embedAsBase64(e: DragEvent, clb?: UploadFileClb) {
// List files dropped // List files dropped
// @ts-ignore // @ts-ignore
const files = e.dataTransfer ? e.dataTransfer.files : e.target.files; const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;

9
packages/core/src/dom_components/view/ComponentImageView.ts

@ -40,14 +40,17 @@ export default class ComponentImageView<TComp extends ComponentImage = Component
const fu = em.Assets.FileUploader(); const fu = em.Assets.FileUploader();
fu?.uploadFile( fu?.uploadFile(
{ {
// @ts-ignore
dataTransfer: { files: [file] }, dataTransfer: { files: [file] },
}, } as unknown as DragEvent,
(res: any) => { (res) => {
const obj = res && res.data && res.data[0]; const obj = res && res.data && res.data[0];
const src = obj && (isString(obj) ? obj : obj.src); const src = obj && (isString(obj) ? obj : obj.src);
src && model.set({ src }); src && model.set({ src });
}, },
{
componentView: this,
file,
},
); );
model.set('file', ''); model.set('file', '');
} }

22
packages/core/src/utils/Droppable.ts

@ -1,12 +1,12 @@
import { bindAll, indexOf } from 'underscore'; import { bindAll, indexOf } from 'underscore';
import CanvasModule from '../canvas'; import CanvasModule from '../canvas';
import { ObjectStrings } from '../common'; import { ObjectStrings } from '../common';
import Component from '../dom_components/model/Component';
import EditorModel from '../editor/model/Editor'; import EditorModel from '../editor/model/Editor';
import { getDocumentScroll, off, on } from './dom'; import { getDocumentScroll, off, on } from './dom';
import { DragDirection, DragSource } from './sorter/types';
import CanvasNewComponentNode from './sorter/CanvasNewComponentNode'; import CanvasNewComponentNode from './sorter/CanvasNewComponentNode';
import ComponentSorter from './sorter/ComponentSorter'; import ComponentSorter from './sorter/ComponentSorter';
import Component from '../dom_components/model/Component'; import { DragDirection, DraggableContent, DragSource } from './sorter/types';
// TODO move in sorter // TODO move in sorter
type SorterOptions = { type SorterOptions = {
@ -233,7 +233,7 @@ export default class Droppable {
handleDrop(ev: Event | DragEvent) { handleDrop(ev: Event | DragEvent) {
ev.preventDefault(); ev.preventDefault();
const dt = (ev as DragEvent).dataTransfer; const dt = (ev as DragEvent).dataTransfer;
const content = this.getContentByData(dt).content; const content = this.getContentByData(dt!).content || '';
if (this.draggedNode) { if (this.draggedNode) {
this.draggedNode.content = content; this.draggedNode.content = content;
} }
@ -241,12 +241,12 @@ export default class Droppable {
this.endDrop(!content, ev); this.endDrop(!content, ev);
} }
getContentByData(dt: any) { getContentByData(dt?: DataTransfer) {
const em = this.em; const em = this.em;
const types = dt && dt.types; const types = dt?.types || [];
const files = (dt && dt.files) || []; const files = dt?.files || [];
const dragSource: DragSource<Component> = em.get('dragSource'); const dragSource: DragSource<Component> = em.get('dragSource');
let content = dt && dt.getData('text'); let content: DraggableContent['content'] = dt?.getData('text') || '';
if (files.length) { if (files.length) {
content = []; content = [];
@ -280,9 +280,13 @@ export default class Droppable {
content = `<div>${content}</div>`; content = `<div>${content}</div>`;
} }
const result = { content }; const result = {
content,
setContent(content: DraggableContent['content']) {
result.content = content;
},
};
em.trigger('canvas:dragdata', dt, result); em.trigger('canvas:dragdata', dt, result);
return result; return result;
} }
} }

Loading…
Cancel
Save