Add editor route and component

This commit is contained in:
Matias Arriola 2022-01-17 15:17:44 -03:00
parent 516e9b4ded
commit f84ccfdcbd
4 changed files with 179 additions and 80 deletions

View File

@ -18,7 +18,6 @@
*/ */
import $ from 'jquery'; import $ from 'jquery';
import { $msg } from '../Messages'; import { $msg } from '../Messages';
import BootstrapDialogRequest from '../libraries/bootstrap/BootstrapDialogRequest';
import IMenu from './IMenu'; import IMenu from './IMenu';
import FontFamilyPanel from './FontFamilyPanel'; import FontFamilyPanel from './FontFamilyPanel';
import FontSizePanel from './FontSizePanel'; import FontSizePanel from './FontSizePanel';
@ -38,17 +37,6 @@ class Menu extends IMenu {
const widgetsBaseUrl = `${baseUrl}css/widget`; const widgetsBaseUrl = `${baseUrl}css/widget`;
// Stop event propagation ...
$(`#${this._containerId}`).bind('click', (event) => {
event.stopPropagation();
return false;
});
$(`#${this._containerId}`).bind('dblclick', (event) => {
event.stopPropagation();
return false;
});
// Create panels ... // Create panels ...
const designerModel = designer.getModel(); const designerModel = designer.getModel();
@ -216,38 +204,8 @@ class Menu extends IMenu {
Menu._registerTooltip('fontColor', $msg('FONT_COLOR')); Menu._registerTooltip('fontColor', $msg('FONT_COLOR'));
} }
this._addButton('export', false, false, () => {
// @Todo: this must be configured in the dialog...
const formatExtension = 'jpg';
designer.export(formatExtension)
.then((url: string) => {
// Create hidden anchor to force download ...
const anchor: HTMLAnchorElement = document.createElement('a');
anchor.style.display = 'display: none';
anchor.download = `${mapId}.${formatExtension}`;
anchor.href = url;
document.body.appendChild(anchor);
// Trigger click ...
anchor.click();
// Clean up ...
URL.revokeObjectURL(url);
document.body.removeChild(anchor);
});
// Create anchor element ...
});
Menu._registerTooltip('export', $msg('EXPORT')); Menu._registerTooltip('export', $msg('EXPORT'));
this._addButton('print', false, false, () => {
this.save(saveElem, designer, false);
const urlPrefix = window.location.href.substring(0, window.location.href.lastIndexOf('c/maps/'));
window.open(`${urlPrefix}c/maps/${mapId}/print`);
});
Menu._registerTooltip('print', $msg('PRINT')); Menu._registerTooltip('print', $msg('PRINT'));
this._addButton('zoom-plus', false, false, () => { this._addButton('zoom-plus', false, false, () => {
@ -367,42 +325,6 @@ class Menu extends IMenu {
Menu._registerTooltip('discard', $msg('DISCARD_CHANGES')); Menu._registerTooltip('discard', $msg('DISCARD_CHANGES'));
} }
const shareElem = $('#shareIt');
if (shareElem.length !== 0) {
this._addButton('shareIt', false, false, () => {
new BootstrapDialogRequest(`c/maps/${mapId}/sharef`, $msg('COLLABORATE'), {
closeButton: true,
cancelButton: true,
});
designer.onObjectFocusEvent();
});
Menu._registerTooltip('shareIt', $msg('COLLABORATE'));
}
const publishElem = $('#publishIt');
if (publishElem.length !== 0) {
this._addButton('publishIt', false, false, () => {
new BootstrapDialogRequest(`c/maps/${mapId}/publishf`, $msg('PUBLISH'), {
closeButton: true,
cancelButton: true,
});
designer.onObjectFocusEvent();
});
Menu._registerTooltip('publishIt', $msg('PUBLISH'));
}
const historyElem = $('#history');
if (historyElem.length !== 0) {
this._addButton('history', false, false, () => {
new BootstrapDialogRequest(`c/maps/${mapId}/historyf`, $msg('HISTORY'), {
closeButton: true,
cancelButton: true,
});
designer.onObjectFocusEvent();
});
Menu._registerTooltip('history', $msg('HISTORY'));
}
// Keyboard Shortcuts Action ... // Keyboard Shortcuts Action ...
const keyboardShortcut = $('#keyboardShortcuts'); const keyboardShortcut = $('#keyboardShortcuts');
if (keyboardShortcut.length !== 0) { if (keyboardShortcut.length !== 0) {

View File

@ -15,6 +15,7 @@ import MapsPage from './components/maps-page';
import CssBaseline from '@material-ui/core/CssBaseline'; import CssBaseline from '@material-ui/core/CssBaseline';
import { ThemeProvider } from '@material-ui/core/styles'; import { ThemeProvider } from '@material-ui/core/styles';
import GoogleAnalytics from 'react-ga'; import GoogleAnalytics from 'react-ga';
import Editor from './components/maps-page/editor';
// Google Analytics Initialization. // Google Analytics Initialization.
GoogleAnalytics.initialize('UA-0000000-0'); GoogleAnalytics.initialize('UA-0000000-0');
@ -31,7 +32,6 @@ const queryClient = new QueryClient({
const App = (): ReactElement => { const App = (): ReactElement => {
const appi18n = new AppI18n(); const appi18n = new AppI18n();
const locale = appi18n.getBrowserLocale(); const locale = appi18n.getBrowserLocale();
return locale.message ? ( return locale.message ? (
<Provider store={store}> <Provider store={store}>
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
@ -62,9 +62,12 @@ const App = (): ReactElement => {
path="/c/forgot-password-success" path="/c/forgot-password-success"
component={ForgotPasswordSuccessPage} component={ForgotPasswordSuccessPage}
/> />
<Route path="/c/maps/"> <Route exact path="/c/maps/">
<MapsPage /> <MapsPage />
</Route> </Route>
<Route exact path="/c/maps/:id/edit">
<Editor />
</Route>
</Switch> </Switch>
</Router> </Router>
</ThemeProvider> </ThemeProvider>

View File

@ -0,0 +1,62 @@
import React from 'react';
import Toolbar from './toolbar';
import ActionDispatcher from '../action-dispatcher';
import { ActionType } from '../action-chooser';
// this component is a hack. In order to work, we need to load externally the "loader.js" script from mindplot
// TODO: create the Editor component in the editor package, with its own build and include it instead
export default function Editor(): React.ReactElement {
const memoryPersistence = false;
const readOnlyMode = false;
const mapId = 1;
const [activeDialog, setActiveDialog] = React.useState<ActionType | null>(null);
return <>
<div id="header">
<Toolbar
memoryPersistence={memoryPersistence}
readOnlyMode={readOnlyMode}
onAction={setActiveDialog} />
</div>
<div id="mindplot"></div>
<div id="floating-panel">
<div id="keyboardShortcuts" className="buttonExtOn">
<img src="../../images/editor/keyboard.svg"/>
</div>
<div id="zoom-button">
<button id="zoom-plus">
<img src="../../images/editor/add.svg" />
</button>
<button id="zoom-minus">
<img src="../../images/editor/minus.svg" />
</button>
</div>
<div id="position">
<button id="position-button">
<img src="../../images/editor/center_focus.svg" />
</button>
</div>
</div>
<div id="bottom-logo"></div>
<div id="headerNotifier"></div>
{
memoryPersistence && <div id="tryInfoPanel">
<p>TRY_WELCOME</p>
<p>TRY_WELCOME_DESC</p>
<a href="/c/registration"><div className="actionButton">
SIGN_UP</div>
</a>
</div>
}
{
activeDialog &&
<ActionDispatcher
action={activeDialog}
onClose={() => setActiveDialog(null)}
mapsId={[mapId]}
/>
}
</>
}

View File

@ -0,0 +1,112 @@
import React from 'react';
import { ActionType } from '../action-chooser';
export type ToolbarPropsType = {
memoryPersistence: boolean;
readOnlyMode: boolean;
onAction: (action: ActionType) => void;
};
export default function Toolbar({
memoryPersistence,
readOnlyMode,
onAction,
}: ToolbarPropsType): React.ReactElement {
return (
<div id="toolbar">
<div id="backToList">
<img src="../../images/editor/back-icon.svg" />
</div>
{!memoryPersistence && (
<div id="persist" className="buttonContainer">
<div id="save" className="buttonOn">
<img src="../../images/editor/save.svg" />
</div>
</div>
)}
{!readOnlyMode && (
<>
<div id="edit" className="buttonContainer">
<div id="undoEdition" className="buttonOn">
<img src="../../images/editor/undo.svg" />
</div>
<div id="redoEdition" className="buttonOn">
<img src="../../images/editor/redo.svg" />
</div>
</div>
<div id="nodeStyle" className="buttonContainer">
<div id="addTopic" className="buttonOn">
<img src="../../images/editor/topic-add.svg" />
</div>
<div id="deleteTopic" className="buttonOn">
<img src="../../images/editor/topic-delete.svg" />
</div>
<div id="topicBorder" className="buttonExtOn">
<img src="../../images/editor/topic-border.svg" />
</div>
<div id="topicColor" className="buttonExtOn">
<img src="../../images/editor/topic-color.svg" />
</div>
<div id="topicShape" className="buttonExtOn">
<img src="../../images/editor/topic-shape.svg" />
</div>
</div>
<div id="font" className="buttonContainer">
<div id="fontFamily" className="buttonOn">
<img src="../../images/editor/font-type.svg" />
</div>
<div id="fontSize" className="buttonExtOn">
<img src="../../images/editor/font-size.svg" />
</div>
<div id="fontBold" className="buttonOn">
<img src="../../images/editor/font-bold.svg" />
</div>
<div id="fontItalic" className="buttonOn">
<img src="../../images/editor/font-italic.svg" />
</div>
<div id="fontColor" className="buttonExtOn">
<img src="../../images/editor/font-color.svg" />
</div>
</div>
<div id="nodeContent" className="buttonContainer">
<div id="topicIcon" className="buttonExtOn">
<img src="../../images/editor/topic-icon.svg" />
</div>
<div id="topicNote" className="buttonOn">
<img src="../../images/editor/topic-note.svg" />
</div>
<div id="topicLink" className="buttonOn">
<img src="../../images/editor/topic-link.svg" />
</div>
<div id="topicRelation" className="buttonOn">
<img src="../../images/editor/topic-relation.svg" />
</div>
</div>
<div id="separator" className="buttonContainer"></div>
</>
)}
{!memoryPersistence && (
<div id="toolbarRight">
<div id="export" className="buttonOn" onClick={() => onAction('export')}>
<img src="../../images/editor/export.svg" />
</div>
<div id="publishIt" className="buttonOn" onClick={() => onAction('publish')}>
<img src="../../images/editor/public.svg" />
</div>
<div id="history" className="buttonOn" onClick={() => onAction('history')}>
<img src="../../images/editor/history.svg" />
</div>
<div id="print" className="buttonOn" onClick={() => onAction('print')}>
<img src="../../images/editor/print.svg" />
</div>
<div id="account">
<img src="../../images/editor/account.svg" />
</div>
<div id="share" className="actionButton" onClick={() => onAction('share')}>
SHARE
</div>
</div>
)}
</div>
);
}