Browse Source

Refactor MoveComponent

typed-command-runs
Artur Arseniev 5 months ago
parent
commit
270c6534ef
  1. 3
      packages/core/src/commands/registry.ts
  2. 106
      packages/core/src/commands/view/MoveComponent.ts
  3. 42
      packages/core/test/specs/commands/view/MoveComponent.ts

3
packages/core/src/commands/registry.ts

@ -17,6 +17,7 @@ import type { ExportTemplateCommandRegistryRun, ExportTemplateCommandRegistrySto
import type { OpenAssetsCommandRegistryRun, OpenAssetsCommandRegistryStop } from './view/OpenAssets';
import type { OpenLayersCommandRegistryRun, OpenLayersCommandRegistryStop } from './view/OpenLayers';
import type { OpenBlocksCommandRegistryRun, OpenBlocksCommandRegistryStop } from './view/OpenBlocks';
import type { MoveComponentCommandRegistryRun, MoveComponentCommandRegistryStop } from './view/MoveComponent';
import type { ShowOffsetCommandRegistryRun, ShowOffsetCommandRegistryStop } from './view/ShowOffset';
import type { SwitchVisibilityCommandRegistryRun, SwitchVisibilityCommandRegistryStop } from './view/SwitchVisibility';
import type {
@ -44,6 +45,7 @@ export interface CommandRegistryRun
CanvasMoveCommandRegistryRun,
CanvasClearCommandRegistryRun,
ExportTemplateCommandRegistryRun,
MoveComponentCommandRegistryRun,
OpenAssetsCommandRegistryRun,
OpenBlocksCommandRegistryRun,
OpenLayersCommandRegistryRun,
@ -58,6 +60,7 @@ export interface CommandRegistryStop
ResizeCommandRegistryStop,
CanvasMoveCommandRegistryStop,
ExportTemplateCommandRegistryStop,
MoveComponentCommandRegistryStop,
OpenAssetsCommandRegistryStop,
OpenBlocksCommandRegistryStop,
OpenLayersCommandRegistryStop,

106
packages/core/src/commands/view/MoveComponent.ts

@ -1,38 +1,55 @@
import { bindAll, extend } from 'underscore';
import { bindAll } from 'underscore';
import { $ } from '../../common';
import Component from '../../dom_components/model/Component';
import type Component from '../../dom_components/model/Component';
import { off, on } from '../../utils/dom';
import { CommandObject } from './CommandAbstract';
import type { CommandPublicFnFromHandler } from '../registryHelpers';
import CommandAbstract from './CommandAbstract';
import SelectComponent from './SelectComponent';
import SelectPosition from './SelectPosition';
export default extend({}, SelectPosition, SelectComponent, {
export interface MoveComponentCommandRegistryRun {
'core:component-move': CommandPublicFnFromHandler<CommandMoveComponent['run']>;
'move-comp': CommandPublicFnFromHandler<CommandMoveComponent['run']>;
}
export interface MoveComponentCommandRegistryStop {
'core:component-move': CommandPublicFnFromHandler<CommandMoveComponent['stop']>;
'move-comp': CommandPublicFnFromHandler<CommandMoveComponent['stop']>;
}
export default class CommandMoveComponent extends CommandAbstract {
[key: string]: any;
init(o: any) {
SelectComponent.init.apply(this, arguments);
(SelectComponent.init as any).apply(this, arguments as any);
bindAll(this, 'initSorter', 'rollback', 'onEndMove');
this.opt = o;
this.hoverClass = this.ppfx + 'highlighter-warning';
this.badgeClass = this.ppfx + 'badge-warning';
this.noSelClass = this.ppfx + 'no-select';
},
this.hoverClass = `${this.ppfx}highlighter-warning`;
this.badgeClass = `${this.ppfx}badge-warning`;
this.noSelClass = `${this.ppfx}no-select`;
}
run(...args: any[]) {
return (SelectPosition.run as any).apply(this, args);
}
enable(...args: any) {
enable(...args: any[]) {
SelectComponent.enable.apply(this, args);
this.getBadgeEl().addClass(this.badgeClass);
this.getHighlighterEl().addClass(this.hoverClass);
var wp = this.$wrapper;
const wp = this.$wrapper;
wp.css('cursor', 'move');
wp.on('mousedown', this.initSorter);
// Avoid strange moving behavior
wp.addClass(this.noSelClass);
},
}
/**
* Overwrite for doing nothing
* @private
*/
toggleClipboard() {},
toggleClipboard() {}
/**
* Delegate sorting
@ -40,8 +57,8 @@ export default extend({}, SelectPosition, SelectComponent, {
* @private
* */
initSorter(e: any) {
var el = $(e.target).data('model');
var drag = el.get('draggable');
const el = $(e.target).data('model');
const drag = el.get('draggable');
if (!drag) return;
// Avoid badge showing on move
@ -52,7 +69,7 @@ export default extend({}, SelectPosition, SelectComponent, {
this.stopSelectComponent();
this.$wrapper.off('mousedown', this.initSorter);
on(this.getContentWindow(), 'keydown', this.rollback);
},
}
/**
* Init sorter from model
@ -60,27 +77,18 @@ export default extend({}, SelectPosition, SelectComponent, {
* @private
*/
initSorterFromModel(model: Component) {
var drag = model.get('draggable');
const drag = model.get('draggable');
if (!drag) return;
// Avoid badge showing on move
this.cacheEl = null;
// @ts-ignore
var el = model.view.el;
const el = model.view?.el;
if (!el) return;
this.startSelectPosition(el, this.frameEl.contentDocument);
this.sorter.draggable = drag;
this.sorter.eventHandlers.legacyOnEndMove = this.onEndMoveFromModel.bind(this);
/*
this.sorter.setDragHelper(el);
var dragHelper = this.sorter.dragHelper;
dragHelper.className = this.ppfx + 'drag-helper';
dragHelper.innerHTML = '';
dragHelper.backgroundColor = 'white';
*/
this.stopSelectComponent();
on(this.getContentWindow(), 'keydown', this.rollback);
},
}
/**
* Init sorter from models
@ -101,11 +109,11 @@ export default extend({}, SelectPosition, SelectComponent, {
this.sorter.eventHandlers.legacyOnEndMove = this.onEndMoveFromModel.bind(this);
this.stopSelectComponent();
on(this.getContentWindow(), 'keydown', this.rollback);
},
}
onEndMoveFromModel() {
off(this.getContentWindow(), 'keydown', this.rollback);
},
}
/**
* Callback after sorting
@ -114,7 +122,7 @@ export default extend({}, SelectPosition, SelectComponent, {
onEndMove() {
this.enable();
off(this.getContentWindow(), 'keydown', this.rollback);
},
}
/**
* Say what to do after the component was selected (selectComponent)
@ -122,7 +130,7 @@ export default extend({}, SelectPosition, SelectComponent, {
* @param {Object} Selected element
* @private
* */
onSelect(e: any, el: any) {},
onSelect(e: any, el: any) {}
/**
* Used to bring the previous situation before start moving the component
@ -130,13 +138,13 @@ export default extend({}, SelectPosition, SelectComponent, {
* @param {Boolean} Indicates if rollback in anycase
* @private
* */
rollback(e: any, force: boolean) {
var key = e.which || e.keyCode;
rollback(e: any, force?: boolean) {
const key = e.which || e.keyCode;
if (key == 27 || force) {
this.sorter.cancelDrag();
}
return;
},
}
/**
* Returns badge element
@ -146,7 +154,7 @@ export default extend({}, SelectPosition, SelectComponent, {
getBadgeEl() {
if (!this.$badge) this.$badge = $(this.getBadge());
return this.$badge;
},
}
/**
* Returns highlighter element
@ -156,14 +164,24 @@ export default extend({}, SelectPosition, SelectComponent, {
getHighlighterEl() {
if (!this.$hl) this.$hl = $(this.canvas.getHighlighter());
return this.$hl;
},
}
stop(...args) {
// @ts-ignore
SelectComponent.stop.apply(this, args);
stop(...args: any[]) {
(SelectComponent.stop as any).apply(this, args);
this.getBadgeEl().removeClass(this.badgeClass);
this.getHighlighterEl().removeClass(this.hoverClass);
var wp = this.$wrapper;
const wp = this.$wrapper;
wp.css('cursor', '').unbind().removeClass(this.noSelClass);
},
} as CommandObject<{}, { [k: string]: any }>);
}
}
[
SelectPosition as Record<string, unknown>,
SelectComponent as Record<string, unknown>,
].forEach((source) => {
Object.keys(source).forEach((key) => {
if (!(key in CommandMoveComponent.prototype)) {
(CommandMoveComponent.prototype as Record<string, unknown>)[key] = source[key];
}
});
});

42
packages/core/test/specs/commands/view/MoveComponent.ts

@ -0,0 +1,42 @@
import MoveComponent from '../../../../src/commands/view/MoveComponent';
describe('MoveComponent command', () => {
test('rollback should cancel drag on escape', () => {
const command = new MoveComponent({});
const cancelDrag = jest.fn();
command.sorter = { cancelDrag };
command.rollback({ which: 27 }, false);
expect(cancelDrag).toHaveBeenCalledTimes(1);
});
test('stop should reset wrapper and remove helper classes', () => {
const command = new MoveComponent({});
const wrapper: any = {};
wrapper.css = jest.fn(() => wrapper);
wrapper.unbind = jest.fn(() => wrapper);
wrapper.removeClass = jest.fn(() => wrapper);
const removeBadgeClass = jest.fn();
const removeHighlighterClass = jest.fn();
command.$wrapper = wrapper;
command.$badge = { removeClass: removeBadgeClass };
command.$hl = { removeClass: removeHighlighterClass };
command.badgeClass = 'badge-warning';
command.hoverClass = 'highlighter-warning';
command.noSelClass = 'no-select';
command.onHovered = jest.fn();
command.stopSelectComponent = jest.fn();
command.em = { setSelected: jest.fn() } as any;
command.toggleToolsEl = jest.fn();
command.editor = { stopCommand: jest.fn() };
command.stop();
expect(removeBadgeClass).toHaveBeenCalledWith('badge-warning');
expect(removeHighlighterClass).toHaveBeenCalledWith('highlighter-warning');
expect(wrapper.css).toHaveBeenCalledWith('cursor', '');
expect(wrapper.unbind).toHaveBeenCalledTimes(1);
expect(wrapper.removeClass).toHaveBeenCalledWith('no-select');
});
});
Loading…
Cancel
Save