Improve copy paste support.

This commit is contained in:
Paulo Gustavo Veiga 2023-01-14 19:31:01 -08:00
parent 57934487f7
commit e54d4ff543
26 changed files with 120 additions and 75 deletions

View File

@ -0,0 +1,19 @@
/// <reference types="cypress" />
describe('Edit Topic', () => {
beforeEach(() => {
// Remove storage for autosave ...
cy.visit('/editor.html');
cy.waitEditorLoaded();
cy.get('[test-id=2]').click();
});
it('Copy and Paste', () => {
cy.get(`[aria-label="Topic Style"]`).first().trigger('mouseover');
cy.get('body').type('{meta}c');
// Copy & Paste require permissions. More reseach needed.
// cy.get('body').type('{meta}v');
// cy.get('[test-id=50]').click();
// cy.matchImageSnapshot('copyandpaste');
});
});

View File

@ -56,6 +56,7 @@ import FeatureType from './model/FeatureType';
import WidgetManager from './WidgetManager'; import WidgetManager from './WidgetManager';
import { TopicShapeType } from './model/INodeModel'; import { TopicShapeType } from './model/INodeModel';
import { LineType } from './ConnectionLine'; import { LineType } from './ConnectionLine';
import XMLSerializerFactory from './persistence/XMLSerializerFactory';
class Designer extends Events { class Designer extends Events {
private _mindmap: Mindmap | null; private _mindmap: Mindmap | null;
@ -74,8 +75,6 @@ class Designer extends Events {
private _relPivot: RelationshipPivot; private _relPivot: RelationshipPivot;
private _clipboard: NodeModel[];
private _cleanScreen!: () => void; private _cleanScreen!: () => void;
constructor(options: DesignerOptions, divElement: JQuery) { constructor(options: DesignerOptions, divElement: JQuery) {
@ -129,7 +128,6 @@ class Designer extends Events {
this._relPivot = new RelationshipPivot(this._workspace, this); this._relPivot = new RelationshipPivot(this._workspace, this);
TopicEventDispatcher.configure(this.isReadOnly()); TopicEventDispatcher.configure(this.isReadOnly());
this._clipboard = [];
// Hack: There are static reference to designer variable. Needs to be reviewed. // Hack: There are static reference to designer variable. Needs to be reviewed.
globalThis.designer = this; globalThis.designer = this;
@ -381,45 +379,80 @@ class Designer extends Events {
copyToClipboard(): void { copyToClipboard(): void {
let topics = this.getModel().filterSelectedTopics(); let topics = this.getModel().filterSelectedTopics();
if (topics.length <= 0) { if (topics.length > 0) {
// If there are more than one node selected, const mindmap = new Mindmap();
$notify($msg('AT_LEAST_ONE_TOPIC_MUST_BE_SELECTED')); const central: NodeModel = new NodeModel('CentralTopic', mindmap);
return; mindmap.addBranch(central);
}
// Exclude central topic .. // Exclude central topic ..
topics = topics.filter((topic) => !topic.isCentralTopic()); topics = topics.filter((topic) => !topic.isCentralTopic());
topics.forEach((topic) => {
this._clipboard = topics.map((topic) => { const nodeModel: NodeModel = topic.getModel().deepCopy();
const nodeModel = topic.getModel().deepCopy(); nodeModel.connectTo(central);
// Change position to make the new topic evident...
const pos = nodeModel.getPosition();
nodeModel.setPosition(pos.x + 60 * Math.sign(pos.x), pos.y + 30);
return nodeModel;
}); });
$notify($msg('SELECTION_COPIED_TO_CLIPBOARD')); // Serialize to mindmap ...
const serializer = XMLSerializerFactory.createFromMindmap(mindmap);
const document = serializer.toXML(mindmap);
const xmmStr: string = new XMLSerializer().serializeToString(document);
// Convert to node, only text/html is supported...
const type = 'text/plain';
const blob = new Blob([xmmStr], { type });
const clipboard = new ClipboardItem({
[blob.type]: blob,
});
// Copy to clipboard ...
navigator.clipboard.write([clipboard]).then(
() => console.log('Copy of node success'),
(e) => console.error(e),
);
}
} }
pasteClipboard(): void { async pasteClipboard(): Promise<void> {
// If the no selection has been made, update with the text on the clipboard. const type = 'text/plain';
if (this._clipboard.length !== 0) { const clipboardItems = await navigator.clipboard.read();
this._actionDispatcher.addTopics(this._clipboard, null); clipboardItems.forEach(async (item) => {
this._clipboard = []; if (item.types.includes(type)) {
const blob: Blob = await item.getType(type);
const text: string = await blob.text();
// Is a mindmap ?. Try to infer if it's a text or a map...
if (text.indexOf('</map>') !== -1) {
const dom = new DOMParser().parseFromString(text, 'application/xml');
const serializer = XMLSerializerFactory.createFromDocument(dom);
const mindmap = serializer.loadFromDom(dom, 'application/xml');
// Remove reference to the parent mindmap and clean up to support multiple copy of the nodes ...
const central = mindmap.getBranches()[0];
let children = central.getChildren();
children.forEach((c) => c.disconnect());
children = children.map((m: NodeModel) => m.deepCopy());
// Charge position to avoid overlap ...
children.forEach((m) => {
const pos = m.getPosition();
m.setPosition(
pos.x * Math.sign(pos.x) + Math.random() * 60,
pos.y + Math.random() * 30,
);
});
// Finally, add the node ...
this._actionDispatcher.addTopics(children, null);
} else { } else {
const topics = this.getModel().filterSelectedTopics(); const topics = this.getModel().filterSelectedTopics();
if (topics.length > 0) {
navigator.clipboard.readText().then((text) => {
this._actionDispatcher.changeTextToTopic( this._actionDispatcher.changeTextToTopic(
topics.map((t) => t.getId()), topics.map((t) => t.getId()),
text.trim(), text.trim(),
); );
}
}
}); });
} }
}
}
getModel(): DesignerModel { getModel(): DesignerModel {
return this._model; return this._model;

View File

@ -173,8 +173,9 @@ class MindplotWebComponent extends HTMLElement {
const persistenceManager = PersistenceManager.getInstance(); const persistenceManager = PersistenceManager.getInstance();
// If the map could not be loaded, partial map load could happen. // If the map could not be loaded, partial map load could happen.
if (mindmap) { const mapId = mindmap.getId();
persistenceManager.unlockMap(mindmap.getId()); if (mindmap && mapId) {
persistenceManager.unlockMap(mapId);
} }
} }
} }

View File

@ -38,10 +38,10 @@ abstract class PersistenceManager {
$assert(mindmap, 'mindmap can not be null'); $assert(mindmap, 'mindmap can not be null');
$assert(editorProperties, 'editorProperties can not be null'); $assert(editorProperties, 'editorProperties can not be null');
const mapId = mindmap.getId(); const mapId = mindmap.getId() || 'WiseMapping';
$assert(mapId, 'mapId can not be null'); $assert(mapId, 'mapId can not be null');
const serializer = XMLSerializerFactory.createInstanceFromMindmap(mindmap); const serializer = XMLSerializerFactory.createFromMindmap(mindmap);
const domMap = serializer.toXML(mindmap); const domMap = serializer.toXML(mindmap);
const pref = JSON.stringify(editorProperties); const pref = JSON.stringify(editorProperties);
try { try {
@ -106,7 +106,7 @@ abstract class PersistenceManager {
$assert(mapId, 'mapId can not be null'); $assert(mapId, 'mapId can not be null');
$assert(mapDom, 'mapDom can not be null'); $assert(mapDom, 'mapDom can not be null');
const serializer = XMLSerializerFactory.createInstanceFromDocument(mapDom); const serializer = XMLSerializerFactory.createFromDocument(mapDom);
return serializer.loadFromDom(mapDom, mapId); return serializer.loadFromDom(mapDom, mapId);
} }
} }

View File

@ -80,7 +80,7 @@ class RESTPersistenceManager extends PersistenceManager {
if (response.ok) { if (response.ok) {
events.onSuccess(); events.onSuccess();
} else { } else {
console.log(`Saving error: ${response.status}`); console.error(`Saving error: ${response.status}`);
let userMsg: PersistenceError | null = null; let userMsg: PersistenceError | null = null;
if (response.status === 405) { if (response.status === 405) {
userMsg = { userMsg = {

View File

@ -30,7 +30,6 @@ class AddTopicCommand extends Command {
* the mindmap. * the mindmap.
*/ */
constructor(models: NodeModel[], parentTopicsId: number[] | null) { constructor(models: NodeModel[], parentTopicsId: number[] | null) {
$assert(models, 'models can not be null');
$assert( $assert(
parentTopicsId == null || parentTopicsId.length === models.length, parentTopicsId == null || parentTopicsId.length === models.length,
'parents and models must have the same size', 'parents and models must have the same size',

View File

@ -29,7 +29,7 @@ class WiseXMLExporter extends Exporter {
export(): Promise<string> { export(): Promise<string> {
const { mindmap } = this; const { mindmap } = this;
const serializer = XMLSerializerFactory.createInstanceFromMindmap(mindmap); const serializer = XMLSerializerFactory.createFromMindmap(mindmap);
const document: Document = serializer.toXML(mindmap); const document: Document = serializer.toXML(mindmap);
const xmlStr: string = new XMLSerializer().serializeToString(document); const xmlStr: string = new XMLSerializer().serializeToString(document);

View File

@ -77,7 +77,7 @@ export default class FreemindImporter extends Importer {
this.mindmap.setDescription(description); this.mindmap.setDescription(description);
this.mindmap.addBranch(wiseTopic); this.mindmap.addBranch(wiseTopic);
const serialize = XMLSerializerFactory.createInstanceFromMindmap(this.mindmap); const serialize = XMLSerializerFactory.createFromMindmap(this.mindmap);
const domMindmap = serialize.toXML(this.mindmap); const domMindmap = serialize.toXML(this.mindmap);
const xmlToString = new XMLSerializer().serializeToString(domMindmap); const xmlToString = new XMLSerializer().serializeToString(domMindmap);
const formatXml = xmlFormatter(xmlToString, { const formatXml = xmlFormatter(xmlToString, {

View File

@ -13,7 +13,7 @@ export default class WisemappingImporter extends Importer {
const parser = new DOMParser(); const parser = new DOMParser();
const wiseDoc = parser.parseFromString(this.wisemappingInput, 'application/xml'); const wiseDoc = parser.parseFromString(this.wisemappingInput, 'application/xml');
const serialize = XMLSerializerFactory.createInstanceFromDocument(wiseDoc); const serialize = XMLSerializerFactory.createFromDocument(wiseDoc);
const mindmap = serialize.loadFromDom(wiseDoc, nameMap); const mindmap = serialize.loadFromDom(wiseDoc, nameMap);
mindmap.setDescription(description); mindmap.setDescription(description);

View File

@ -13,11 +13,9 @@ const DE = {
SUB_TOPIC: 'Unterthema', SUB_TOPIC: 'Unterthema',
ISOLATED_TOPIC: 'Isoliertes Thema', ISOLATED_TOPIC: 'Isoliertes Thema',
CENTRAL_TOPIC: 'Zentrales Thema', CENTRAL_TOPIC: 'Zentrales Thema',
AT_LEAST_ONE_TOPIC_MUST_BE_SELECTED: 'Es muss mindestens ein Thema ausgewählt sein.',
CLIPBOARD_IS_EMPTY: 'Es gibt nichts zu kopieren. Die Zwischenablage ist leer.', CLIPBOARD_IS_EMPTY: 'Es gibt nichts zu kopieren. Die Zwischenablage ist leer.',
CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'Das zentrale Thema kann nicht gelöscht werden.', CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'Das zentrale Thema kann nicht gelöscht werden.',
RELATIONSHIP_COULD_NOT_BE_CREATED: 'Die Beziehung konnte nicht angelegt werden. Es muss erst ein Vater-Thema ausgewählt werden, um die Beziehung herzustellen.', RELATIONSHIP_COULD_NOT_BE_CREATED: 'Die Beziehung konnte nicht angelegt werden. Es muss erst ein Vater-Thema ausgewählt werden, um die Beziehung herzustellen.',
SELECTION_COPIED_TO_CLIPBOARD: 'Themen in der Zwischenablage',
SESSION_EXPIRED: 'Deine Sitzung ist abgelaufen, bitte melde dich erneut an.', SESSION_EXPIRED: 'Deine Sitzung ist abgelaufen, bitte melde dich erneut an.',
CENTRAL_TOPIC_CONNECTION_STYLE_CAN_NOT_BE_CHANGED: 'Le style de connexion ne peut pas être modifié pour le sujet central.', CENTRAL_TOPIC_CONNECTION_STYLE_CAN_NOT_BE_CHANGED: 'Le style de connexion ne peut pas être modifié pour le sujet central.',
CENTRAL_TOPIC_STYLE_CAN_NOT_BE_CHANGED: 'Le sujet central ne peut pas être changé en style de ligne.', CENTRAL_TOPIC_STYLE_CAN_NOT_BE_CHANGED: 'Le sujet central ne peut pas être changé en style de ligne.',

View File

@ -13,11 +13,9 @@ const EN = {
ISOLATED_TOPIC: 'Isolated Topic', ISOLATED_TOPIC: 'Isolated Topic',
CENTRAL_TOPIC: 'Central Topic', CENTRAL_TOPIC: 'Central Topic',
ENTITIES_COULD_NOT_BE_DELETED: 'Could not delete topic or relation. At least one map entity must be selected.', ENTITIES_COULD_NOT_BE_DELETED: 'Could not delete topic or relation. At least one map entity must be selected.',
AT_LEAST_ONE_TOPIC_MUST_BE_SELECTED: 'At least one topic must be selected.',
CLIPBOARD_IS_EMPTY: 'Nothing to copy. Clipboard is empty.', CLIPBOARD_IS_EMPTY: 'Nothing to copy. Clipboard is empty.',
CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'Central topic can not be deleted.', CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'Central topic can not be deleted.',
RELATIONSHIP_COULD_NOT_BE_CREATED: 'Relationship could not be created. A parent relationship topic must be selected first.', RELATIONSHIP_COULD_NOT_BE_CREATED: 'Relationship could not be created. A parent relationship topic must be selected first.',
SELECTION_COPIED_TO_CLIPBOARD: 'Topics copied to the clipboard',
SESSION_EXPIRED: 'Your session has expired, please log-in again.', SESSION_EXPIRED: 'Your session has expired, please log-in again.',
CENTRAL_TOPIC_CONNECTION_STYLE_CAN_NOT_BE_CHANGED: 'Connection style can not be changed for central topic.', CENTRAL_TOPIC_CONNECTION_STYLE_CAN_NOT_BE_CHANGED: 'Connection style can not be changed for central topic.',
CENTRAL_TOPIC_STYLE_CAN_NOT_BE_CHANGED: 'Central topic can not be changed to line style.', CENTRAL_TOPIC_STYLE_CAN_NOT_BE_CHANGED: 'Central topic can not be changed to line style.',

View File

@ -13,11 +13,9 @@ const ES = {
ISOLATED_TOPIC: 'Tópico Aislado', ISOLATED_TOPIC: 'Tópico Aislado',
CENTRAL_TOPIC: 'Tópico Central', CENTRAL_TOPIC: 'Tópico Central',
ENTITIES_COULD_NOT_BE_DELETED: 'El tópico o la relación no pudo ser borrada. Debe selecionar al menos una.', ENTITIES_COULD_NOT_BE_DELETED: 'El tópico o la relación no pudo ser borrada. Debe selecionar al menos una.',
AT_LEAST_ONE_TOPIC_MUST_BE_SELECTED: 'Al menos un tópico debe ser seleccionado.',
CLIPBOARD_IS_EMPTY: 'Nada que copiar. Clipboard está vacio.', CLIPBOARD_IS_EMPTY: 'Nada que copiar. Clipboard está vacio.',
CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'El tópico central no puede ser borrado.', CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'El tópico central no puede ser borrado.',
RELATIONSHIP_COULD_NOT_BE_CREATED: 'La relación no pudo ser creada. Una relación padre debe ser seleccionada primero.', RELATIONSHIP_COULD_NOT_BE_CREATED: 'La relación no pudo ser creada. Una relación padre debe ser seleccionada primero.',
SELECTION_COPIED_TO_CLIPBOARD: 'Tópicos copiados al clipboard',
SESSION_EXPIRED: 'Su session ha expirado. Por favor, ingrese nuevamente.', SESSION_EXPIRED: 'Su session ha expirado. Por favor, ingrese nuevamente.',
CENTRAL_TOPIC_CONNECTION_STYLE_CAN_NOT_BE_CHANGED: 'El estilo de conexión no se puede cambiar para el tópico central.', CENTRAL_TOPIC_CONNECTION_STYLE_CAN_NOT_BE_CHANGED: 'El estilo de conexión no se puede cambiar para el tópico central.',
CENTRAL_TOPIC_STYLE_CAN_NOT_BE_CHANGED: 'Tópico central no se puede cambiar al estilo de línea.', CENTRAL_TOPIC_STYLE_CAN_NOT_BE_CHANGED: 'Tópico central no se puede cambiar al estilo de línea.',

View File

@ -13,11 +13,9 @@ const FR = {
ISOLATED_TOPIC: 'Noeud isolé', ISOLATED_TOPIC: 'Noeud isolé',
CENTRAL_TOPIC: 'Noeud racine', CENTRAL_TOPIC: 'Noeud racine',
ENTITIES_COULD_NOT_BE_DELETED: "Impossible d'effacer un noeud ou une relation. Au moins un objet de la carte doit être sélectionné.", ENTITIES_COULD_NOT_BE_DELETED: "Impossible d'effacer un noeud ou une relation. Au moins un objet de la carte doit être sélectionné.",
AT_LEAST_ONE_TOPIC_MUST_BE_SELECTED: 'Au moins un objet de la carte doit être sélectionné.',
CLIPBOARD_IS_EMPTY: 'Rien à copier. Presse-papier vide.', CLIPBOARD_IS_EMPTY: 'Rien à copier. Presse-papier vide.',
CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'Le noeud racine ne peut pas être effacé.', CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'Le noeud racine ne peut pas être effacé.',
RELATIONSHIP_COULD_NOT_BE_CREATED: 'Impossible de créer relation. Un noeud parent doit être sélectionné au préalable.', RELATIONSHIP_COULD_NOT_BE_CREATED: 'Impossible de créer relation. Un noeud parent doit être sélectionné au préalable.',
SELECTION_COPIED_TO_CLIPBOARD: 'Noeuds sélectionnés copiés dans le presse-papiers.',
SESSION_EXPIRED: 'Votre session a expiré, veuillez vous reconnecter.', SESSION_EXPIRED: 'Votre session a expiré, veuillez vous reconnecter.',
CENTRAL_TOPIC_CONNECTION_STYLE_CAN_NOT_BE_CHANGED: 'Le style de connexion ne peut pas être modifié pour le sujet central.', CENTRAL_TOPIC_CONNECTION_STYLE_CAN_NOT_BE_CHANGED: 'Le style de connexion ne peut pas être modifié pour le sujet central.',
CENTRAL_TOPIC_STYLE_CAN_NOT_BE_CHANGED: 'Le sujet central ne peut pas être changé en style de ligne.', CENTRAL_TOPIC_STYLE_CAN_NOT_BE_CHANGED: 'Le sujet central ne peut pas être changé en style de ligne.',

View File

@ -14,11 +14,9 @@ const RU = {
ISOLATED_TOPIC: 'Isolated Topic', ISOLATED_TOPIC: 'Isolated Topic',
CENTRAL_TOPIC: 'Central Topic', CENTRAL_TOPIC: 'Central Topic',
ENTITIES_COULD_NOT_BE_DELETED: 'Could not delete topic or relation. At least one map entity must be selected.', ENTITIES_COULD_NOT_BE_DELETED: 'Could not delete topic or relation. At least one map entity must be selected.',
AT_LEAST_ONE_TOPIC_MUST_BE_SELECTED: 'At least one topic must be selected.',
CLIPBOARD_IS_EMPTY: 'Nothing to copy. Clipboard is empty.', CLIPBOARD_IS_EMPTY: 'Nothing to copy. Clipboard is empty.',
CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'Central topic can not be deleted.', CENTRAL_TOPIC_CAN_NOT_BE_DELETED: 'Central topic can not be deleted.',
RELATIONSHIP_COULD_NOT_BE_CREATED: 'Relationship could not be created. A parent relationship topic must be selected first.', RELATIONSHIP_COULD_NOT_BE_CREATED: 'Relationship could not be created. A parent relationship topic must be selected first.',
SELECTION_COPIED_TO_CLIPBOARD: 'Topics copied to the clipboard',
SESSION_EXPIRED: 'Your session has expired, please log-in again.', SESSION_EXPIRED: 'Your session has expired, please log-in again.',
}; };

View File

@ -14,11 +14,9 @@ const ZH = {
ISOLATED_TOPIC: '独立主题', ISOLATED_TOPIC: '独立主题',
CENTRAL_TOPIC: '中心主题', CENTRAL_TOPIC: '中心主题',
ENTITIES_COULD_NOT_BE_DELETED: '无法删除主题或关系。至少选择一个脑图实体。', ENTITIES_COULD_NOT_BE_DELETED: '无法删除主题或关系。至少选择一个脑图实体。',
AT_LEAST_ONE_TOPIC_MUST_BE_SELECTED: '至少要选择一个主题',
CLIPBOARD_IS_EMPTY: '没有东西可以复制。剪贴板是空的。', CLIPBOARD_IS_EMPTY: '没有东西可以复制。剪贴板是空的。',
CENTRAL_TOPIC_CAN_NOT_BE_DELETED: '无法删除中心主题。', CENTRAL_TOPIC_CAN_NOT_BE_DELETED: '无法删除中心主题。',
RELATIONSHIP_COULD_NOT_BE_CREATED: '无法创建关系。必须先选择要建立关系的主题。', RELATIONSHIP_COULD_NOT_BE_CREATED: '无法创建关系。必须先选择要建立关系的主题。',
SELECTION_COPIED_TO_CLIPBOARD: '主题已复制到剪贴板',
SESSION_EXPIRED: '您的会话已过期,请重新登录。', SESSION_EXPIRED: '您的会话已过期,请重新登录。',
}; };

View File

@ -19,6 +19,7 @@
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import INodeModel, { NodeModelType as NodeType } from './INodeModel'; import INodeModel, { NodeModelType as NodeType } from './INodeModel';
import NodeModel from './NodeModel';
import RelationshipModel from './RelationshipModel'; import RelationshipModel from './RelationshipModel';
abstract class IMindmap { abstract class IMindmap {
@ -30,7 +31,7 @@ abstract class IMindmap {
abstract setDescription(value: string): void; abstract setDescription(value: string): void;
abstract getId(): string; abstract getId(): string | undefined;
abstract setId(id: string): void; abstract setId(id: string): void;
@ -38,11 +39,11 @@ abstract class IMindmap {
abstract setVersion(version: string): void; abstract setVersion(version: string): void;
abstract addBranch(nodeModel): void; abstract addBranch(nodeModel: INodeModel): void;
abstract getBranches(); abstract getBranches(): NodeModel[];
abstract removeBranch(node): void; abstract removeBranch(node: INodeModel): void;
abstract getRelationships(): RelationshipModel[]; abstract getRelationships(): RelationshipModel[];

View File

@ -27,16 +27,14 @@ class Mindmap extends IMindmap {
private _version: string; private _version: string;
private _id: string; private _id: string | undefined;
private _branches: Array<NodeModel>; private _branches: Array<NodeModel>;
private _relationships: Array<RelationshipModel>; private _relationships: Array<RelationshipModel>;
constructor(id: string, version: string = ModelCodeName.TANGO) { constructor(id?: string, version: string = ModelCodeName.TANGO) {
super(); super();
$assert(id, 'Id can not be null');
this._branches = []; this._branches = [];
this._description = ''; this._description = '';
this._relationships = []; this._relationships = [];
@ -54,8 +52,7 @@ class Mindmap extends IMindmap {
this._description = value; this._description = value;
} }
/** */ getId(): string | undefined {
getId(): string {
return this._id; return this._id;
} }

View File

@ -49,7 +49,7 @@ class XMLSerializerFactory {
* @return {mindplot.persistence.XMLSerializer_Beta|mindplot.persistence.XMLSerializer_Pela| * @return {mindplot.persistence.XMLSerializer_Beta|mindplot.persistence.XMLSerializer_Pela|
* mindplot.persistence.XMLSerializer_Tango} serializer corresponding to the mindmap's version * mindplot.persistence.XMLSerializer_Tango} serializer corresponding to the mindmap's version
*/ */
static createInstanceFromMindmap(mindmap: Mindmap) { static createFromMindmap(mindmap: Mindmap): XMLMindmapSerializer {
return XMLSerializerFactory.getSerializer(mindmap.getVersion()); return XMLSerializerFactory.getSerializer(mindmap.getVersion());
} }
@ -57,7 +57,7 @@ class XMLSerializerFactory {
* @param domDocument * @param domDocument
* @return serializer corresponding to the mindmap's version * @return serializer corresponding to the mindmap's version
*/ */
static createInstanceFromDocument(domDocument: Document) { static createFromDocument(domDocument: Document): XMLMindmapSerializer {
const rootElem = domDocument.documentElement; const rootElem = domDocument.documentElement;
// Legacy version don't have version defined. // Legacy version don't have version defined.
@ -71,8 +71,6 @@ class XMLSerializerFactory {
* retrieves the serializer for the mindmap's version and migrates to the current version, * retrieves the serializer for the mindmap's version and migrates to the current version,
* e.g. for a Beta mindmap and current version Tango: * e.g. for a Beta mindmap and current version Tango:
* serializer = new Pela2TangoMigrator(new Beta2PelaMigrator(new XMLSerializer_Beta())) * serializer = new Pela2TangoMigrator(new Beta2PelaMigrator(new XMLSerializer_Beta()))
* @param {String} version the version name
* @return serializer
*/ */
static getSerializer(version = ModelCodeName.TANGO): XMLMindmapSerializer { static getSerializer(version = ModelCodeName.TANGO): XMLMindmapSerializer {
let found = false; let found = false;

View File

@ -45,7 +45,7 @@ class XMLSerializerTango implements XMLMindmapSerializer {
// Store map attributes ... // Store map attributes ...
const mapElem = document.createElement('map'); const mapElem = document.createElement('map');
const name = mindmap.getId(); const name = mindmap.getId();
if ($defined(name)) { if (name) {
mapElem.setAttribute('name', this._rmXmlInv(name)); mapElem.setAttribute('name', this._rmXmlInv(name));
} }
const version = mindmap.getVersion(); const version = mindmap.getVersion();

View File

@ -20,7 +20,7 @@ describe('WXML export test execution', () => {
const mapDocument = parseXMLFile(mindmapPath, 'text/xml'); const mapDocument = parseXMLFile(mindmapPath, 'text/xml');
// Convert to mindmap ... // Convert to mindmap ...
const serializer = XMLSerializerFactory.createInstanceFromDocument(mapDocument); const serializer = XMLSerializerFactory.createFromDocument(mapDocument);
const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName); const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName);
const exporter = TextExporterFactory.create('wxml', mindmap); const exporter = TextExporterFactory.create('wxml', mindmap);
@ -35,7 +35,7 @@ describe('Txt export test execution', () => {
const mapDocument = parseXMLFile(mindmapPath, 'text/xml'); const mapDocument = parseXMLFile(mindmapPath, 'text/xml');
// Convert to mindmap ... // Convert to mindmap ...
const serializer = XMLSerializerFactory.createInstanceFromDocument(mapDocument); const serializer = XMLSerializerFactory.createFromDocument(mapDocument);
const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName); const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName);
const exporter = TextExporterFactory.create('txt', mindmap); const exporter = TextExporterFactory.create('txt', mindmap);
@ -50,7 +50,7 @@ describe('MD export test execution', () => {
const mapDocument = parseXMLFile(mindmapPath, 'text/xml'); const mapDocument = parseXMLFile(mindmapPath, 'text/xml');
// Convert to mindmap ... // Convert to mindmap ...
const serializer = XMLSerializerFactory.createInstanceFromDocument(mapDocument); const serializer = XMLSerializerFactory.createFromDocument(mapDocument);
const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName); const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName);
const exporter = TextExporterFactory.create('md', mindmap); const exporter = TextExporterFactory.create('md', mindmap);
@ -65,7 +65,7 @@ describe('MM export test execution', () => {
const mapDocument = parseXMLFile(mindmapPath, 'text/xml'); const mapDocument = parseXMLFile(mindmapPath, 'text/xml');
// Convert to mindmap... // Convert to mindmap...
const serializer = XMLSerializerFactory.createInstanceFromDocument(mapDocument); const serializer = XMLSerializerFactory.createFromDocument(mapDocument);
const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName); const mindmap: Mindmap = serializer.loadFromDom(mapDocument, testName);
const exporter = TextExporterFactory.create('mm', mindmap); const exporter = TextExporterFactory.create('mm', mindmap);

View File

@ -1,3 +1,5 @@
/// <reference types="cypress" />
describe('Editor Page', () => { describe('Editor Page', () => {
beforeEach(() => { beforeEach(() => {
cy.visit('/c/maps/11/edit'); cy.visit('/c/maps/11/edit');

View File

@ -1,3 +1,5 @@
/// <reference types="cypress" />
describe('Forgot Password Page', () => { describe('Forgot Password Page', () => {
beforeEach(() => { beforeEach(() => {
cy.visit('/c/forgot-password'); cy.visit('/c/forgot-password');

View File

@ -1,3 +1,5 @@
/// <reference types="cypress" />
describe('Login Page', () => { describe('Login Page', () => {
beforeEach(() => { beforeEach(() => {
cy.visit('/c/login'); cy.visit('/c/login');

View File

@ -1,3 +1,5 @@
/// <reference types="cypress" />
describe('Maps Page', () => { describe('Maps Page', () => {
beforeEach(() => { beforeEach(() => {
cy.visit('/c/maps'); cy.visit('/c/maps');

View File

@ -1,3 +1,5 @@
/// <reference types="cypress" />
describe('Registration Page', () => { describe('Registration Page', () => {
beforeEach(() => { beforeEach(() => {
cy.visit('/c/registration'); cy.visit('/c/registration');

View File

@ -13,7 +13,6 @@
} }
], ],
"permissions" : [ "permissions" : [
"http://*/*",
"https://*/*", "https://*/*",
"clipboardRead", "clipboardRead",
"clipboardWrite", "clipboardWrite",