Browse Source

Convert views into ts

pull/4431/head
Alex Ritter 4 years ago
parent
commit
b5a63e19d6
  1. 2
      src/abstract/Collection.ts
  2. 37
      src/abstract/View.ts
  3. 7
      src/panels/index.ts
  4. 29
      src/panels/model/Button.ts
  5. 2
      src/panels/model/Panel.ts
  6. 70
      src/panels/view/ButtonView.ts
  7. 28
      src/panels/view/ButtonsView.ts
  8. 29
      src/panels/view/PanelView.ts
  9. 33
      src/panels/view/PanelsView.ts
  10. 4
      test/specs/panels/view/ButtonsView.js
  11. 21
      test/specs/panels/view/PanelView.js
  12. 10
      test/specs/panels/view/PanelsView.js

2
src/abstract/Collection.ts

@ -7,7 +7,7 @@ type ModelConstructor<TModel extends Model> = { new (mod: Module<TModel>, attr:
export default class Collection<TModel extends Model = Model> extends Backbone.Collection<TModel> {
module!: Module<TModel>;
private newModel!: { new (mod: Module<TModel>, attr: any): TModel };
private newModel!: ModelConstructor<TModel>;
//modelConstructor = {new (mod: Module<TModel>, attr: any): TModel}
add(model: Array<Record<string, any>> | TModel, options?: AddOptions): TModel;

37
src/abstract/View.ts

@ -1,29 +1,44 @@
import Backbone from 'backbone';
import Collection from './Collection';
import Model from './Model';
import Module, { IBaseModule } from './Module';
import { IBaseModule } from './Module';
export default class View<TModel extends Model = Model, TElement extends Element = HTMLElement> extends Backbone.View<
TModel,
TElement
> {
type ModuleFromModel<TModel extends Model> = TModel extends Model<infer M> ? M : unknown;
type Module<TItem extends Model | Collection> = TItem extends Collection<infer M>
? ModuleFromModel<M>
: TItem extends Model<infer M>
? M
: unknown;
export default class View<
TModel extends Model | Collection = Model,
TElement extends Element = HTMLElement
> extends Backbone.View<TModel extends Model ? TModel : undefined, TElement> {
protected get pfx() {
return this.ppfx + this.config.stylePrefix || '';
return this.ppfx + (this.config as any).stylePrefix || '';
}
protected get ppfx() {
return (this.em.config as any).stylePrefix || '';
return this.em.config.stylePrefix || '';
}
protected get module(): TModel extends Model<infer M> ? M : unknown {
//console.log((this.collection.first as any).module)
return this.model?.module ?? (this.collection as any).module;
collection!: TModel extends Collection ? TModel : Collection<Model>;
protected get module(): Module<TModel> {
return (this.model as any)?.module ?? this.collection.module;
}
protected get em() {
return this.module.em;
}
protected get config(): TModel extends Model<infer M> ? (M extends IBaseModule<infer C> ? C : unknown) : unknown {
protected get config(): Module<TModel> extends IBaseModule<infer C> ? C : unknown {
return this.module.config as any;
}
public className!: string;
preinitialize(options?: any) {
this.className = '';
}
}

7
src/panels/index.ts

@ -191,15 +191,10 @@ export default class PanelManager extends Module<typeof defaults> {
/**
* Render panels and buttons
* @return {HTMLElement}
* @private
*/
render() {
this.PanelsViewObj && this.PanelsViewObj.remove();
this.PanelsViewObj = new PanelsView({
collection: this.panels,
//@ts-ignore
config: this.config,
});
this.PanelsViewObj = new PanelsView(this.panels);
return this.PanelsViewObj.render().el;
}

29
src/panels/model/Button.ts

@ -24,6 +24,35 @@ export default class Button extends Model<PanelManager> {
};
}
get className(): string {
return this.get('className');
}
get command(): string {
return this.get('command');
}
get active(): boolean {
return this.get('active');
}
set active(isActive: boolean) {
this.set('active', isActive);
}
get togglable(): boolean {
return this.get('togglable');
}
get runDefaultCommand(): boolean {
return this.get('runDefaultCommand');
}
get stopDefaultCommand(): boolean {
return this.get('stopDefaultCommand');
}
get disable(): boolean {
return this.get('disable');
}
constructor(module: PanelManager, options: any) {
super(module, options);
if (this.get('buttons').length) {

2
src/panels/model/Panel.ts

@ -21,6 +21,8 @@ export default class Panel extends Model<PanelManager> {
this.set('buttons', buttons);
}
view?: any;
constructor(module: PanelManager, options: any) {
super(module, options);
var btn = this.get('buttons') || [];

70
src/panels/view/ButtonView.js → src/panels/view/ButtonView.ts

@ -1,7 +1,10 @@
import { isString, isObject, isFunction } from 'underscore';
import { View } from '../../common';
import { View } from '../../abstract';
import Button from '../model/Button';
import Buttons from '../model/Buttons';
export default class ButtonView extends View {
export default class ButtonView extends View<Button> {
//@ts-ignore
tagName() {
return this.model.get('tagName');
}
@ -12,18 +15,20 @@ export default class ButtonView extends View {
};
}
initialize(o) {
const { model } = this;
const cls = model.get('className');
commands: any;
activeCls: string;
disableCls: string;
btnsVisCls: string;
//Note: I don't think this is working
$buttons?: any;
constructor(o: any) {
super(o);
const { model, em, pfx, ppfx } = this;
const cls = model.className;
const { command, listen } = model.attributes;
const config = o.config || {};
const { em } = config;
this.config = config;
this.em = em;
const pfx = this.config.stylePrefix || '';
const ppfx = this.config.pStylePrefix || '';
this.pfx = pfx;
this.ppfx = this.config.pStylePrefix || '';
this.id = pfx + model.get('id');
this.activeCls = `${pfx}active ${ppfx}four-color`;
this.disableCls = `${ppfx}disabled`;
@ -38,7 +43,7 @@ export default class ButtonView extends View {
this.listenTo(model, 'change:disable', this.updateDisable);
if (em && isString(command) && listen) {
const chnOpt = { fromListen: 1 };
const chnOpt: any = { fromListen: true };
this.listenTo(em, `run:${command}`, () => model.set('active', true, chnOpt));
this.listenTo(em, `stop:${command}`, () => model.set('active', false, chnOpt));
}
@ -51,9 +56,9 @@ export default class ButtonView extends View {
*
* @return void
* */
updateClassName() {
private updateClassName() {
const { model, pfx } = this;
const cls = model.get('className');
const cls = model.className;
const attrCls = model.get('attributes').class;
const classStr = `${attrCls ? attrCls : ''} ${pfx}btn ${cls ? cls : ''}`;
this.$el.attr('class', classStr.trim());
@ -64,7 +69,7 @@ export default class ButtonView extends View {
*
* @return void
* */
updateAttributes() {
private updateAttributes() {
const { em, model, $el } = this;
const attr = model.get('attributes') || {};
const title = em && em.t && em.t(`panels.buttons.titles.${model.id}`);
@ -79,7 +84,7 @@ export default class ButtonView extends View {
*
* @return void
* */
updateBtnsVis() {
private updateBtnsVis() {
if (!this.$buttons) return;
if (this.model.get('bntsVis')) this.$buttons.addClass(this.btnsVisCls);
@ -91,12 +96,12 @@ export default class ButtonView extends View {
*
* @return void
* */
updateActive(m, v, opts = {}) {
private updateActive(m: any, v: any, opts: any = {}) {
const { model, commands, $el, activeCls } = this;
const { fromCollection, fromListen } = opts;
const context = model.get('context');
const options = model.get('options');
const commandName = model.get('command');
const commandName = model.command;
let command = {};
if (!commandName) return;
@ -109,12 +114,13 @@ export default class ButtonView extends View {
command = commands.create(commandName);
}
if (model.get('active')) {
!fromCollection && model.collection?.deactivateAll(context, model);
if (model.active) {
!fromCollection && (model.collection as Buttons)?.deactivateAll(context, model);
model.set('active', true, { silent: true }).trigger('checkActive');
!fromListen && commands.runCommand(command, { ...options, sender: model });
// Disable button if the command has no stop method
//@ts-ignore
command.noStop && model.set('active', false);
} else {
$el.removeClass(activeCls);
@ -124,7 +130,7 @@ export default class ButtonView extends View {
updateDisable() {
const { disableCls, model } = this;
const disable = model.get('disable');
const disable = model.disable;
this.$el[disable ? 'addClass' : 'removeClass'](disableCls);
}
@ -135,7 +141,7 @@ export default class ButtonView extends View {
* */
checkActive() {
const { model, $el, activeCls } = this;
model.get('active') ? $el.addClass(activeCls) : $el.removeClass(activeCls);
model.active ? $el.addClass(activeCls) : $el.removeClass(activeCls);
}
/**
@ -144,31 +150,31 @@ export default class ButtonView extends View {
*
* @return void
* */
clicked(e) {
clicked(e: Event) {
const { model } = this;
if (model.get('bntsVis') || model.get('disable') || !model.get('command')) return;
if (model.get('bntsVis') || model.disable || !model.command) return;
this.toggleActive();
}
toggleActive() {
private toggleActive() {
const { model, em } = this;
const { active, togglable } = model.attributes;
const { active, togglable } = model;
if (active && !togglable) return;
model.set('active', !active);
model.active = !active;
// If the stop is requested
if (active) {
if (model.get('runDefaultCommand')) em.runDefault();
if (model.runDefaultCommand) em.runDefault();
} else {
if (model.get('stopDefaultCommand')) em.stopDefault();
if (model.stopDefaultCommand) em.stopDefault();
}
}
render() {
public render() {
const { model } = this;
const label = model.get('label');
const { $el } = this;

28
src/panels/view/ButtonsView.js → src/panels/view/ButtonsView.ts

@ -1,13 +1,12 @@
import { result } from 'underscore';
import { View } from '../../common';
import { View } from '../../abstract';
import Button from '../model/Button';
import Buttons from '../model/Buttons';
import ButtonView from './ButtonView';
export default class ButtonsView extends View {
initialize(o) {
this.opt = o || {};
this.config = this.opt.config || {};
this.pfx = this.config.stylePrefix || '';
this.parentM = this.opt.parentM || null;
export default class ButtonsView extends View<Buttons> {
constructor(collection: Buttons) {
super({ collection });
this.listenTo(this.collection, 'add', this.addTo);
this.listenTo(this.collection, 'reset remove', this.render);
this.className = this.pfx + 'buttons';
@ -19,7 +18,7 @@ export default class ButtonsView extends View {
*
* @return Object
* */
addTo(model) {
private addTo(model: Button) {
this.addToCollection(model);
}
@ -30,15 +29,12 @@ export default class ButtonsView extends View {
*
* @return Object Object created
* */
addToCollection(model, fragmentEl) {
private addToCollection(model: Button, fragmentEl?: DocumentFragment) {
const fragment = fragmentEl || null;
const viewObject = ButtonView;
const el = model.get('el');
const view = new viewObject({
const view = new ButtonView({
el,
model,
config: this.config,
parentM: this.parentM,
});
const rendered = view.render().el;
@ -51,13 +47,11 @@ export default class ButtonsView extends View {
return rendered;
}
render() {
public render() {
var fragment = document.createDocumentFragment();
this.$el.empty();
this.collection.each(function (model) {
this.addToCollection(model, fragment);
}, this);
this.collection.each(model => this.addToCollection(model, fragment));
this.$el.append(fragment);
this.$el.attr('class', result(this, 'className'));

29
src/panels/view/PanelView.js → src/panels/view/PanelView.ts

@ -1,14 +1,10 @@
import { View } from '../../common';
import { View } from '../../abstract';
import Panel from '../model/Panel';
import ButtonsView from './ButtonsView';
export default class PanelView extends View {
initialize(o) {
const config = o.config || {};
const model = this.model;
this.config = config;
this.pfx = config.stylePrefix || '';
this.ppfx = config.pStylePrefix || '';
this.buttons = model.get('buttons');
export default class PanelView extends View<Panel> {
constructor(model: Panel) {
super({ model, el: model.get('el') });
this.className = this.pfx + 'panel';
this.id = this.pfx + model.get('id');
this.listenTo(model, 'change:appendContent', this.appendContent);
@ -39,12 +35,13 @@ export default class PanelView extends View {
this.$el.removeClass(`${this.ppfx}hidden`);
}
//@ts-ignore
attributes() {
return this.model.get('attributes');
}
initResize() {
const em = this.config.em;
const em = this.em;
const editor = em ? em.get('Editor') : '';
const resizable = this.model.get('resizable');
@ -85,7 +82,7 @@ export default class PanelView extends View {
onEnd() {
em && em.trigger('change:canvasOffset');
},
posFetcher: (el, { target }) => {
posFetcher: (el: HTMLElement, { target }: any) => {
const style = el.style;
const config = resizer.getConfig();
const keyWidth = config.keyWidth;
@ -111,6 +108,7 @@ export default class PanelView extends View {
}
render() {
const { buttons } = this.model;
const $el = this.$el;
const ppfx = this.ppfx;
const cls = `${this.className} ${this.id} ${ppfx}one-bg ${ppfx}two-color`;
@ -118,12 +116,9 @@ export default class PanelView extends View {
this.toggleVisible();
if (this.buttons.length) {
var buttons = new ButtonsView({
collection: this.buttons,
config: this.config,
});
$el.append(buttons.render().el);
if (buttons.length) {
var buttonsView = new ButtonsView(buttons);
$el.append(buttonsView.render().el);
}
$el.append(this.model.get('content'));

33
src/panels/view/PanelsView.js → src/panels/view/PanelsView.ts

@ -1,19 +1,18 @@
import { View } from '../../common';
import { View } from '../../abstract';
import Panel from '../model/Panel';
import Panels from '../model/Panels';
import PanelView from './PanelView';
export default class PanelsView extends View {
initialize(o) {
this.opt = o || {};
this.config = this.opt.config || {};
this.pfx = this.config.stylePrefix || '';
const items = this.collection;
this.listenTo(items, 'add', this.addTo);
this.listenTo(items, 'reset', this.render);
this.listenTo(items, 'remove', this.onRemove);
export default class PanelsView extends View<Panels> {
constructor(target: Panels) {
super({ collection: target });
this.listenTo(target, 'add', this.addTo);
this.listenTo(target, 'reset', this.render);
this.listenTo(target, 'remove', this.onRemove);
this.className = this.pfx + 'panels';
}
onRemove(model) {
private onRemove(model: Panel) {
const view = model.view;
view && view.remove();
}
@ -25,7 +24,7 @@ export default class PanelsView extends View {
* @return Object
* @private
* */
addTo(model) {
private addTo(model: Panel) {
this.addToCollection(model);
}
@ -38,15 +37,11 @@ export default class PanelsView extends View {
* @return Object Object created
* @private
* */
addToCollection(model, fragmentEl) {
private addToCollection(model: Panel, fragmentEl?: DocumentFragment) {
const fragment = fragmentEl || null;
const config = this.config;
const el = model.get('el');
const view = new PanelView({
el,
model,
config,
});
const view = new PanelView(model);
const rendered = view.render().el;
const appendTo = model.get('appendTo');
@ -67,7 +62,7 @@ export default class PanelsView extends View {
return rendered;
}
render() {
public render() {
const $el = this.$el;
const frag = document.createDocumentFragment();
$el.empty();

4
test/specs/panels/view/ButtonsView.js

@ -11,9 +11,7 @@ describe('ButtonsView', () => {
beforeEach(() => {
em = new Editor({});
model = new Buttons(em.Panels, []);
view = new ButtonsView({
collection: model,
});
view = new ButtonsView(model);
document.body.innerHTML = '<div id="fixtures"></div>';
fixtures = document.body.querySelector('#fixtures');
fixtures.appendChild(view.render().el);

21
test/specs/panels/view/PanelView.js

@ -1,16 +1,17 @@
import PanelView from 'panels/view/PanelView';
import Panel from 'panels/model/Panel';
import Editor from 'editor';
describe('PanelView', () => {
var fixtures;
var em;
var model;
var view;
beforeEach(() => {
model = new Panel();
view = new PanelView({
model,
});
em = new Editor();
model = new Panel(em.Panels);
view = new PanelView(model);
document.body.innerHTML = '<div id="fixtures"></div>';
fixtures = document.body.querySelector('#fixtures');
fixtures.appendChild(view.render().el);
@ -38,16 +39,16 @@ describe('PanelView', () => {
});
test('Hide panel', () => {
expect(view.$el.hasClass('hidden')).toBeFalsy();
expect(view.$el.hasClass('gjs-hidden')).toBeFalsy();
model.set('visible', false);
expect(view.$el.hasClass('hidden')).toBeTruthy();
expect(view.$el.hasClass('gjs-hidden')).toBeTruthy();
});
test('Show panel', () => {
model.set('visible', false);
expect(view.$el.hasClass('hidden')).toBeTruthy();
expect(view.$el.hasClass('gjs-hidden')).toBeTruthy();
model.set('visible', true);
expect(view.$el.hasClass('hidden')).toBeFalsy();
expect(view.$el.hasClass('gjs-hidden')).toBeFalsy();
});
describe('Init with options', () => {
@ -55,9 +56,7 @@ describe('PanelView', () => {
model = new Panel({
buttons: [{}],
});
view = new PanelView({
model,
});
view = new PanelView(model);
document.body.innerHTML = '<div id="fixtures"></div>';
fixtures = document.body.querySelector('#fixtures');
fixtures.appendChild(view.render().el);

10
test/specs/panels/view/PanelsView.js

@ -1,17 +1,17 @@
import PanelsView from 'panels/view/PanelsView';
import Panels from 'panels/model/Panels';
import Editor from 'editor';
describe('PanelsView', () => {
var fixtures;
var $fixture;
var em;
var model;
var view;
beforeEach(() => {
model = new Panels([]);
view = new PanelsView({
collection: model,
});
em = new Editor({});
model = new Panels(em.Panels);
view = new PanelsView(model);
document.body.innerHTML = '<div id="fixtures"></div>';
fixtures = document.body.querySelector('#fixtures');
fixtures.appendChild(view.render().el);

Loading…
Cancel
Save