mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-14 03:07:57 +01:00
Merged develop into fix/import-freemind
This commit is contained in:
commit
31dc83d30b
@ -35,7 +35,7 @@ const mapId = 'welcome';
|
|||||||
const options: EditorOptions = {
|
const options: EditorOptions = {
|
||||||
zoom: 0.8,
|
zoom: 0.8,
|
||||||
locked: false,
|
locked: false,
|
||||||
mapTitle: "Develop Mindnap",
|
mapTitle: "Develop WiseMapping",
|
||||||
mode: 'edition-owner',
|
mode: 'edition-owner',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
enableKeyboardEvents: true
|
enableKeyboardEvents: true
|
||||||
|
@ -36,7 +36,7 @@ const persistence = new LocalStorageManager('samples/{id}.wxml', false);
|
|||||||
const options: EditorOptions = {
|
const options: EditorOptions = {
|
||||||
zoom: 0.8,
|
zoom: 0.8,
|
||||||
locked: false,
|
locked: false,
|
||||||
mapTitle: "Develop Mindnap",
|
mapTitle: "Develop WiseMapping",
|
||||||
mode: 'viewonly',
|
mode: 'viewonly',
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
enableKeyboardEvents: true
|
enableKeyboardEvents: true
|
||||||
|
@ -21,12 +21,19 @@ import Keyboard from './Keyboard';
|
|||||||
import { Designer } from '..';
|
import { Designer } from '..';
|
||||||
import Topic from './Topic';
|
import Topic from './Topic';
|
||||||
|
|
||||||
|
import initHotKeyPluggin from '../../../../libraries/jquery.hotkeys';
|
||||||
|
|
||||||
|
// Provides dispatcher of keyevents by key...
|
||||||
|
initHotKeyPluggin($);
|
||||||
|
|
||||||
export type EventCallback = (event?: Event) => void;
|
export type EventCallback = (event?: Event) => void;
|
||||||
class DesignerKeyboard extends Keyboard {
|
class DesignerKeyboard extends Keyboard {
|
||||||
// eslint-disable-next-line no-use-before-define
|
// eslint-disable-next-line no-use-before-define
|
||||||
static _instance: DesignerKeyboard;
|
private static _instance: DesignerKeyboard;
|
||||||
|
|
||||||
static _disabled: boolean;
|
private static _disabled: boolean;
|
||||||
|
|
||||||
|
private static excludeFromEditor = ['Enter', 'CapsLock', 'Escape', 'F1', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12'];
|
||||||
|
|
||||||
constructor(designer: Designer) {
|
constructor(designer: Designer) {
|
||||||
super();
|
super();
|
||||||
@ -35,173 +42,61 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addShortcut(shortcuts: string[] | string, callback: EventCallback): void {
|
addShortcut(shortcuts: string[] | string, callback: EventCallback): void {
|
||||||
super.addShortcut(shortcuts, (e: Event) => {
|
super.addShortcut(shortcuts, () => {
|
||||||
if (DesignerKeyboard.isDisabled()) {
|
if (DesignerKeyboard.isDisabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
callback(e);
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _registerEvents(designer: Designer) {
|
private _registerEvents(designer: Designer) {
|
||||||
// Try with the keyboard ..
|
// Try with the keyboard ..
|
||||||
const model = designer.getModel();
|
const model = designer.getModel();
|
||||||
this.addShortcut(
|
this.addShortcut(['backspace', 'del'], () => { designer.deleteSelectedEntities(); });
|
||||||
['backspace'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
designer.deleteSelectedEntities();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['space'], (event: Event) => {
|
|
||||||
designer.shrinkSelectedBranch();
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['f2'], (event: Event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
const node = model.selectedTopic();
|
|
||||||
if (node) {
|
|
||||||
node.showTextEditor(node.getText());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['del'], (event: Event) => {
|
|
||||||
designer.deleteSelectedEntities();
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['enter'], () => {
|
|
||||||
designer.createSiblingForSelectedNode();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['insert'], (event: Event) => {
|
|
||||||
designer.createChildForSelectedNode();
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['tab'], (eventevent: Event) => {
|
|
||||||
designer.createChildForSelectedNode();
|
|
||||||
eventevent.preventDefault();
|
|
||||||
eventevent.stopPropagation();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['meta+enter'], (eventevent: Event) => {
|
|
||||||
eventevent.preventDefault();
|
|
||||||
eventevent.stopPropagation();
|
|
||||||
designer.createChildForSelectedNode();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+z', 'meta+z'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
designer.undo();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+c', 'meta+c'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
designer.copyToClipboard();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+l', 'meta+l'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
designer.addLink();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+k', 'meta+k'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
designer.addNote();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+v', 'meta+v'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
designer.pasteClipboard();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+shift+z', 'meta+shift+z', 'ctrl+y', 'meta+y'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
designer.redo();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+a', 'meta+a'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
designer.selectAll();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+b', 'meta+b'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
designer.changeFontWeight();
|
this.addShortcut('space', () => { designer.shrinkSelectedBranch(); });
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+s', 'meta+s'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
$(document).find('#save').trigger('click');
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['ctrl+i', 'meta+i'], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
designer.changeFontStyle();
|
this.addShortcut('f2', () => {
|
||||||
},
|
const node = model.selectedTopic();
|
||||||
);
|
if (node) {
|
||||||
this.addShortcut(
|
node.showTextEditor(node.getText());
|
||||||
['ctrl+shift+a', 'meta+shift+a'], (event: Event) => {
|
}
|
||||||
event.preventDefault();
|
});
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
designer.deselectAll();
|
this.addShortcut(['insert', 'tab', 'meta+enter'], () => { designer.createChildForSelectedNode(); });
|
||||||
},
|
|
||||||
);
|
|
||||||
this.addShortcut(
|
|
||||||
['meta+=', 'ctrl+='], (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
designer.zoomIn();
|
this.addShortcut('enter', () => { designer.createSiblingForSelectedNode(); });
|
||||||
},
|
|
||||||
);
|
this.addShortcut(['ctrl+z', 'meta+z'], () => { designer.undo(); });
|
||||||
this.addShortcut(
|
|
||||||
['meta+-', 'ctrl+-'], (event: Event) => {
|
this.addShortcut(['ctrl+shift+z', 'meta+shift+z'], () => { designer.redo(); });
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
this.addShortcut(['ctrl+c', 'meta+c'], () => { designer.copyToClipboard(); });
|
||||||
|
|
||||||
|
this.addShortcut(['ctrl+l', 'meta+l'], () => { designer.addLink(); });
|
||||||
|
|
||||||
|
this.addShortcut(['ctrl+k', 'meta+k'], () => { designer.addNote(); });
|
||||||
|
|
||||||
|
this.addShortcut(['ctrl+v', 'meta+v'], () => { designer.pasteClipboard(); });
|
||||||
|
|
||||||
|
this.addShortcut(['ctrl+a', 'meta+a'], () => { designer.selectAll(); });
|
||||||
|
|
||||||
|
this.addShortcut(['ctrl+b', 'meta+b'], () => { designer.changeFontWeight(); });
|
||||||
|
|
||||||
|
this.addShortcut(['ctrl+s', 'meta+s'], () => { $(document).find('#save').trigger('click'); });
|
||||||
|
|
||||||
|
this.addShortcut(['ctrl+i', 'meta+i'], () => { designer.changeFontStyle(); });
|
||||||
|
|
||||||
|
this.addShortcut(['ctrl+shift+a', 'meta+shift+a'], () => { designer.deselectAll(); });
|
||||||
|
|
||||||
|
this.addShortcut(['meta+=', 'ctrl+='], () => { designer.zoomIn(); });
|
||||||
|
|
||||||
|
this.addShortcut(['meta+-', 'ctrl+-'], () => { designer.zoomOut(); });
|
||||||
|
|
||||||
designer.zoomOut();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const me = this;
|
const me = this;
|
||||||
this.addShortcut(
|
this.addShortcut(
|
||||||
'right', (event: Event) => {
|
'right', () => {
|
||||||
const node = model.selectedTopic();
|
const node = model.selectedTopic();
|
||||||
if (node) {
|
if (node) {
|
||||||
if (node.isCentralTopic()) {
|
if (node.isCentralTopic()) {
|
||||||
@ -215,12 +110,11 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
const centralTopic = model.getCentralTopic();
|
const centralTopic = model.getCentralTopic();
|
||||||
me._goToNode(designer, centralTopic);
|
me._goToNode(designer, centralTopic);
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.addShortcut(
|
this.addShortcut(
|
||||||
'left', (event: Event) => {
|
'left', () => {
|
||||||
const node = model.selectedTopic();
|
const node = model.selectedTopic();
|
||||||
if (node) {
|
if (node) {
|
||||||
if (node.isCentralTopic()) {
|
if (node.isCentralTopic()) {
|
||||||
@ -234,12 +128,11 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
const centralTopic = model.getCentralTopic();
|
const centralTopic = model.getCentralTopic();
|
||||||
me._goToNode(designer, centralTopic);
|
me._goToNode(designer, centralTopic);
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.addShortcut(
|
this.addShortcut(
|
||||||
'up', (event: Event) => {
|
'up', () => {
|
||||||
const node = model.selectedTopic();
|
const node = model.selectedTopic();
|
||||||
if (node) {
|
if (node) {
|
||||||
if (!node.isCentralTopic()) {
|
if (!node.isCentralTopic()) {
|
||||||
@ -249,12 +142,10 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
const centralTopic = model.getCentralTopic();
|
const centralTopic = model.getCentralTopic();
|
||||||
me._goToNode(designer, centralTopic);
|
me._goToNode(designer, centralTopic);
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.addShortcut(
|
this.addShortcut(
|
||||||
'down', (event: Event) => {
|
'down', () => {
|
||||||
const node = model.selectedTopic();
|
const node = model.selectedTopic();
|
||||||
if (node) {
|
if (node) {
|
||||||
if (!node.isCentralTopic()) {
|
if (!node.isCentralTopic()) {
|
||||||
@ -264,42 +155,26 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
const centralTopic = model.getCentralTopic();
|
const centralTopic = model.getCentralTopic();
|
||||||
me._goToNode(designer, centralTopic);
|
me._goToNode(designer, centralTopic);
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const excludes = ['esc', 'escape', 'f1', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11', 'f12'];
|
|
||||||
|
|
||||||
$(document).on('keypress', (event) => {
|
$(document).on('keypress', (event) => {
|
||||||
let keyCode: number;
|
// Needs to be ignored ?
|
||||||
|
if (DesignerKeyboard.isDisabled() || DesignerKeyboard.excludeFromEditor.includes(event.code)) {
|
||||||
if (DesignerKeyboard.isDisabled()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Firefox doesn't skip special keys for keypress event...
|
|
||||||
if (event.key && excludes.includes(event.key.toLowerCase())) {
|
// Is a modifier ?
|
||||||
|
if (event.ctrlKey || event.altKey || event.metaKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Sometimes Firefox doesn't contain keyCode value
|
|
||||||
if (event.key && event.keyCode === 0) {
|
|
||||||
keyCode = event.charCode;
|
|
||||||
} else {
|
|
||||||
keyCode = event.keyCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// If a node is selected, open the editor ...
|
||||||
const jq: any = $;
|
const topic = designer.getModel().selectedTopic();
|
||||||
const specialKey = jq.hotkeys.specialKeys[keyCode];
|
if (topic) {
|
||||||
if (['enter', 'capslock'].indexOf(specialKey) === -1 && !jq.hotkeys.shiftNums[keyCode]) {
|
event.stopPropagation();
|
||||||
const nodes = designer.getModel().filterSelectedTopics();
|
event.preventDefault();
|
||||||
if (nodes.length > 0) {
|
topic.showTextEditor(event.key);
|
||||||
// If a modifier is press, the key selected must be ignored.
|
|
||||||
if (event.ctrlKey || event.altKey || event.metaKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nodes[0].showTextEditor('');
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -405,75 +280,17 @@ class DesignerKeyboard extends Keyboard {
|
|||||||
this._disabled = false;
|
this._disabled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
static pause = function pause() {
|
static pause() {
|
||||||
this._disabled = true;
|
this._disabled = true;
|
||||||
};
|
}
|
||||||
|
|
||||||
static resume = function resume() {
|
static resume() {
|
||||||
this._disabled = false;
|
this._disabled = false;
|
||||||
};
|
}
|
||||||
|
|
||||||
static isDisabled = function isDisabled() {
|
static isDisabled() {
|
||||||
return this._disabled;
|
return this._disabled;
|
||||||
};
|
}
|
||||||
|
|
||||||
static specialKeys = {
|
|
||||||
8: 'backspace',
|
|
||||||
9: 'tab',
|
|
||||||
10: 'return',
|
|
||||||
13: 'enter',
|
|
||||||
16: 'shift',
|
|
||||||
17: 'ctrl',
|
|
||||||
18: 'alt',
|
|
||||||
19: 'pause',
|
|
||||||
20: 'capslock',
|
|
||||||
27: 'esc',
|
|
||||||
32: 'space',
|
|
||||||
33: 'pageup',
|
|
||||||
34: 'pagedown',
|
|
||||||
35: 'end',
|
|
||||||
36: 'home',
|
|
||||||
37: 'left',
|
|
||||||
38: 'up',
|
|
||||||
39: 'right',
|
|
||||||
40: 'down',
|
|
||||||
45: 'insert',
|
|
||||||
46: 'del',
|
|
||||||
96: '0',
|
|
||||||
97: '1',
|
|
||||||
98: '2',
|
|
||||||
99: '3',
|
|
||||||
100: '4',
|
|
||||||
101: '5',
|
|
||||||
102: '6',
|
|
||||||
103: '7',
|
|
||||||
104: '8',
|
|
||||||
105: '9',
|
|
||||||
106: '*',
|
|
||||||
107: '+',
|
|
||||||
109: '-',
|
|
||||||
110: '.',
|
|
||||||
111: '/',
|
|
||||||
112: 'f1',
|
|
||||||
113: 'f2',
|
|
||||||
114: 'f3',
|
|
||||||
115: 'f4',
|
|
||||||
116: 'f5',
|
|
||||||
117: 'f6',
|
|
||||||
118: 'f7',
|
|
||||||
119: 'f8',
|
|
||||||
120: 'f9',
|
|
||||||
121: 'f10',
|
|
||||||
122: 'f11',
|
|
||||||
123: 'f12',
|
|
||||||
144: 'numlock',
|
|
||||||
145: 'scroll',
|
|
||||||
186: ';',
|
|
||||||
191: '/',
|
|
||||||
220: '\\',
|
|
||||||
222: "'",
|
|
||||||
224: 'meta',
|
|
||||||
};
|
|
||||||
|
|
||||||
static getInstance() {
|
static getInstance() {
|
||||||
return this._instance;
|
return this._instance;
|
||||||
|
@ -59,27 +59,15 @@ class DesignerModel extends Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filterSelectedTopics(): Topic[] {
|
filterSelectedTopics(): Topic[] {
|
||||||
const result: Topic[] = [];
|
return this._topics.filter((t) => t.isOnFocus());
|
||||||
for (let i = 0; i < this._topics.length; i++) {
|
|
||||||
if (this._topics[i].isOnFocus()) {
|
|
||||||
result.push(this._topics[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filterSelectedRelationships(): Relationship[] {
|
filterSelectedRelationships(): Relationship[] {
|
||||||
const result:Relationship[] = [];
|
return this._relationships.filter((r) => r.isOnFocus());
|
||||||
for (let i = 0; i < this._relationships.length; i++) {
|
|
||||||
if (this._relationships[i].isOnFocus()) {
|
|
||||||
result.push(this._relationships[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getEntities(): (Relationship | Topic)[] {
|
getEntities(): (Relationship | Topic)[] {
|
||||||
let result:(Relationship|Topic)[] = [];
|
let result: (Relationship | Topic)[] = [];
|
||||||
result = result.concat(this._topics);
|
result = result.concat(this._topics);
|
||||||
result = result.concat(this._relationships);
|
result = result.concat(this._relationships);
|
||||||
return result;
|
return result;
|
||||||
@ -133,15 +121,7 @@ class DesignerModel extends Events {
|
|||||||
}
|
}
|
||||||
|
|
||||||
findTopicById(id: number): Topic | undefined {
|
findTopicById(id: number): Topic | undefined {
|
||||||
let result: Topic | undefined;
|
return this._topics.find((t) => t.getId() === id);
|
||||||
for (let i = 0; i < this._topics.length; i++) {
|
|
||||||
const topic = this._topics[i];
|
|
||||||
if (topic.getId() === id) {
|
|
||||||
result = topic;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ ImageIcon.prototype.ICON_FAMILIES = [{
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'meetapps',
|
id: 'meetapps',
|
||||||
icons: ['meetapps_slack', 'meetapps_google-meet', 'meetapps_whatapp', 'meetapps_ms-teams', 'meetapps_zoom', 'meeetapps_facebook-messenger'],
|
icons: ['meetapps_slack', 'meetapps_google-meet', 'meetapps_whatapp', 'meetapps_ms-teams', 'meetapps_zoom', 'meetapps_facebook-messenger'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'appsgoogle',
|
id: 'appsgoogle',
|
||||||
|
@ -16,12 +16,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
import initHotKeyPluggin from '../../../../libraries/jquery.hotkeys';
|
||||||
|
|
||||||
|
// Provides dispatcher of keyevents by key...
|
||||||
|
initHotKeyPluggin($);
|
||||||
|
|
||||||
class Keyboard {
|
class Keyboard {
|
||||||
addShortcut(shortcuts: string[] | string, callback) {
|
addShortcut(shortcuts: string[] | string, callback: () => void) {
|
||||||
const shortcutsArray = Array.isArray(shortcuts) ? shortcuts : [shortcuts];
|
const shortcutsArray = Array.isArray(shortcuts) ? shortcuts : [shortcuts];
|
||||||
shortcutsArray.forEach((shortcut) => {
|
shortcutsArray.forEach((shortcut) => {
|
||||||
$(document).bind('keydown', shortcut, callback);
|
$(document).bind('keydown', shortcut,
|
||||||
|
(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
callback();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,10 @@
|
|||||||
import { $defined } from '@wisemapping/core-js';
|
import { $defined } from '@wisemapping/core-js';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
import initHotKeyPluggin from '../../../../libraries/jquery.hotkeys';
|
|
||||||
import Events from './Events';
|
import Events from './Events';
|
||||||
import ActionDispatcher from './ActionDispatcher';
|
import ActionDispatcher from './ActionDispatcher';
|
||||||
import Topic from './Topic';
|
import Topic from './Topic';
|
||||||
|
|
||||||
initHotKeyPluggin($);
|
|
||||||
|
|
||||||
class MultilineTextEditor extends Events {
|
class MultilineTextEditor extends Events {
|
||||||
private _topic: Topic;
|
private _topic: Topic;
|
||||||
|
|
||||||
@ -61,12 +58,11 @@ class MultilineTextEditor extends Events {
|
|||||||
private _registerEvents(containerElem: JQuery) {
|
private _registerEvents(containerElem: JQuery) {
|
||||||
const textareaElem = this._getTextareaElem();
|
const textareaElem = this._getTextareaElem();
|
||||||
textareaElem.on('keydown', (event) => {
|
textareaElem.on('keydown', (event) => {
|
||||||
const j: any = $;
|
switch (event.code) {
|
||||||
switch (j.hotkeys.specialKeys[event.keyCode]) {
|
case 'Escape':
|
||||||
case 'esc':
|
|
||||||
this.close(false);
|
this.close(false);
|
||||||
break;
|
break;
|
||||||
case 'enter': {
|
case 'Enter': {
|
||||||
if (event.metaKey || event.ctrlKey) {
|
if (event.metaKey || event.ctrlKey) {
|
||||||
// Add return ...
|
// Add return ...
|
||||||
const text = this._getTextAreaText();
|
const text = this._getTextAreaText();
|
||||||
|
@ -16,7 +16,7 @@ const DeleteDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
const [error, setError] = React.useState<ErrorInfo>();
|
const [error, setError] = React.useState<ErrorInfo>();
|
||||||
|
|
||||||
const mutation = useMutation((id: number) => client.deleteMap(id), {
|
const mutation = useMutation((id: number) => client.deleteMap(id), {
|
||||||
onSuccess: () => handleOnMutationSuccess(onClose, queryClient),
|
onSuccess: () => handleOnMutationSuccess(() => onClose(true), queryClient),
|
||||||
onError: (error: ErrorInfo) => {
|
onError: (error: ErrorInfo) => {
|
||||||
setError(error);
|
setError(error);
|
||||||
},
|
},
|
||||||
@ -31,7 +31,7 @@ const DeleteDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { map } = fetchMapById(mapId)
|
const { map } = fetchMapById(mapId)
|
||||||
const alertTitle=`${intl.formatMessage({ id: 'action.delete-title', defaultMessage: 'Delete' })} ${map?.title}`;
|
const alertTitle = `${intl.formatMessage({ id: 'action.delete-title', defaultMessage: 'Delete' })} ${map?.title}`;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<BaseDialog
|
<BaseDialog
|
||||||
|
@ -18,7 +18,7 @@ const DeleteMultiselectDialog = ({
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const mutation = useMutation((ids: number[]) => client.deleteMaps(ids), {
|
const mutation = useMutation((ids: number[]) => client.deleteMaps(ids), {
|
||||||
onSuccess: () => handleOnMutationSuccess(onClose, queryClient),
|
onSuccess: () => handleOnMutationSuccess(() => onClose(true), queryClient),
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error(`Unexpected error ${error}`);
|
console.error(`Unexpected error ${error}`);
|
||||||
},
|
},
|
||||||
|
@ -22,13 +22,13 @@ export type BasicMapInfo = {
|
|||||||
type ActionDialogProps = {
|
type ActionDialogProps = {
|
||||||
action?: ActionType;
|
action?: ActionType;
|
||||||
mapsId: number[];
|
mapsId: number[];
|
||||||
onClose: () => void;
|
onClose: (success?: boolean) => void;
|
||||||
fromEditor: boolean;
|
fromEditor: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ActionDispatcher = ({ mapsId, action, onClose, fromEditor }: ActionDialogProps): React.ReactElement => {
|
const ActionDispatcher = ({ mapsId, action, onClose, fromEditor }: ActionDialogProps): React.ReactElement => {
|
||||||
const handleOnClose = (): void => {
|
const handleOnClose = (success?: boolean): void => {
|
||||||
onClose();
|
onClose(success);
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
@ -78,12 +78,12 @@ export const handleOnMutationSuccess = (onClose: () => void, queryClient: QueryC
|
|||||||
|
|
||||||
export type SimpleDialogProps = {
|
export type SimpleDialogProps = {
|
||||||
mapId: number;
|
mapId: number;
|
||||||
onClose: () => void;
|
onClose: (success?: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MultiDialogProps = {
|
export type MultiDialogProps = {
|
||||||
mapsId: number[];
|
mapsId: number[];
|
||||||
onClose: () => void;
|
onClose: (success?: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ActionDispatcher;
|
export default ActionDispatcher;
|
||||||
|
@ -56,11 +56,18 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const splitEmail = (emails: string): string[] => {
|
||||||
|
return emails.split(/,|;/)
|
||||||
|
.map(e => e.trim().replace(/\s/g, ''))
|
||||||
|
.filter(e => e.trim().length > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const addMutation = useMutation(
|
const addMutation = useMutation(
|
||||||
(model: ShareModel) => {
|
(model: ShareModel) => {
|
||||||
const emails = model.emails.split(',');
|
const emails = splitEmail(model.emails);
|
||||||
const permissions = emails.map((email: string) => {
|
const permissions = emails.map((email: string) => {
|
||||||
return { email: email.replace(/\s/g, ''), role: model.role };
|
return { email: email, role: model.role };
|
||||||
});
|
});
|
||||||
return client.addMapPermissions(mapId, model.message, permissions);
|
return client.addMapPermissions(mapId, model.message, permissions);
|
||||||
},
|
},
|
||||||
@ -114,7 +121,9 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
};
|
};
|
||||||
|
|
||||||
// very basic email validation, just make sure the basic syntax is fine
|
// very basic email validation, just make sure the basic syntax is fine
|
||||||
const isValid = model.emails.split(',').every(str => /\S+@\S+\.\S+/.test((str || '').trim()));
|
const isValid = splitEmail(model.emails)
|
||||||
|
.every(str => /\S+@\S+\.\S+/.test((str || '')
|
||||||
|
.trim()));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -59,9 +59,9 @@ function getComparator<Key extends keyof any>(
|
|||||||
order: Order,
|
order: Order,
|
||||||
orderBy: Key
|
orderBy: Key
|
||||||
): (
|
): (
|
||||||
a: { [key in Key]: number | string | boolean | Label[] | undefined },
|
a: { [key in Key]: number | string | boolean | Label[] | undefined },
|
||||||
b: { [key in Key]: number | string | Label[] | boolean }
|
b: { [key in Key]: number | string | Label[] | boolean }
|
||||||
) => number {
|
) => number {
|
||||||
return order === 'desc'
|
return order === 'desc'
|
||||||
? (a, b) => descendingComparator(a, b, orderBy)
|
? (a, b) => descendingComparator(a, b, orderBy)
|
||||||
: (a, b) => -descendingComparator(a, b, orderBy);
|
: (a, b) => -descendingComparator(a, b, orderBy);
|
||||||
@ -240,19 +240,19 @@ export type ChangeLabelMutationFunctionParam = { maps: MapInfo[]; label: Label;
|
|||||||
|
|
||||||
export const getChangeLabelMutationFunction =
|
export const getChangeLabelMutationFunction =
|
||||||
(client: Client) =>
|
(client: Client) =>
|
||||||
async ({ maps, label, checked }: ChangeLabelMutationFunctionParam): Promise<void> => {
|
async ({ maps, label, checked }: ChangeLabelMutationFunctionParam): Promise<void> => {
|
||||||
if (!label.id) {
|
if (!label.id) {
|
||||||
label.id = await client.createLabel(label.title, label.color);
|
label.id = await client.createLabel(label.title, label.color);
|
||||||
}
|
}
|
||||||
if (checked) {
|
if (checked) {
|
||||||
const toAdd = maps.filter((m) => !m.labels.find((l) => l.id === label.id));
|
const toAdd = maps.filter((m) => !m.labels.find((l) => l.id === label.id));
|
||||||
await Promise.all(toAdd.map((m) => client.addLabelToMap(label.id, m.id)));
|
await Promise.all(toAdd.map((m) => client.addLabelToMap(label.id, m.id)));
|
||||||
} else {
|
} else {
|
||||||
const toRemove = maps.filter((m) => m.labels.find((l) => l.id === label.id));
|
const toRemove = maps.filter((m) => m.labels.find((l) => l.id === label.id));
|
||||||
await Promise.all(toRemove.map((m) => client.deleteLabelFromMap(label.id, m.id)));
|
await Promise.all(toRemove.map((m) => client.deleteLabelFromMap(label.id, m.id)));
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MapsList = (props: MapsListProps): React.ReactElement => {
|
export const MapsList = (props: MapsListProps): React.ReactElement => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
@ -698,7 +698,14 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
|
|
||||||
<ActionDispatcher
|
<ActionDispatcher
|
||||||
action={activeDialog?.actionType}
|
action={activeDialog?.actionType}
|
||||||
onClose={() => setActiveDialog(undefined)}
|
onClose={(success) => {
|
||||||
|
setActiveDialog(undefined);
|
||||||
|
|
||||||
|
// If it was a success action, reset the selection list ...
|
||||||
|
if (success) {
|
||||||
|
setSelected([]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
mapsId={activeDialog ? activeDialog.mapsId : []}
|
mapsId={activeDialog ? activeDialog.mapsId : []}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user