Fix map loading ..

This commit is contained in:
Paulo Gustavo Veiga 2024-02-08 22:54:10 -08:00
parent fc0c03b2bc
commit e3d6f5dad5
20 changed files with 248 additions and 138 deletions

View File

@ -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 };
};

View File

@ -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;

View File

@ -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>
}
/>

View File

@ -38,7 +38,7 @@ class _AppConfig {
googleOauth2Url: '/c/registration-google?code=aFakeCode',
};
isDevelopEnv(): boolean {
isMockEnv(): boolean {
const config = this.getInstance();
return config.clientType === 'mock';
}

View File

@ -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>;

View File

@ -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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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,
);
}

View File

@ -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}

View File

@ -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',

View File

@ -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);

View File

@ -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',

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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');

View File

@ -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 => {

View File

@ -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',
}),