mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-22 06:37:56 +01:00
Add status change support in mindmap editor
This commit is contained in:
parent
7a9c89b8ae
commit
9b10a987f3
@ -181,6 +181,10 @@ const ActionConfigByRenderMode: Record<ActionType, CapabilitySupport> = {
|
||||
hidden: ['viewonly', 'edition-viewer', 'edition-editor', 'edition-owner'],
|
||||
},
|
||||
},
|
||||
starred: undefined,
|
||||
starred: {
|
||||
desktop: {
|
||||
hidden: ['showcase', 'viewonly'],
|
||||
},
|
||||
},
|
||||
};
|
||||
export default Capability;
|
||||
|
@ -48,16 +48,16 @@ class Editor {
|
||||
this.component.loadMap(mapId);
|
||||
}
|
||||
|
||||
registerEvents(setToolbarsRerenderSwitch: (timestamp: number) => void, capability: Capability) {
|
||||
registerEvents(canvasUpdate: (timestamp: number) => void, capability: Capability) {
|
||||
const desiger = this.component.getDesigner();
|
||||
const onNodeBlurHandler = () => {
|
||||
if (!desiger.getModel().selectedTopic()) {
|
||||
setToolbarsRerenderSwitch(Date.now());
|
||||
canvasUpdate(Date.now());
|
||||
}
|
||||
};
|
||||
|
||||
const onNodeFocusHandler = () => {
|
||||
setToolbarsRerenderSwitch(Date.now());
|
||||
canvasUpdate(Date.now());
|
||||
};
|
||||
|
||||
// Register events ...
|
||||
|
32
packages/editor/src/classes/model/map-info/index.ts
Normal file
32
packages/editor/src/classes/model/map-info/index.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
interface MapInfo {
|
||||
isStarred(): Promise<boolean>;
|
||||
updateStarred(value: boolean): Promise<void>;
|
||||
|
||||
getTitle(): string;
|
||||
setTitle(value: string): void;
|
||||
|
||||
isLocked(): boolean;
|
||||
getLockedMessage(): string;
|
||||
|
||||
getZoom(): number;
|
||||
|
||||
getId(): string;
|
||||
}
|
||||
export default MapInfo;
|
@ -15,7 +15,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import MaterialToolbar from '@mui/material/Toolbar';
|
||||
import MaterialAppBar from '@mui/material/AppBar';
|
||||
import { ToolbarMenuItem } from '../toolbar';
|
||||
@ -40,159 +40,168 @@ import Button from '@mui/material/Button';
|
||||
import LogoTextBlackSvg from '../../../images/logo-text-black.svg';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import { ToolbarActionType } from '../toolbar/ToolbarActionType';
|
||||
import MapInfo from '../../classes/model/map-info';
|
||||
|
||||
interface AppBarProps {
|
||||
model: Editor;
|
||||
mapTitle: string;
|
||||
mapInfo: MapInfo;
|
||||
capability: Capability;
|
||||
onAction?: (type: ToolbarActionType) => void;
|
||||
accountConfig?;
|
||||
}
|
||||
const appBarDivisor = {
|
||||
render: () => <Typography component="div" sx={{ flexGrow: 1 }} />,
|
||||
};
|
||||
|
||||
const AppBar = ({ model, mapTitle, capability, onAction, accountConfig }: AppBarProps) => {
|
||||
const appBarDivisor = {
|
||||
render: () => <Typography component="div" sx={{ flexGrow: 1 }} />,
|
||||
const AppBar = ({ model, mapInfo, capability, onAction, accountConfig }: AppBarProps) => {
|
||||
const [isStarred, setStarred] = useState<undefined | boolean>(undefined);
|
||||
|
||||
const handleStarredOnClick = () => {
|
||||
const newStatus = !isStarred;
|
||||
mapInfo.updateStarred(newStatus).then(() => setStarred(newStatus));
|
||||
};
|
||||
|
||||
const buildConfig = (
|
||||
model: Editor,
|
||||
mapTitle: string,
|
||||
capability: Capability,
|
||||
onAction: (type: ToolbarActionType) => void,
|
||||
accountConfig,
|
||||
): ActionConfig[] => {
|
||||
return [
|
||||
{
|
||||
icon: <ArrowBackIosNewOutlinedIcon />,
|
||||
tooltip: $msg('BACK_TO_MAP_LIST'),
|
||||
onClick: () => history.back(),
|
||||
},
|
||||
{
|
||||
render: () => <img src={LogoTextBlackSvg} />,
|
||||
},
|
||||
{
|
||||
render: () => (
|
||||
<Tooltip title={mapTitle}>
|
||||
<Typography
|
||||
className="truncated"
|
||||
variant="body1"
|
||||
component="div"
|
||||
sx={{ marginX: '1.5rem' }}
|
||||
>
|
||||
{mapTitle}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
null,
|
||||
{
|
||||
render: () => (
|
||||
<UndoAndRedo
|
||||
configuration={{
|
||||
icon: <UndoOutlinedIcon />,
|
||||
tooltip: $msg('UNDO') + ' (' + $msg('CTRL') + ' + Z)',
|
||||
onClick: () => designer.undo(),
|
||||
}}
|
||||
disabledCondition={(event) => event.undoSteps > 0}
|
||||
></UndoAndRedo>
|
||||
),
|
||||
visible: !capability.isHidden('undo-changes'),
|
||||
disabled: () => !model?.isMapLoadded(),
|
||||
},
|
||||
{
|
||||
render: () => (
|
||||
<UndoAndRedo
|
||||
configuration={{
|
||||
icon: <RedoOutlinedIcon />,
|
||||
tooltip: $msg('REDO') + ' (' + $msg('CTRL') + ' + Shift + Z)',
|
||||
onClick: () => designer.redo(),
|
||||
}}
|
||||
disabledCondition={(event) => event.redoSteps > 0}
|
||||
></UndoAndRedo>
|
||||
),
|
||||
visible: !capability.isHidden('redo-changes'),
|
||||
disabled: () => !model?.isMapLoadded(),
|
||||
},
|
||||
null,
|
||||
{
|
||||
icon: <SaveOutlinedIcon />,
|
||||
tooltip: $msg('SAVE') + ' (' + $msg('CTRL') + ' + S)',
|
||||
onClick: () => {
|
||||
model.save(true);
|
||||
},
|
||||
visible: !capability.isHidden('save'),
|
||||
disabled: () => !model?.isMapLoadded(),
|
||||
},
|
||||
{
|
||||
icon: <RestoreOutlinedIcon />,
|
||||
tooltip: $msg('HISTORY'),
|
||||
onClick: () => onAction('history'),
|
||||
visible: !capability.isHidden('history'),
|
||||
},
|
||||
appBarDivisor,
|
||||
{
|
||||
tooltip: $msg('SAVE') + ' (' + $msg('CTRL') + ' + S)',
|
||||
render: () => (
|
||||
<IconButton size="small" onClick={() => {}}>
|
||||
<StarRateRoundedIcon
|
||||
color="action"
|
||||
style={{
|
||||
color: 'yellow',
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
),
|
||||
visible: !capability.isHidden('starred'),
|
||||
disabled: () => !model?.isMapLoadded(),
|
||||
},
|
||||
{
|
||||
icon: <FileDownloadOutlinedIcon />,
|
||||
tooltip: $msg('EXPORT'),
|
||||
onClick: () => onAction('export'),
|
||||
visible: !capability.isHidden('export'),
|
||||
},
|
||||
{
|
||||
icon: <PrintOutlinedIcon />,
|
||||
tooltip: $msg('PRINT'),
|
||||
onClick: () => onAction('print'),
|
||||
visible: !capability.isHidden('print'),
|
||||
},
|
||||
{
|
||||
icon: <HelpOutlineOutlinedIcon />,
|
||||
onClick: () => onAction('info'),
|
||||
tooltip: $msg('MAP_INFO'),
|
||||
visible: !capability.isHidden('info'),
|
||||
},
|
||||
{
|
||||
icon: <CloudUploadOutlinedIcon />,
|
||||
onClick: () => onAction('publish'),
|
||||
tooltip: $msg('PUBLISH'),
|
||||
visible: !capability.isHidden('publish'),
|
||||
},
|
||||
{
|
||||
render: () => (
|
||||
<Button variant="contained" onClick={() => onAction('share')}>
|
||||
{$msg('COLLABORATE')}
|
||||
</Button>
|
||||
),
|
||||
visible: !capability.isHidden('share'),
|
||||
},
|
||||
{
|
||||
render: () => accountConfig,
|
||||
visible: !capability.isHidden('account'),
|
||||
},
|
||||
{
|
||||
render: () => (
|
||||
<Button variant="contained" onClick={() => (window.location.href = '/c/registration')}>
|
||||
{$msg('SIGN_UP')}
|
||||
</Button>
|
||||
),
|
||||
visible: !capability.isHidden('sign-up'),
|
||||
},
|
||||
];
|
||||
};
|
||||
useEffect(() => {
|
||||
mapInfo
|
||||
.isStarred()
|
||||
.then((value) => setStarred(value))
|
||||
.catch((e) => {
|
||||
console.error(`Unexpected error loading starred status-> ${e}`);
|
||||
});
|
||||
}, []);
|
||||
|
||||
console.log(``);
|
||||
const config: ActionConfig[] = [
|
||||
{
|
||||
icon: <ArrowBackIosNewOutlinedIcon />,
|
||||
tooltip: $msg('BACK_TO_MAP_LIST'),
|
||||
onClick: () => history.back(),
|
||||
},
|
||||
{
|
||||
render: () => <img src={LogoTextBlackSvg} />,
|
||||
},
|
||||
{
|
||||
render: () => (
|
||||
<Tooltip title={mapInfo.getTitle()}>
|
||||
<Typography
|
||||
className="truncated"
|
||||
variant="body1"
|
||||
component="div"
|
||||
sx={{ marginX: '1.5rem' }}
|
||||
>
|
||||
{mapInfo.getTitle()}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
null,
|
||||
{
|
||||
render: () => (
|
||||
<UndoAndRedo
|
||||
configuration={{
|
||||
icon: <UndoOutlinedIcon />,
|
||||
tooltip: $msg('UNDO') + ' (' + $msg('CTRL') + ' + Z)',
|
||||
onClick: () => designer.undo(),
|
||||
}}
|
||||
disabledCondition={(event) => event.undoSteps > 0}
|
||||
/>
|
||||
),
|
||||
visible: !capability.isHidden('undo-changes'),
|
||||
disabled: () => !model?.isMapLoadded(),
|
||||
},
|
||||
{
|
||||
render: () => (
|
||||
<UndoAndRedo
|
||||
configuration={{
|
||||
icon: <RedoOutlinedIcon />,
|
||||
tooltip: $msg('REDO') + ' (' + $msg('CTRL') + ' + Shift + Z)',
|
||||
onClick: () => designer.redo(),
|
||||
}}
|
||||
disabledCondition={(event) => event.redoSteps > 0}
|
||||
/>
|
||||
),
|
||||
visible: !capability.isHidden('redo-changes'),
|
||||
disabled: () => !model?.isMapLoadded(),
|
||||
},
|
||||
null,
|
||||
{
|
||||
icon: <SaveOutlinedIcon />,
|
||||
tooltip: $msg('SAVE') + ' (' + $msg('CTRL') + ' + S)',
|
||||
onClick: () => {
|
||||
model.save(true);
|
||||
},
|
||||
visible: !capability.isHidden('save'),
|
||||
disabled: () => !model?.isMapLoadded(),
|
||||
},
|
||||
{
|
||||
icon: <RestoreOutlinedIcon />,
|
||||
tooltip: $msg('HISTORY'),
|
||||
onClick: () => onAction('history'),
|
||||
visible: !capability.isHidden('history'),
|
||||
},
|
||||
appBarDivisor,
|
||||
{
|
||||
tooltip: $msg('STARRED'),
|
||||
render: () => (
|
||||
<IconButton size="small" onClick={handleStarredOnClick}>
|
||||
<StarRateRoundedIcon
|
||||
color="action"
|
||||
style={{
|
||||
color: isStarred ? 'yellow' : 'gray',
|
||||
}}
|
||||
/>
|
||||
</IconButton>
|
||||
),
|
||||
|
||||
visible: !capability.isHidden('starred'),
|
||||
disabled: () => isStarred !== undefined,
|
||||
},
|
||||
{
|
||||
icon: <FileDownloadOutlinedIcon />,
|
||||
tooltip: $msg('EXPORT'),
|
||||
onClick: () => onAction('export'),
|
||||
visible: !capability.isHidden('export'),
|
||||
},
|
||||
{
|
||||
icon: <PrintOutlinedIcon />,
|
||||
tooltip: $msg('PRINT'),
|
||||
onClick: () => onAction('print'),
|
||||
visible: !capability.isHidden('print'),
|
||||
},
|
||||
{
|
||||
icon: <HelpOutlineOutlinedIcon />,
|
||||
onClick: () => onAction('info'),
|
||||
tooltip: $msg('MAP_INFO'),
|
||||
visible: !capability.isHidden('info'),
|
||||
},
|
||||
{
|
||||
icon: <CloudUploadOutlinedIcon />,
|
||||
onClick: () => onAction('publish'),
|
||||
tooltip: $msg('PUBLISH'),
|
||||
visible: !capability.isHidden('publish'),
|
||||
},
|
||||
{
|
||||
render: () => (
|
||||
<Button variant="contained" onClick={() => onAction('share')}>
|
||||
{$msg('COLLABORATE')}
|
||||
</Button>
|
||||
),
|
||||
visible: !capability.isHidden('share'),
|
||||
},
|
||||
{
|
||||
render: () => accountConfig,
|
||||
visible: !capability.isHidden('account'),
|
||||
},
|
||||
{
|
||||
render: () => (
|
||||
<Button variant="contained" onClick={() => (window.location.href = '/c/registration')}>
|
||||
{$msg('SIGN_UP')}
|
||||
</Button>
|
||||
),
|
||||
visible: !capability.isHidden('sign-up'),
|
||||
},
|
||||
];
|
||||
|
||||
const config = buildConfig(model, mapTitle, capability, onAction, accountConfig);
|
||||
return (
|
||||
<MaterialAppBar
|
||||
role="menubar"
|
||||
|
@ -15,7 +15,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { ErrorInfo, useCallback, useEffect, useState } from 'react';
|
||||
import Popover from '@mui/material/Popover';
|
||||
import Model from '../classes/model/editor';
|
||||
import { buildEditorPanelConfig, buildZoomToolbarConfig } from './toolbar/toolbarConfigBuilder';
|
||||
@ -40,19 +40,16 @@ import DefaultWidgetManager from '../classes/default-widget-manager';
|
||||
import AppBar from './app-bar';
|
||||
import Capability from '../classes/action/capability';
|
||||
import { ToolbarActionType } from './toolbar/ToolbarActionType';
|
||||
import MapInfo from '../classes/model/map-info';
|
||||
|
||||
type EditorOptions = {
|
||||
export type EditorOptions = {
|
||||
mode: EditorRenderMode;
|
||||
locale: string;
|
||||
zoom?: number;
|
||||
locked?: boolean;
|
||||
lockedMsg?: string;
|
||||
mapTitle: string;
|
||||
enableKeyboardEvents: boolean;
|
||||
};
|
||||
|
||||
type EditorProps = {
|
||||
mapId: string;
|
||||
mapInfo: MapInfo;
|
||||
options: EditorOptions;
|
||||
persistenceManager: PersistenceManager;
|
||||
onAction: (action: ToolbarActionType) => void;
|
||||
@ -62,25 +59,24 @@ type EditorProps = {
|
||||
};
|
||||
|
||||
const Editor = ({
|
||||
mapId,
|
||||
mapInfo,
|
||||
options,
|
||||
persistenceManager,
|
||||
onAction,
|
||||
theme,
|
||||
accountConfiguration,
|
||||
}: EditorProps) => {
|
||||
const [model, setModel]: [Model | undefined, Function] = useState();
|
||||
const [model, setModel] = useState<Model | undefined>();
|
||||
const [canvasUpdate, setCanvasUpdate] = useState<number>();
|
||||
const editorTheme: Theme = theme ? theme : defaultEditorTheme;
|
||||
const [toolbarsRerenderSwitch, setToolbarsRerenderSwitch] = useState(0);
|
||||
|
||||
const [popoverOpen, popoverTarget, widgetManager] = DefaultWidgetManager.create();
|
||||
const capability = new Capability(options.mode, options.locked);
|
||||
const capability = new Capability(options.mode, mapInfo.isLocked());
|
||||
|
||||
const mindplotRef = useCallback((component: MindplotWebComponent) => {
|
||||
// Initialized model ...
|
||||
const model = new Model(component);
|
||||
model.loadMindmap(mapId, persistenceManager, widgetManager);
|
||||
model.registerEvents(setToolbarsRerenderSwitch, capability);
|
||||
model.loadMindmap(mapInfo.getId(), persistenceManager, widgetManager);
|
||||
model.registerEvents(setCanvasUpdate, capability);
|
||||
setModel(model);
|
||||
}, []);
|
||||
|
||||
@ -101,7 +97,7 @@ const Editor = ({
|
||||
<IntlProvider locale={locale} messages={msg}>
|
||||
<AppBar
|
||||
model={model}
|
||||
mapTitle={options.mapTitle}
|
||||
mapInfo={mapInfo}
|
||||
capability={capability}
|
||||
onAction={onAction}
|
||||
accountConfig={accountConfiguration}
|
||||
@ -120,11 +116,9 @@ const Editor = ({
|
||||
{widgetManager.getEditorContent()}
|
||||
</Popover>
|
||||
{!capability.isHidden('edition-toolbar') && model?.isMapLoadded() && (
|
||||
<Toolbar
|
||||
configurations={buildEditorPanelConfig(model)}
|
||||
rerender={toolbarsRerenderSwitch}
|
||||
></Toolbar>
|
||||
<Toolbar configurations={buildEditorPanelConfig(model)} />
|
||||
)}
|
||||
|
||||
<Toolbar
|
||||
configurations={buildZoomToolbarConfig(model, capability)}
|
||||
position={{
|
||||
@ -134,22 +128,21 @@ const Editor = ({
|
||||
},
|
||||
vertical: false,
|
||||
}}
|
||||
rerender={toolbarsRerenderSwitch}
|
||||
></Toolbar>
|
||||
/>
|
||||
|
||||
<mindplot-component
|
||||
ref={mindplotRef}
|
||||
id="mindmap-comp"
|
||||
mode={options.mode}
|
||||
locale={options.locale}
|
||||
></mindplot-component>
|
||||
/>
|
||||
|
||||
<Notifier id="headerNotifier"></Notifier>
|
||||
<Notifier id="headerNotifier" />
|
||||
|
||||
<WarningDialog
|
||||
capability={capability}
|
||||
message={options.locked ? options.lockedMsg : ''}
|
||||
></WarningDialog>
|
||||
message={mapInfo.isLocked() ? mapInfo.getLockedMessage() : ''}
|
||||
/>
|
||||
</IntlProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
@ -34,7 +34,10 @@ import {
|
||||
Importer,
|
||||
TextImporterFactory,
|
||||
} from '@wisemapping/mindplot';
|
||||
|
||||
import Editor from './components';
|
||||
import { EditorOptions } from './components';
|
||||
import MapInfo from './classes/model/map-info';
|
||||
|
||||
declare global {
|
||||
// used in mindplot
|
||||
@ -65,6 +68,8 @@ export {
|
||||
Exporter,
|
||||
Importer,
|
||||
TextImporterFactory,
|
||||
EditorOptions,
|
||||
MapInfo,
|
||||
};
|
||||
|
||||
export default Editor;
|
||||
|
66
packages/editor/test/playground/map-render/js/MapInfoImpl.ts
Normal file
66
packages/editor/test/playground/map-render/js/MapInfoImpl.ts
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 { MapInfo } from '../../../../src';
|
||||
|
||||
class MapInfoImpl implements MapInfo {
|
||||
private id: string;
|
||||
private title: string;
|
||||
private locked: boolean;
|
||||
private starred: boolean;
|
||||
|
||||
constructor(id: string, title: string, locked: boolean) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.locked = locked;
|
||||
this.starred = true;
|
||||
}
|
||||
|
||||
isStarred(): Promise<boolean> {
|
||||
return Promise.resolve(this.starred);
|
||||
}
|
||||
|
||||
updateStarred(value: boolean): Promise<void> {
|
||||
this.starred = value;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
setTitle(value: string): void {
|
||||
throw this.title;
|
||||
}
|
||||
|
||||
isLocked(): boolean {
|
||||
return this.locked;
|
||||
}
|
||||
|
||||
getLockedMessage(): string {
|
||||
return 'Map Is Locked !';
|
||||
}
|
||||
|
||||
getZoom(): number {
|
||||
return 0.8;
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
export default MapInfoImpl;
|
@ -19,6 +19,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Editor, { EditorOptions } from '../../../../src/index';
|
||||
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
||||
import MapInfoImpl from './MapInfoImpl';
|
||||
|
||||
const initialization = (designer: Designer) => {
|
||||
designer.addEvent('loadSuccess', () => {
|
||||
@ -32,9 +33,6 @@ const initialization = (designer: Designer) => {
|
||||
const persistence = new LocalStorageManager('samples/{id}.wxml', false, false);
|
||||
const mapId = 'welcome';
|
||||
const options: EditorOptions = {
|
||||
zoom: 0.8,
|
||||
locked: false,
|
||||
mapTitle: 'Develop WiseMapping',
|
||||
mode: 'edition-owner',
|
||||
locale: 'en',
|
||||
enableKeyboardEvents: true,
|
||||
@ -42,7 +40,7 @@ const options: EditorOptions = {
|
||||
|
||||
ReactDOM.render(
|
||||
<Editor
|
||||
mapId={mapId}
|
||||
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
||||
options={options}
|
||||
persistenceManager={persistence}
|
||||
onAction={(action) => console.log('action called:', action)}
|
||||
|
@ -19,6 +19,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Editor, { EditorOptions } from '../../../../src/index';
|
||||
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
||||
import MapInfoImpl from './MapInfoImpl';
|
||||
|
||||
const initialization = (designer: Designer) => {
|
||||
designer.addEvent('loadSuccess', () => {
|
||||
@ -30,20 +31,16 @@ const initialization = (designer: Designer) => {
|
||||
};
|
||||
|
||||
const persistence = new LocalStorageManager('samples/{id}.wxml', false, false);
|
||||
const mapId = 'welcome';
|
||||
const options: EditorOptions = {
|
||||
zoom: 0.8,
|
||||
locked: true,
|
||||
lockedMsg: 'Blockeado',
|
||||
mapTitle: 'Develop WiseMapping',
|
||||
mode: 'edition-editor',
|
||||
locale: 'en',
|
||||
enableKeyboardEvents: true,
|
||||
};
|
||||
|
||||
const mapInfo = new MapInfoImpl('welcome', 'Develop WiseMapping', true);
|
||||
ReactDOM.render(
|
||||
<Editor
|
||||
mapId={mapId}
|
||||
mapInfo={mapInfo}
|
||||
options={options}
|
||||
persistenceManager={persistence}
|
||||
onAction={(action) => console.log('action called:', action)}
|
||||
|
@ -19,6 +19,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Editor, { EditorOptions } from '../../../../src/index';
|
||||
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
||||
import MapInfoImpl from './MapInfoImpl';
|
||||
|
||||
const initialization = (designer: Designer) => {
|
||||
designer.addEvent('loadSuccess', () => {
|
||||
@ -32,9 +33,6 @@ const initialization = (designer: Designer) => {
|
||||
const persistence = new LocalStorageManager('samples/{id}.wxml', false, false);
|
||||
const mapId = 'welcome';
|
||||
const options: EditorOptions = {
|
||||
zoom: 0.8,
|
||||
locked: false,
|
||||
mapTitle: 'Develop WiseMapping',
|
||||
mode: 'showcase',
|
||||
locale: 'en',
|
||||
enableKeyboardEvents: true,
|
||||
@ -42,7 +40,7 @@ const options: EditorOptions = {
|
||||
|
||||
ReactDOM.render(
|
||||
<Editor
|
||||
mapId={mapId}
|
||||
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
||||
options={options}
|
||||
persistenceManager={persistence}
|
||||
onAction={(action) => console.log('action called:', action)}
|
||||
|
@ -3,6 +3,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Editor, { EditorOptions } from '../../../../src/index';
|
||||
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
||||
import MapInfoImpl from './MapInfoImpl';
|
||||
|
||||
const initialization = (designer: Designer) => {
|
||||
designer.addEvent('loadSuccess', () => {
|
||||
@ -32,9 +33,6 @@ const params = new URLSearchParams(window.location.search.substring(1));
|
||||
const mapId = params.get('id') || 'welcome';
|
||||
const persistence = new LocalStorageManager('samples/{id}.wxml', false);
|
||||
const options: EditorOptions = {
|
||||
zoom: 0.8,
|
||||
locked: false,
|
||||
mapTitle: 'Develop WiseMapping',
|
||||
mode: 'viewonly',
|
||||
locale: 'en',
|
||||
enableKeyboardEvents: true,
|
||||
@ -42,7 +40,7 @@ const options: EditorOptions = {
|
||||
|
||||
ReactDOM.render(
|
||||
<Editor
|
||||
mapId={mapId}
|
||||
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
||||
options={options}
|
||||
persistenceManager={persistence}
|
||||
onAction={(action) => console.log('action called:', action)}
|
||||
|
@ -13,6 +13,7 @@ import AppBar from '../../../src/components/app-bar';
|
||||
import ActionConfig from '../../../src/classes/action/action-config';
|
||||
import Capability from '../../../src/classes/action/capability';
|
||||
import Editor from '../../../src/classes/model/editor';
|
||||
import MapInfoImpl from '../../playground/map-render/js/MapInfoImpl';
|
||||
|
||||
require('babel-polyfill');
|
||||
jest.mock('../../../src/components/app-bar/styles.css', () => '');
|
||||
@ -275,7 +276,14 @@ describe('AppBar', () => {
|
||||
it('When render it displays a menu', () => {
|
||||
const capacity = new Capability('edition-owner', false);
|
||||
const model = new Editor(null);
|
||||
render(<AppBar mapTitle="Some title" capability={capacity} model={model} />);
|
||||
|
||||
render(
|
||||
<AppBar
|
||||
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
||||
capability={capacity}
|
||||
model={model}
|
||||
/>,
|
||||
);
|
||||
screen.getByRole('menubar');
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="9.449 8.932 132.742 34.405" width="133px" height="34.5px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg viewBox="9.449 8.932 132.742 34.405" width="100px" height="34.5px" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="i08j30ef6a" fill="#fff">
|
||||
<path d="M 32.284 17.414 C 32.284 20.379 31.176 23.221 29.199 25.317 C 27.224 27.413 24.546 28.59 21.753 28.59 C 18.96 28.59 16.282 27.413 14.307 25.317 C 12.331 23.221 11.222 20.379 11.222 17.414 L 32.284 17.414 Z"/>
|
||||
</mask>
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@ -1,3 +1,21 @@
|
||||
/*
|
||||
* 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 Client from '../client';
|
||||
import CacheDecoratorClient from '../client/cache-decorator-client';
|
||||
import MockClient from '../client/mock-client';
|
||||
|
@ -17,6 +17,10 @@ class CacheDecoratorClient implements Client {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
fetchStarred(id: number): Promise<boolean> {
|
||||
return this.client.fetchStarred(id);
|
||||
}
|
||||
|
||||
onSessionExpired(callback?: () => void): () => void {
|
||||
return this.client.onSessionExpired(callback);
|
||||
}
|
||||
|
@ -80,6 +80,8 @@ interface Client {
|
||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
|
||||
fetchAllMaps(): Promise<MapInfo[]>;
|
||||
|
||||
fetchStarred(id: number): Promise<boolean>;
|
||||
|
||||
fetchMapPermissions(id: number): Promise<Permission[]>;
|
||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void>;
|
||||
deleteMapPermission(id: number, email: string): Promise<void>;
|
||||
|
@ -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 Client, {
|
||||
AccountInfo,
|
||||
BasicMapInfo,
|
||||
@ -108,6 +125,10 @@ class MockClient implements Client {
|
||||
this.labels = [label1, label2, label3];
|
||||
}
|
||||
|
||||
fetchStarred(id: number): Promise<boolean> {
|
||||
return Promise.resolve(this.maps.find((m) => m.id == id).starred);
|
||||
}
|
||||
|
||||
onSessionExpired(callback?: () => void): () => void {
|
||||
return callback;
|
||||
}
|
||||
@ -123,8 +144,6 @@ class MockClient implements Client {
|
||||
let perm = this.permissionsByMap.get(id) || [];
|
||||
perm = perm.concat(permissions);
|
||||
this.permissionsByMap.set(id, perm);
|
||||
|
||||
console.debug(`Message ${message}`);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,25 @@ export default class RestClient implements Client {
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
fetchStarred(id: number): Promise<boolean> {
|
||||
const handler = (success: (starred: boolean) => void, reject: (error: ErrorInfo) => void) => {
|
||||
this.axios
|
||||
.get(`${this.baseUrl}/c/restful/maps/${id}/starred`, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then((response) => {
|
||||
const data = response.data;
|
||||
success(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
|
||||
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||
|
77
packages/webapp/src/classes/editor-map-info/index.ts
Normal file
77
packages/webapp/src/classes/editor-map-info/index.ts
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 { MapInfo } from '@wisemapping/editor';
|
||||
import Client from '../client';
|
||||
|
||||
class MapInfoImpl implements MapInfo {
|
||||
private client: Client;
|
||||
private id: number;
|
||||
private title: string;
|
||||
private zoom: number;
|
||||
private locked: boolean;
|
||||
private lockedMsg: string;
|
||||
|
||||
constructor(
|
||||
id: number,
|
||||
client: Client,
|
||||
title: string,
|
||||
locked: boolean,
|
||||
lockedMsg: string,
|
||||
zoom: number,
|
||||
) {
|
||||
this.id = id;
|
||||
this.client = client;
|
||||
this.title = title;
|
||||
this.zoom = zoom;
|
||||
this.locked = locked;
|
||||
this.lockedMsg = lockedMsg;
|
||||
}
|
||||
|
||||
isStarred(): Promise<boolean> {
|
||||
return this.client.fetchStarred(this.id);
|
||||
}
|
||||
|
||||
updateStarred(value: boolean): Promise<void> {
|
||||
return this.client.updateStarred(this.id, value);
|
||||
}
|
||||
|
||||
getTitle(): string {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
setTitle(value: string): void {
|
||||
this.client.renameMap(Number.parseInt(this.getId(), 10), { title: value });
|
||||
}
|
||||
|
||||
isLocked(): boolean {
|
||||
return this.locked;
|
||||
}
|
||||
|
||||
getLockedMessage(): string {
|
||||
return this.lockedMsg;
|
||||
}
|
||||
|
||||
getZoom(): number {
|
||||
return this.zoom;
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return String(this.id);
|
||||
}
|
||||
}
|
||||
export default MapInfoImpl;
|
@ -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 React, { useEffect } from 'react';
|
||||
import ActionDispatcher from '../maps-page/action-dispatcher';
|
||||
import { ActionType } from '../maps-page/action-chooser';
|
||||
@ -13,6 +30,10 @@ import EditorOptionsBuilder from './EditorOptionsBuilder';
|
||||
import { buildPersistenceManagerForEditor } from './PersistenceManagerUtils';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import AccountMenu from '../maps-page/account-menu';
|
||||
import MapInfoImpl from '../../classes/editor-map-info';
|
||||
import { MapInfo } from '@wisemapping/editor';
|
||||
import { activeInstance } from '../../redux/clientSlice';
|
||||
import Client from '../../classes/client';
|
||||
|
||||
export type EditorPropsType = {
|
||||
isTryMode: boolean;
|
||||
@ -23,6 +44,7 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
||||
const hotkey = useSelector(hotkeysEnabled);
|
||||
const userLocale = AppI18n.getUserLocale();
|
||||
const theme = useTheme();
|
||||
const client: Client = useSelector(activeInstance);
|
||||
|
||||
useEffect(() => {
|
||||
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` });
|
||||
@ -62,16 +84,25 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
||||
const loadCompleted = mode && isAccountLoaded;
|
||||
|
||||
let options, persistence: PersistenceManager;
|
||||
let mapInfo: MapInfo;
|
||||
if (loadCompleted) {
|
||||
options = EditorOptionsBuilder.build(userLocale.code, mode, hotkey);
|
||||
persistence = buildPersistenceManagerForEditor(mode);
|
||||
mapInfo = new MapInfoImpl(
|
||||
mapId,
|
||||
client,
|
||||
options.title,
|
||||
options.isLocked,
|
||||
options.lockedMsg,
|
||||
options.zoom,
|
||||
);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (options?.mapTitle) {
|
||||
document.title = `${options.mapTitle} | WiseMapping `;
|
||||
}
|
||||
}, options?.mapTitle);
|
||||
}, [loadCompleted]);
|
||||
|
||||
return loadCompleted ? (
|
||||
<IntlProvider
|
||||
@ -83,7 +114,7 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
||||
onAction={setActiveDialog}
|
||||
options={options}
|
||||
persistenceManager={persistence}
|
||||
mapId={mapId}
|
||||
mapInfo={mapInfo}
|
||||
theme={theme}
|
||||
accountConfiguration={
|
||||
// Prevent load on non-authenticated.
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { useQuery } from 'react-query';
|
||||
|
@ -7,7 +7,6 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
module.exports = merge(common, {
|
||||
mode: 'development',
|
||||
devtool: 'source-map',
|
||||
watch: true,
|
||||
devServer: {
|
||||
contentBase: path.join(__dirname, 'dist'),
|
||||
port: 3000,
|
||||
|
Loading…
Reference in New Issue
Block a user