Merged in lazy-editor-in-app (pull request #59)

Lazy editor in app

* remove editor dependecies from Client + code refactor

* eslint fixes

* commented code removed

* Merged develop into lazy-editor-in-app
* code refactor to move logic from views

* eslint fixes

* Merge branch 'lazy-editor-in-app' of bitbucket.org:wisemapping/wisemapping-frontend into lazy-editor-in-app
This commit is contained in:
Gonzalo Martinez 2022-09-08 03:46:09 +00:00 committed by Paulo Veiga
parent 394346810a
commit e976f3747a
8 changed files with 76 additions and 117 deletions

View File

@ -35,6 +35,11 @@ class _AppConfig {
return result; return result;
} }
isRestClient(): boolean {
const config = this.getInstance();
return config.clientType === 'rest';
}
isRecaptcha2Enabled(): boolean { isRecaptcha2Enabled(): boolean {
const config = this.getInstance(); const config = this.getInstance();
return config.recaptcha2Enabled; return config.recaptcha2Enabled;

View File

@ -1,4 +1,3 @@
import { EditorRenderMode, Mindmap, PersistenceManager } from '@wisemapping/editor';
import Client, { import Client, {
AccountInfo, AccountInfo,
BasicMapInfo, BasicMapInfo,
@ -22,10 +21,6 @@ class CacheDecoratorClient implements Client {
return this.client.onSessionExpired(callback); return this.client.onSessionExpired(callback);
} }
fetchMindmap(id: number): Mindmap {
return this.client.fetchMindmap(id);
}
deleteAccount(): Promise<void> { deleteAccount(): Promise<void> {
return this.client.deleteAccount(); return this.client.deleteAccount();
} }
@ -129,14 +124,6 @@ class CacheDecoratorClient implements Client {
revertHistory(id: number, cid: number): Promise<void> { revertHistory(id: number, cid: number): Promise<void> {
return this.client.revertHistory(id, cid); return this.client.revertHistory(id, cid);
} }
buildPersistenceManager(mode: EditorRenderMode): PersistenceManager {
return this.client.buildPersistenceManager(mode);
}
removePersistenceManager(): void {
return this.client.removePersistenceManager();
}
} }
export default CacheDecoratorClient; export default CacheDecoratorClient;

View File

@ -1,4 +1,3 @@
import { EditorRenderMode, Mindmap, PersistenceManager } from '@wisemapping/editor';
import { Locale, LocaleCode } from '../app-i18n'; import { Locale, LocaleCode } from '../app-i18n';
export type NewUser = { export type NewUser = {
@ -107,11 +106,6 @@ interface Client {
fetchHistory(id: number): Promise<ChangeHistory[]>; fetchHistory(id: number): Promise<ChangeHistory[]>;
revertHistory(id: number, cid: number): Promise<void>; revertHistory(id: number, cid: number): Promise<void>;
fetchMindmap(id: number): Mindmap;
buildPersistenceManager(mode: EditorRenderMode): PersistenceManager;
removePersistenceManager(): void;
onSessionExpired(callback?: () => void): () => void; onSessionExpired(callback?: () => void): () => void;
} }

View File

@ -1,5 +1,3 @@
import { Mindmap, MockPersistenceManager, PersistenceManager } from '@wisemapping/editor';
import XMLSerializerTango from '@wisemapping/editor';
import Client, { import Client, {
AccountInfo, AccountInfo,
BasicMapInfo, BasicMapInfo,
@ -11,7 +9,6 @@ import Client, {
Permission, Permission,
} from '..'; } from '..';
import { LocaleCode, localeFromStr } from '../../app-i18n'; import { LocaleCode, localeFromStr } from '../../app-i18n';
import exampleMap from './example-map.wxml';
const label1: Label = { const label1: Label = {
id: 1, id: 1,
@ -35,7 +32,6 @@ class MockClient implements Client {
private maps: MapInfo[] = []; private maps: MapInfo[] = [];
private labels: Label[] = []; private labels: Label[] = [];
private permissionsByMap: Map<number, Permission[]> = new Map(); private permissionsByMap: Map<number, Permission[]> = new Map();
private persistenceManager: PersistenceManager;
constructor() { constructor() {
// Remove, just for develop .... // Remove, just for develop ....
@ -116,20 +112,6 @@ class MockClient implements Client {
return callback; return callback;
} }
fetchMindmap(id: number): Mindmap {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(
`
<map name="${id}" version="tango">
<topic central="true" text="This is the map ${id}" id="1" fontStyle=";;#ffffff;;;"></topic>
</map>
`,
'text/xml',
);
const serializer = new XMLSerializerTango();
return serializer.loadFromDom(xmlDoc, String(id));
}
deleteMapPermission(id: number, email: string): Promise<void> { deleteMapPermission(id: number, email: string): Promise<void> {
let perm = this.permissionsByMap.get(id) || []; let perm = this.permissionsByMap.get(id) || [];
perm = perm.filter((p) => p.email != email); perm = perm.filter((p) => p.email != email);
@ -405,21 +387,6 @@ class MockClient implements Client {
console.log('email:' + email); console.log('email:' + email);
return Promise.resolve(); return Promise.resolve();
} }
buildPersistenceManager(): PersistenceManager {
if (this.persistenceManager) {
return this.persistenceManager;
}
const persistence: PersistenceManager = new MockPersistenceManager(exampleMap);
this.persistenceManager = persistence;
return persistence;
}
removePersistenceManager(): void {
if (this.persistenceManager) {
delete this.persistenceManager;
}
}
} }
export default MockClient; export default MockClient;

View File

@ -1,11 +1,3 @@
import {
EditorRenderMode,
LocalStorageManager,
Mindmap,
PersistenceManager,
RESTPersistenceManager,
} from '@wisemapping/editor';
import { PersistenceError } from '@wisemapping/editor';
import axios, { AxiosInstance, AxiosResponse } from 'axios'; import axios, { AxiosInstance, AxiosResponse } from 'axios';
import Client, { import Client, {
ErrorInfo, ErrorInfo,
@ -23,7 +15,6 @@ import { LocaleCode, localeFromStr } from '../../app-i18n';
export default class RestClient implements Client { export default class RestClient implements Client {
private baseUrl: string; private baseUrl: string;
private persistenceManager: PersistenceManager;
private axios: AxiosInstance; private axios: AxiosInstance;
private checkResponseForSessionExpired = <T>(error: { private checkResponseForSessionExpired = <T>(error: {
@ -65,13 +56,6 @@ export default class RestClient implements Client {
} }
} }
fetchMindmap(id: number): Mindmap {
// Load mindmap ...
const persistence = new LocalStorageManager(`/c/restful/maps/{id}/document/xml`, true);
const mindmap = persistence.load(String(id));
return mindmap;
}
deleteMapPermission(id: number, email: string): Promise<void> { deleteMapPermission(id: number, email: string): Promise<void> {
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => { const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
this.axios this.axios
@ -621,44 +605,6 @@ export default class RestClient implements Client {
return new Promise(handler); return new Promise(handler);
} }
private onPersistenceManagerError(error: PersistenceError) {
if (error.errorType === 'session-expired') {
this.sessionExpired();
}
}
buildPersistenceManager(editorMode: EditorRenderMode): PersistenceManager {
if (this.persistenceManager) {
return this.persistenceManager;
}
let persistence: PersistenceManager;
if (editorMode === 'edition-owner' || editorMode === 'edition-editor') {
persistence = new RESTPersistenceManager({
documentUrl: '/c/restful/maps/{id}/document',
revertUrl: '/c/restful/maps/{id}/history/latest',
lockUrl: '/c/restful/maps/{id}/lock',
});
} else {
persistence = new LocalStorageManager(
`/c/restful/maps/{id}/${global.historyId ? `${global.historyId}/` : ''}document/xml${
editorMode === 'showcase' ? '-pub' : ''
}`,
true,
);
}
persistence.addErrorHandler((err) => this.onPersistenceManagerError(err));
this.persistenceManager = persistence;
return persistence;
}
removePersistenceManager(): void {
if (this.persistenceManager) {
this.persistenceManager.removeErrorHandler();
delete this.persistenceManager;
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
private parseResponseOnError = (response: any): ErrorInfo => { private parseResponseOnError = (response: any): ErrorInfo => {
console.error(`Performing backend action error: ${JSON.stringify(response)}`); console.error(`Performing backend action error: ${JSON.stringify(response)}`);

View File

@ -0,0 +1,61 @@
import AppConfig from '../../classes/app-config';
import exampleMap from '../../classes/client/mock-client/example-map.wxml';
import {
PersistenceManager,
RESTPersistenceManager,
LocalStorageManager,
Mindmap,
MockPersistenceManager,
XMLSerializerTango,
} from '@wisemapping/editor';
export const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
let persistenceManager: PersistenceManager;
if (AppConfig.isRestClient()) {
if (mode === 'edition-owner' || mode === 'edition-editor') {
persistenceManager = new RESTPersistenceManager({
documentUrl: '/c/restful/maps/{id}/document',
revertUrl: '/c/restful/maps/{id}/history/latest',
lockUrl: '/c/restful/maps/{id}/lock',
});
} else {
persistenceManager = new LocalStorageManager(
`/c/restful/maps/{id}/${global.historyId ? `${global.historyId}/` : ''}document/xml${
mode === 'showcase' ? '-pub' : ''
}`,
true,
);
}
persistenceManager.addErrorHandler((error) => {
if (error.errorType === 'session-expired') {
// TODO: this line was in RestPersistenceClient, do something similar here
//client.sessionExpired();
}
});
} else {
persistenceManager = new MockPersistenceManager(exampleMap);
}
return persistenceManager;
};
export const getMindmapFromPersistence = (mapId: string): Mindmap => {
let mindmap: Mindmap;
if (AppConfig.isRestClient()) {
const persistence = new LocalStorageManager(`/c/restful/maps/{id}/document/xml`, true);
mindmap = persistence.load(String(mapId));
} else {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(
`
<map name="${mapId}" version="tango">
<topic central="true" text="This is the map ${mapId}" id="1" fontStyle=";;#ffffff;;;"></topic>
</map>
`,
'text/xml',
);
const serializer = new XMLSerializerTango();
mindmap = serializer.loadFromDom(xmlDoc, String(mapId));
}
return mindmap;
};

View File

@ -8,9 +8,9 @@ import AppI18n, { Locales } from '../../classes/app-i18n';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { hotkeysEnabled } from '../../redux/editorSlice'; import { hotkeysEnabled } from '../../redux/editorSlice';
import ReactGA from 'react-ga4'; import ReactGA from 'react-ga4';
import Client from '../../classes/client'; import { fetchAccount, fetchMapById } from '../../redux/clientSlice';
import { activeInstance, fetchAccount, fetchMapById } from '../../redux/clientSlice';
import EditorOptionsBuilder from './EditorOptionsBuilder'; import EditorOptionsBuilder from './EditorOptionsBuilder';
import { buildPersistenceManagerForEditor } from './PersistenceManagerUtils';
export type EditorPropsType = { export type EditorPropsType = {
isTryMode: boolean; isTryMode: boolean;
@ -20,7 +20,6 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
const [activeDialog, setActiveDialog] = React.useState<ActionType | null>(null); const [activeDialog, setActiveDialog] = React.useState<ActionType | null>(null);
const hotkey = useSelector(hotkeysEnabled); const hotkey = useSelector(hotkeysEnabled);
const userLocale = AppI18n.getUserLocale(); const userLocale = AppI18n.getUserLocale();
const client: Client = useSelector(activeInstance);
useEffect(() => { useEffect(() => {
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` }); ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` });
@ -62,7 +61,7 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
let options, persistence: PersistenceManager; let options, persistence: PersistenceManager;
if (loadCompleted) { if (loadCompleted) {
options = EditorOptionsBuilder.build(userLocale.code, mode, hotkey); options = EditorOptionsBuilder.build(userLocale.code, mode, hotkey);
persistence = client.buildPersistenceManager(mode); persistence = buildPersistenceManagerForEditor(mode);
} }
return loadCompleted ? ( return loadCompleted ? (

View File

@ -16,12 +16,10 @@ import {
ImageExporterFactory, ImageExporterFactory,
Exporter, Exporter,
Mindmap, Mindmap,
SizeType,
} from '@wisemapping/editor'; } from '@wisemapping/editor';
import Client from '../../../../classes/client'; import { getMindmapFromPersistence } from '../../../editor-page/PersistenceManagerUtils';
import { activeInstance } from '../../../../redux/clientSlice';
import { useSelector } from 'react-redux';
import SizeType from '@wisemapping/editor';
import Checkbox from '@mui/material/Checkbox'; import Checkbox from '@mui/material/Checkbox';
type ExportFormat = 'svg' | 'jpg' | 'png' | 'txt' | 'mm' | 'wxml' | 'xls' | 'md'; type ExportFormat = 'svg' | 'jpg' | 'png' | 'txt' | 'mm' | 'wxml' | 'xls' | 'md';
@ -42,7 +40,6 @@ const ExportDialog = ({
const intl = useIntl(); const intl = useIntl();
const [submit, setSubmit] = React.useState<boolean>(false); const [submit, setSubmit] = React.useState<boolean>(false);
const { map } = fetchMapById(mapId); const { map } = fetchMapById(mapId);
const client: Client = useSelector(activeInstance);
const [exportGroup, setExportGroup] = React.useState<ExportGroup>( const [exportGroup, setExportGroup] = React.useState<ExportGroup>(
enableImgExport ? 'image' : 'document', enableImgExport ? 'image' : 'document',
@ -96,14 +93,17 @@ const ExportDialog = ({
let mindmap: Mindmap; let mindmap: Mindmap;
const designer: Designer = global.designer; const designer: Designer = global.designer;
// exporting from editor toolbar action
if (designer != null) { if (designer != null) {
// Depending on the type of export. It will require differt POST. // Depending on the type of export. It will require differt POST.
const workspace = designer.getWorkSpace(); const workspace = designer.getWorkSpace();
svgElement = workspace.getSVGElement(); svgElement = workspace.getSVGElement();
size = { width: window.innerWidth, height: window.innerHeight }; size = { width: window.innerWidth, height: window.innerHeight };
mindmap = designer.getMindmap(); mindmap = designer.getMindmap();
} else { }
mindmap = client.fetchMindmap(mapId); // exporting from map list
else {
mindmap = getMindmapFromPersistence(String(mapId));
} }
let exporter: Exporter; let exporter: Exporter;