mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-25 15:47:55 +01:00
Fix map loading ..
This commit is contained in:
parent
fc0c03b2bc
commit
e3d6f5dad5
@ -37,15 +37,18 @@ export const useEditor = ({
|
||||
const [model, setModel] = useState<Model | undefined>();
|
||||
// useEditor hook creates mindplotRef
|
||||
const mindplotRef = useRef(null);
|
||||
// This is required to redraw in case of chansges in the canvas...
|
||||
// This is required to redraw in case of changes in the canvas...
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [, setCanvasUpdate] = useState<number>();
|
||||
|
||||
const { widgetManager } = useWidgetManager();
|
||||
const capability = new Capability(options.mode, mapInfo.isLocked());
|
||||
let capability;
|
||||
if (options && mapInfo) {
|
||||
capability = new Capability(options.mode, mapInfo.isLocked());
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!model) {
|
||||
if (!model && options) {
|
||||
const model = new Model(mindplotRef.current);
|
||||
model
|
||||
.loadMindmap(mapInfo.getId(), persistenceManager, widgetManager)
|
||||
@ -59,15 +62,17 @@ export const useEditor = ({
|
||||
});
|
||||
setModel(model);
|
||||
}
|
||||
}, [mindplotRef]);
|
||||
}, [mindplotRef, options]);
|
||||
|
||||
useEffect(() => {
|
||||
if (options.enableKeyboardEvents) {
|
||||
DesignerKeyboard.resume();
|
||||
} else {
|
||||
DesignerKeyboard.pause();
|
||||
if (options) {
|
||||
if (options.enableKeyboardEvents) {
|
||||
DesignerKeyboard.resume();
|
||||
} else {
|
||||
DesignerKeyboard.pause();
|
||||
}
|
||||
}
|
||||
}, [options.enableKeyboardEvents]);
|
||||
}, [options, options?.enableKeyboardEvents]);
|
||||
|
||||
return { model, mindplotRef, mapInfo, capability, options };
|
||||
};
|
||||
|
@ -26,11 +26,13 @@ class RESTPersistenceManager extends PersistenceManager {
|
||||
|
||||
private lockUrl: string;
|
||||
|
||||
private onSave: boolean;
|
||||
private jwt: string | undefined;
|
||||
|
||||
private clearTimeout;
|
||||
|
||||
constructor(options: { documentUrl: string; revertUrl: string; lockUrl: string }) {
|
||||
private onSave: boolean;
|
||||
|
||||
constructor(options: { documentUrl: string; revertUrl: string; lockUrl: string; jwt?: string }) {
|
||||
$assert(options.documentUrl, 'documentUrl can not be null');
|
||||
$assert(options.revertUrl, 'revertUrl can not be null');
|
||||
$assert(options.lockUrl, 'lockUrl can not be null');
|
||||
@ -40,6 +42,7 @@ class RESTPersistenceManager extends PersistenceManager {
|
||||
this.revertUrl = options.revertUrl;
|
||||
this.lockUrl = options.lockUrl;
|
||||
this.onSave = false;
|
||||
this.jwt = options.jwt;
|
||||
}
|
||||
|
||||
saveMapXml(mapId: string, mapXml: Document, pref: string, saveHistory: boolean, events): void {
|
||||
@ -61,14 +64,7 @@ class RESTPersistenceManager extends PersistenceManager {
|
||||
|
||||
const persistence = this;
|
||||
|
||||
const crfs = this.getCSRFToken();
|
||||
const headers = {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
Accept: 'application/json',
|
||||
};
|
||||
if (crfs) {
|
||||
headers['X-CSRF-Token'] = crfs;
|
||||
}
|
||||
const headers = this._buildHttpHeader('application/json; charset=utf-8', 'application/json');
|
||||
|
||||
fetch(`${this.documentUrl.replace('{id}', mapId)}?${query}`, {
|
||||
method: 'PUT',
|
||||
@ -133,15 +129,7 @@ class RESTPersistenceManager extends PersistenceManager {
|
||||
}
|
||||
|
||||
discardChanges(mapId: string): void {
|
||||
const crfs = this.getCSRFToken();
|
||||
const headers = {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
Accept: 'application/json',
|
||||
};
|
||||
if (crfs) {
|
||||
headers['X-CSRF-Token'] = crfs;
|
||||
}
|
||||
|
||||
const headers = this._buildHttpHeader('application/json; charset=utf-8');
|
||||
fetch(this.revertUrl.replace('{id}', mapId), {
|
||||
method: 'POST',
|
||||
headers,
|
||||
@ -149,14 +137,7 @@ class RESTPersistenceManager extends PersistenceManager {
|
||||
}
|
||||
|
||||
unlockMap(mapId: string): void {
|
||||
const crfs = this.getCSRFToken();
|
||||
const headers = {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
};
|
||||
if (crfs) {
|
||||
headers['X-CSRF-Token'] = crfs;
|
||||
}
|
||||
|
||||
const headers = this._buildHttpHeader('text/plain; charset=utf-8');
|
||||
fetch(this.lockUrl.replace('{id}', mapId), {
|
||||
method: 'PUT',
|
||||
headers,
|
||||
@ -180,14 +161,7 @@ class RESTPersistenceManager extends PersistenceManager {
|
||||
|
||||
loadMapDom(mapId: string): Promise<Document> {
|
||||
const url = `${this.documentUrl.replace('{id}', mapId)}/xml`;
|
||||
const crfs = this.getCSRFToken();
|
||||
const headers = {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
Accept: 'application/xml',
|
||||
};
|
||||
if (crfs) {
|
||||
headers['X-CSRF-Token'] = crfs;
|
||||
}
|
||||
const headers = this._buildHttpHeader('text/plain; charset=utf-8', 'application/xml');
|
||||
|
||||
return fetch(url, {
|
||||
method: 'get',
|
||||
@ -202,6 +176,28 @@ class RESTPersistenceManager extends PersistenceManager {
|
||||
})
|
||||
.then((xmlStr) => new DOMParser().parseFromString(xmlStr, 'text/xml'));
|
||||
}
|
||||
|
||||
private _buildHttpHeader(contentType: string, accept?: string) {
|
||||
const headers = {
|
||||
'Content-Type': contentType,
|
||||
};
|
||||
|
||||
if (accept) {
|
||||
// eslint-disable-next-line dot-notation
|
||||
headers['Accept'] = accept;
|
||||
}
|
||||
|
||||
if (this.jwt) {
|
||||
// eslint-disable-next-line dot-notation
|
||||
headers['Authorization'] = `Bearer ${this.jwt} `;
|
||||
}
|
||||
|
||||
const crfs = this.getCSRFToken();
|
||||
if (crfs) {
|
||||
headers['X-CSRF-Token'] = crfs;
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
||||
export default RESTPersistenceManager;
|
||||
|
@ -17,7 +17,7 @@
|
||||
*/
|
||||
import React, { ReactElement, Suspense, useEffect } from 'react';
|
||||
import { FormattedMessage, IntlProvider } from 'react-intl';
|
||||
import { Route, Routes, BrowserRouter as Router, useNavigate } from 'react-router-dom';
|
||||
import { Route, Routes, BrowserRouter as Router, useNavigate, useParams } from 'react-router-dom';
|
||||
import ForgotPasswordSuccessPage from './components/forgot-password-success-page';
|
||||
import RegistationPage from './components/registration-page';
|
||||
import LoginPage from './components/login-page';
|
||||
@ -66,6 +66,11 @@ function Redirect({ to }) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const PageEditorWhapper = ({ isTryMode }: { isTryMode: boolean }) => {
|
||||
const mapId: string = useParams().id!;
|
||||
return <EditorPage isTryMode={isTryMode} mapId={Number.parseInt(mapId)} />;
|
||||
};
|
||||
|
||||
const App = (): ReactElement => {
|
||||
const locale = AppI18n.getDefaultLocale();
|
||||
const overwriteView = window.errorMvcView;
|
||||
@ -126,7 +131,7 @@ const App = (): ReactElement => {
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<EditorPage isTryMode={false} />
|
||||
<PageEditorWhapper isTryMode={false} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
@ -143,7 +148,7 @@ const App = (): ReactElement => {
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<EditorPage isTryMode={true} />
|
||||
<PageEditorWhapper isTryMode={true} />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
|
@ -38,7 +38,7 @@ class _AppConfig {
|
||||
googleOauth2Url: '/c/registration-google?code=aFakeCode',
|
||||
};
|
||||
|
||||
isDevelopEnv(): boolean {
|
||||
isMockEnv(): boolean {
|
||||
const config = this.getInstance();
|
||||
return config.clientType === 'mock';
|
||||
}
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Copyright [2021] [wisemapping]
|
||||
*
|
||||
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||
* "powered by wisemapping" text requirement on every single page;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the license at
|
||||
*
|
||||
* http://www.wisemapping.org/license
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Locale, LocaleCode } from '../app-i18n';
|
||||
|
||||
export type JwtAuth = {
|
||||
@ -42,6 +59,14 @@ export type MapInfo = {
|
||||
role: Role;
|
||||
};
|
||||
|
||||
export type MapMetadata = {
|
||||
id: number;
|
||||
title: string;
|
||||
isLocked: boolean;
|
||||
isLockedBy?: string;
|
||||
zoom: number;
|
||||
};
|
||||
|
||||
export type ChangeHistory = {
|
||||
id: number;
|
||||
lastModificationBy: string;
|
||||
@ -99,6 +124,7 @@ interface Client {
|
||||
deleteMap(id: number): Promise<void>;
|
||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
|
||||
fetchAllMaps(): Promise<MapInfo[]>;
|
||||
fetchMapMetadata(id: number): Promise<MapMetadata>;
|
||||
|
||||
fetchStarred(id: number): Promise<boolean>;
|
||||
|
||||
|
@ -27,6 +27,7 @@ import Client, {
|
||||
Oauth2CallbackResult,
|
||||
ForgotPasswordResult,
|
||||
JwtAuth,
|
||||
MapMetadata,
|
||||
} from '..';
|
||||
import { LocaleCode, localeFromStr } from '../../app-i18n';
|
||||
import Cookies from 'universal-cookie';
|
||||
@ -128,6 +129,15 @@ class MockClient implements Client {
|
||||
|
||||
this.labels = [label1, label2, label3];
|
||||
}
|
||||
fetchMapMetadata(id: number): Promise<MapMetadata> {
|
||||
return Promise.resolve({
|
||||
title: 'my map',
|
||||
id: id,
|
||||
isLocked: false,
|
||||
zoom: 0.8,
|
||||
});
|
||||
}
|
||||
|
||||
logout(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*
|
||||
* Copyright [2021] [wisemapping]
|
||||
*
|
||||
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||
* "powered by wisemapping" text requirement on every single page;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the license at
|
||||
*
|
||||
* http://www.wisemapping.org/license
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import axios, { AxiosInstance, AxiosResponse } from 'axios';
|
||||
import Client, {
|
||||
ErrorInfo,
|
||||
@ -12,6 +29,7 @@ import Client, {
|
||||
Oauth2CallbackResult,
|
||||
ForgotPasswordResult,
|
||||
JwtAuth,
|
||||
MapMetadata,
|
||||
} from '..';
|
||||
import { getCsrfToken } from '../../../utils';
|
||||
import { LocaleCode, localeFromStr } from '../../app-i18n';
|
||||
@ -20,11 +38,11 @@ import Cookies from 'universal-cookie';
|
||||
export default class RestClient implements Client {
|
||||
private baseUrl: string;
|
||||
private axios: AxiosInstance;
|
||||
private _onSessionExpired: () => void;
|
||||
|
||||
private checkResponseForSessionExpired = <T>(error: {
|
||||
response?: AxiosResponse<T>;
|
||||
}): Promise<{ response?: AxiosResponse<T> }> => {
|
||||
// TODO: Improve session timeout response and response handling
|
||||
if (error.response && (error.response.status === 405 || error.response.status === 403)) {
|
||||
this.sessionExpired();
|
||||
}
|
||||
@ -63,6 +81,28 @@ export default class RestClient implements Client {
|
||||
);
|
||||
}
|
||||
|
||||
fetchMapMetadata(id: number): Promise<MapMetadata> {
|
||||
const handler = (
|
||||
success: (mapMetadata: MapMetadata) => void,
|
||||
reject: (error: ErrorInfo) => void,
|
||||
) => {
|
||||
this.axios
|
||||
.get(`${this.baseUrl}/api/restful/maps/${id}/metadata`, {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
const data = response.data;
|
||||
success(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
logout(): Promise<void> {
|
||||
// Set jwt token on cookie ...
|
||||
const cookies = new Cookies();
|
||||
@ -100,7 +140,6 @@ export default class RestClient implements Client {
|
||||
return token ? `Bearer ${token}` : null;
|
||||
}
|
||||
|
||||
private _onSessionExpired: () => void;
|
||||
onSessionExpired(callback?: () => void): () => void {
|
||||
if (callback) {
|
||||
this._onSessionExpired = callback;
|
||||
|
@ -1,44 +0,0 @@
|
||||
import { EditorOptions } from '@wisemapping/editor';
|
||||
import { EditorRenderMode } from '@wisemapping/editor';
|
||||
import AppConfig from '../../classes/app-config';
|
||||
|
||||
class EditorOptionsBuilder {
|
||||
static build(locale: string, mode: EditorRenderMode, hotkeys: boolean): EditorOptions {
|
||||
let options: EditorOptions = {
|
||||
enableKeyboardEvents: hotkeys,
|
||||
locale: locale,
|
||||
mode: mode,
|
||||
};
|
||||
|
||||
if (!AppConfig.isDevelopEnv()) {
|
||||
options = {
|
||||
zoom: globalThis.userOptions?.zoom ? globalThis?.userOptions?.zoom : 0.8,
|
||||
locked: globalThis.mindmapLocked,
|
||||
lockedMsg: globalThis.mindmapLockedMsg,
|
||||
mapTitle: globalThis.mapTitle,
|
||||
...options,
|
||||
};
|
||||
} else {
|
||||
// Running in a development mode.
|
||||
console.log('Running editor in development mode');
|
||||
options = {
|
||||
zoom: 0.8,
|
||||
locked: false,
|
||||
mapTitle: 'Develop Mindnap',
|
||||
...options,
|
||||
};
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
static loadMapId(): number {
|
||||
const result = !AppConfig.isDevelopEnv() ? globalThis.mapId : 11;
|
||||
if (result === undefined) {
|
||||
throw Error(
|
||||
`Could not resolve mapId. Map Id: globalThis.mapId: ${result} , globalThis.mapTitle: ${globalThis.mapTitle}, globalThis.lockSession: ${globalThis.lockSession}`,
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
export default EditorOptionsBuilder;
|
@ -4,7 +4,7 @@ import { LocalStorageManager, Mindmap, XMLSerializerFactory } from '@wisemapping
|
||||
export const fetchMindmap = async (mapId: number): Promise<Mindmap> => {
|
||||
let mindmap: Mindmap;
|
||||
if (AppConfig.isRestClient()) {
|
||||
const persistence = new LocalStorageManager(`/c/restful/maps/{id}/document/xml`, true);
|
||||
const persistence = new LocalStorageManager(`/api/restful/maps/{id}/document/xml`, true);
|
||||
mindmap = await persistence.load(String(mapId));
|
||||
} else {
|
||||
const parser = new DOMParser();
|
||||
|
@ -34,8 +34,8 @@ import {
|
||||
useFetchMapById,
|
||||
activeInstance,
|
||||
sessionExpired,
|
||||
useFetchMapMetadata,
|
||||
} from '../../redux/clientSlice';
|
||||
import EditorOptionsBuilder from './EditorOptionsBuilder';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import MapInfoImpl from '../../classes/editor-map-info';
|
||||
import { MapInfo } from '@wisemapping/editor';
|
||||
@ -43,24 +43,31 @@ import Client from '../../classes/client';
|
||||
import AppConfig from '../../classes/app-config';
|
||||
import exampleMap from '../../classes/client/mock-client/example-map.wxml';
|
||||
import ClientHealthSentinel from '../common/client-health-sentinel';
|
||||
import Cookies from 'universal-cookie';
|
||||
|
||||
const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
|
||||
let persistenceManager: PersistenceManager;
|
||||
if (AppConfig.isRestClient()) {
|
||||
if (mode === 'edition-owner' || mode === 'edition-editor') {
|
||||
// Fetch JWT token ...
|
||||
const cookies = new Cookies();
|
||||
const token = cookies.get('jwt-auth-token');
|
||||
|
||||
persistenceManager = new RESTPersistenceManager({
|
||||
documentUrl: '/c/restful/maps/{id}/document',
|
||||
revertUrl: '/c/restful/maps/{id}/history/latest',
|
||||
lockUrl: '/c/restful/maps/{id}/lock',
|
||||
documentUrl: '/api/restful/maps/{id}/document',
|
||||
revertUrl: '/api/restful/maps/{id}/history/latest',
|
||||
lockUrl: '/api/restful/maps/{id}/lock',
|
||||
jwt: token,
|
||||
});
|
||||
} else {
|
||||
persistenceManager = new LocalStorageManager(
|
||||
`/c/restful/maps/{id}/${
|
||||
`/api/restful/maps/{id}/${
|
||||
globalThis.historyId ? `${globalThis.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
|
||||
@ -75,6 +82,7 @@ const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
|
||||
|
||||
export type EditorPropsType = {
|
||||
isTryMode: boolean;
|
||||
mapId: number;
|
||||
};
|
||||
|
||||
type ActionType =
|
||||
@ -97,7 +105,14 @@ type ActionType =
|
||||
const ActionDispatcher = React.lazy(() => import('../maps-page/action-dispatcher'));
|
||||
const AccountMenu = React.lazy(() => import('../maps-page/account-menu'));
|
||||
|
||||
const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
||||
type EditorMetadata = {
|
||||
mode: EditorRenderMode;
|
||||
title: string;
|
||||
isLocked: boolean;
|
||||
zoom: number;
|
||||
};
|
||||
|
||||
const EditorPage = ({ mapId, isTryMode }: EditorPropsType): React.ReactElement => {
|
||||
const [activeDialog, setActiveDialog] = React.useState<ActionType | null>(null);
|
||||
const hotkey = useSelector(hotkeysEnabled);
|
||||
const userLocale = AppI18n.getUserLocale();
|
||||
@ -119,51 +134,79 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
||||
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` });
|
||||
}, []);
|
||||
|
||||
const useFindEditorMode = (isTryMode: boolean, mapId: number): EditorRenderMode | null => {
|
||||
let result: EditorRenderMode = null;
|
||||
if (isTryMode) {
|
||||
result = 'showcase';
|
||||
} else if (globalThis.mindmapLocked) {
|
||||
result = 'viewonly';
|
||||
} else {
|
||||
const fetchResult = useFetchMapById(mapId);
|
||||
if (!fetchResult.isLoading) {
|
||||
if (fetchResult.error) {
|
||||
throw new Error(`Map info could not be loaded: ${JSON.stringify(fetchResult.error)}`);
|
||||
}
|
||||
const useFindEditorMode = (isTryMode: boolean, mapId: number): EditorMetadata | undefined => {
|
||||
let mode: EditorRenderMode = null;
|
||||
let title = '';
|
||||
let isLocked = false;
|
||||
|
||||
if (!fetchResult.map) {
|
||||
if (isTryMode) {
|
||||
mode = 'showcase';
|
||||
title = 'Try map';
|
||||
isLocked = false;
|
||||
} else {
|
||||
const fetchMapInfoResult = useFetchMapById(mapId);
|
||||
const fetchMetadataResult = useFetchMapMetadata(mapId);
|
||||
|
||||
if (!fetchMapInfoResult.isLoading && !fetchMetadataResult.isLoading) {
|
||||
if (fetchMapInfoResult.error || fetchMetadataResult.error) {
|
||||
throw new Error(
|
||||
`Map info could not be loaded. Info not present: ${JSON.stringify(fetchResult)}`,
|
||||
`Map info could not be loaded: ${JSON.stringify(fetchMapInfoResult.error)}`,
|
||||
);
|
||||
}
|
||||
result = `edition-${fetchResult.map.role}`;
|
||||
|
||||
if (!fetchMapInfoResult.data) {
|
||||
throw new Error(
|
||||
`Map info could not be loaded. Info not present: ${JSON.stringify(fetchMapInfoResult)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!fetchMetadataResult.data) {
|
||||
throw new Error(
|
||||
`Map info could not be loaded. Info not present: ${JSON.stringify(
|
||||
fetchMetadataResult,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (fetchMetadataResult.data?.isLocked) {
|
||||
mode = 'viewonly';
|
||||
} else {
|
||||
mode = `edition-${fetchMapInfoResult.data.role}`;
|
||||
}
|
||||
isLocked = fetchMetadataResult.data.isLocked;
|
||||
title = fetchMetadataResult.data.title;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return mode ? { mode: mode, isLocked: isLocked, title: title, zoom: 0.8 } : undefined;
|
||||
};
|
||||
|
||||
// What is the role ?
|
||||
const mapId = EditorOptionsBuilder.loadMapId();
|
||||
const mode = useFindEditorMode(isTryMode, mapId);
|
||||
const mapMetadata = useFindEditorMode(isTryMode, mapId);
|
||||
|
||||
// Account settings can be null and editor cannot be initilized multiple times. This creates problems
|
||||
// at the i18n resource loading.
|
||||
const isAccountLoaded = mode === 'showcase' || useFetchAccount;
|
||||
const loadCompleted = mode && isAccountLoaded;
|
||||
const isAccountLoaded = mapMetadata?.mode === 'showcase' || useFetchAccount;
|
||||
const loadCompleted = mapMetadata && isAccountLoaded;
|
||||
|
||||
let options: EditorOptions, persistence: PersistenceManager;
|
||||
let persistence: PersistenceManager;
|
||||
let mapInfo: MapInfo;
|
||||
let options: EditorOptions;
|
||||
if (loadCompleted) {
|
||||
options = EditorOptionsBuilder.build(userLocale.code, mode, hotkey);
|
||||
persistence = buildPersistenceManagerForEditor(mode);
|
||||
// Configure de
|
||||
options = {
|
||||
enableKeyboardEvents: hotkey,
|
||||
locale: userLocale.code,
|
||||
mode: mapMetadata.mode,
|
||||
};
|
||||
|
||||
persistence = buildPersistenceManagerForEditor(mapMetadata.mode);
|
||||
mapInfo = new MapInfoImpl(
|
||||
mapId,
|
||||
client,
|
||||
options.mapTitle,
|
||||
options.locked,
|
||||
options.lockedMsg,
|
||||
options.zoom,
|
||||
mapMetadata.title,
|
||||
mapMetadata.isLocked,
|
||||
'',
|
||||
mapMetadata.zoom,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ const ActionChooser = (props: ActionProps): React.ReactElement => {
|
||||
};
|
||||
};
|
||||
|
||||
const role = mapId !== undefined ? useFetchMapById(mapId)?.map?.role : undefined;
|
||||
const role = mapId !== undefined ? useFetchMapById(mapId)?.data?.role : undefined;
|
||||
return (
|
||||
<Menu
|
||||
anchorEl={anchor}
|
||||
|
@ -30,7 +30,7 @@ const DeleteDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
||||
mutation.mutate(mapId);
|
||||
};
|
||||
|
||||
const { map } = useFetchMapById(mapId);
|
||||
const { data: map } = useFetchMapById(mapId);
|
||||
const alertTitle = `${intl.formatMessage({
|
||||
id: 'action.delete-title',
|
||||
defaultMessage: 'Delete',
|
||||
|
@ -56,7 +56,7 @@ const DuplicateDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElem
|
||||
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
||||
};
|
||||
|
||||
const { map } = useFetchMapById(mapId);
|
||||
const { data: map } = useFetchMapById(mapId);
|
||||
useEffect(() => {
|
||||
if (map) {
|
||||
setModel(map);
|
||||
|
@ -39,7 +39,7 @@ const ExportDialog = ({
|
||||
}: ExportDialogProps): React.ReactElement => {
|
||||
const intl = useIntl();
|
||||
const [submit, setSubmit] = React.useState<boolean>(false);
|
||||
const { map } = useFetchMapById(mapId);
|
||||
const { data: map } = useFetchMapById(mapId);
|
||||
|
||||
const [exportGroup, setExportGroup] = React.useState<ExportGroup>(
|
||||
enableImgExport ? 'image' : 'document',
|
||||
|
@ -18,7 +18,7 @@ import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
||||
dayjs.extend(LocalizedFormat);
|
||||
|
||||
const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const { map } = useFetchMapById(mapId);
|
||||
const { data: map } = useFetchMapById(mapId);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
|
||||
const intl = useIntl();
|
||||
|
@ -21,7 +21,7 @@ import AppConfig from '../../../../classes/app-config';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
const PublishDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const { map } = useFetchMapById(mapId);
|
||||
const { data: map } = useFetchMapById(mapId);
|
||||
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const [model, setModel] = React.useState<boolean>(map ? map.isPublic : false);
|
||||
|
@ -58,7 +58,7 @@ const RenameDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
||||
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
||||
};
|
||||
|
||||
const { map } = useFetchMapById(mapId);
|
||||
const { data: map } = useFetchMapById(mapId);
|
||||
useEffect(() => {
|
||||
if (map) {
|
||||
setModel(map);
|
||||
|
@ -62,6 +62,7 @@ import LabelDeleteConfirm from './maps-list/label-delete-confirm';
|
||||
import ReactGA from 'react-ga4';
|
||||
import { CSSObject, Interpolation, Theme } from '@emotion/react';
|
||||
import withEmotionStyles from '../HOCs/withEmotionStyles';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export type Filter = GenericFilter | LabelFilter;
|
||||
|
||||
@ -91,6 +92,7 @@ const MapsPage = (): ReactElement => {
|
||||
localStorage.getItem('desktopDrawerOpen') === 'true',
|
||||
);
|
||||
const classes = useStyles(desktopDrawerOpen);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleMobileDrawerToggle = () => {
|
||||
setMobileDrawerOpen(!mobileDrawerOpen);
|
||||
@ -123,6 +125,16 @@ const MapsPage = (): ReactElement => {
|
||||
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: 'Maps List' });
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (client) {
|
||||
client.onSessionExpired(() => {
|
||||
navigate('/c/login');
|
||||
});
|
||||
} else {
|
||||
console.warn('Session expiration wont be handled because could not find client');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const mutation = useMutation((id: number) => client.deleteLabel(id), {
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries('labels');
|
||||
|
@ -19,7 +19,7 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { useQuery } from 'react-query';
|
||||
import Client, { AccountInfo, ErrorInfo, MapInfo } from '../classes/client';
|
||||
import Client, { AccountInfo, ErrorInfo, MapInfo, MapMetadata } from '../classes/client';
|
||||
import { useSelector } from 'react-redux';
|
||||
import AppConfig from '../classes/app-config';
|
||||
import { RootState } from './rootReducer';
|
||||
@ -55,7 +55,7 @@ export const clientSlice = createSlice({
|
||||
type MapLoadResult = {
|
||||
isLoading: boolean;
|
||||
error: ErrorInfo | null;
|
||||
map: MapInfo | undefined;
|
||||
data: MapInfo | undefined;
|
||||
};
|
||||
|
||||
export const useFetchMapById = (id: number): MapLoadResult => {
|
||||
@ -82,7 +82,24 @@ export const useFetchMapById = (id: number): MapLoadResult => {
|
||||
};
|
||||
}
|
||||
}
|
||||
return { isLoading: isLoading, error: errorMsg, map: map };
|
||||
return { isLoading: isLoading, error: errorMsg, data: map };
|
||||
};
|
||||
|
||||
type MapMetadataLoadResult = {
|
||||
isLoading: boolean;
|
||||
error: ErrorInfo | null;
|
||||
data: MapMetadata | undefined;
|
||||
};
|
||||
|
||||
export const useFetchMapMetadata = (id: number): MapMetadataLoadResult => {
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapMetadata>(
|
||||
`maps-metadata-${id}`,
|
||||
() => {
|
||||
return client.fetchMapMetadata(id);
|
||||
},
|
||||
);
|
||||
return { isLoading: isLoading, error: error, data: data };
|
||||
};
|
||||
|
||||
export const useFetchAccount = (): AccountInfo | undefined => {
|
||||
|
@ -14,6 +14,7 @@ module.exports = merge(common, {
|
||||
template: path.join(__dirname, 'public/index.html'),
|
||||
templateParameters: {
|
||||
PUBLIC_URL: process.env.PUBLIC_URL ? process.env.PUBLIC_URL : 'https://www.wisemapping.com',
|
||||
CLIENT_TYPE: 'rest'
|
||||
},
|
||||
base: process.env.PUBLIC_URL ? process.env.PUBLIC_URL : 'https://www.wisemapping.com',
|
||||
}),
|
||||
|
Loading…
Reference in New Issue
Block a user