Merged in features/move_menu (pull request #47)

Move Menu to editor

* Move Menu
This commit is contained in:
Paulo Veiga 2022-03-05 20:09:25 +00:00
parent 40ecda12fe
commit 2b4356d0de
34 changed files with 284 additions and 46 deletions

View File

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 281 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

View File

Before

Width:  |  Height:  |  Size: 247 B

After

Width:  |  Height:  |  Size: 247 B

View File

Before

Width:  |  Height:  |  Size: 189 B

After

Width:  |  Height:  |  Size: 189 B

View File

@ -0,0 +1,156 @@
/*
* 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 $ from 'jquery';
import Options from '@wisemapping/mindplot/src/components/Options';
import { $msg } from '@wisemapping/mindplot/src/components/Messages';
class BootstrapDialog extends Options {
constructor(title, options) {
super();
this.options = {
cancelButton: false,
closeButton: false,
acceptButton: true,
removeButton: false,
errorMessage: false,
onEventData: {},
};
this.setOptions(options);
this.options.onEventData.dialog = this;
this._native = $('<div class="modal fade" tabindex="-1"></div>').append(
'<div class="modal-dialog"></div>',
);
const content = $('<div class="modal-content"></div>');
const header = this._buildHeader(title);
if (header) {
content.append(header);
}
const body = $('<div class="modal-body"></div>');
if (this.options.errorMessage) {
const error = $('<div class="alert alert-danger"></div>');
error.hide();
body.append(error);
}
content.append(body);
const footer = this._buildFooter();
if (footer) {
content.append(footer);
}
this._native.find('.modal-dialog').append(content);
this._native.on('hidden.bs.modal', function remove() {
$(this).remove();
});
this._native.on('shown.bs.modal', this.onDialogShown);
this._native.appendTo('#mindplot-tooltips');
}
_buildFooter() {
let footer = null;
if (this.options.acceptButton || this.options.removeButton || this.options.cancelButton) {
footer = $('<div class="modal-footer" style="paddingTop:5;textAlign:center">');
}
if (this.options.acceptButton) {
this.acceptButton = $(
`<button type="button" class="btn btn-primary" id="acceptBtn" data-dismiss="modal">${$msg(
'ACCEPT',
)}</button>`,
);
footer.append(this.acceptButton);
this.acceptButton
.unbind('click')
.on('click', this.options.onEventData, this.onAcceptClick);
}
if (this.options.removeButton) {
this.removeButton = $(
`<button type="button" class="btn btn-secondary" id="removeBtn" data-dismiss="modal">${$msg(
'REMOVE',
)}</button>`,
);
footer.append(this.removeButton);
this.removeButton.on('click', this.options.onEventData, this.onRemoveClick);
}
if (this.options.cancelButton) {
footer.append(
`<button type="button" class="btn btn-secondary" data-dismiss="modal">${$msg(
'CANCEL',
)}</button>`,
);
}
return footer;
}
_buildHeader(title) {
let header = null;
if (this.options.closeButton || title) {
header = $('<div class="modal-header"></div>');
}
if (this.options.closeButton) {
header.append(
'<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>',
);
}
if (title) {
header.append(`<h2 class="modal-title">${title}</h2>`);
}
return header;
}
onAcceptClick() {
throw new Error('Unsupported operation');
}
onDialogShown() {
// Overwrite default behaviour ...
}
onRemoveClick() {
throw new Error('Unsupported operation');
}
show() {
this._native.modal();
}
setContent(content) {
const modalBody = this._native.find('.modal-body');
modalBody.append(content);
}
css(options) {
this._native.find('.modal-dialog').css(options);
}
close() {
this._native.modal('hide');
}
alertError(message) {
this._native.find('.alert-danger').text(message);
this._native.find('.alert-danger').show();
}
cleanError() {
this._native.find('.alert-danger').hide();
}
}
export default BootstrapDialog;

View File

@ -0,0 +1,68 @@
/*
* 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.
*/
class Events {
private _handlerByType;
constructor() {
this._handlerByType = {};
}
static _normalizeEventName(string: string) {
return string.replace(/^on([A-Z])/, (_full, first) => first.toLowerCase());
}
addEvent(typeName: string, fn?, internal?: boolean): Events {
const type = Events._normalizeEventName(typeName);
// Add function had not been added yet
const funByType = this._handlerByType[type] ? this._handlerByType[type] : [];
if (!funByType.includes(fn)) {
funByType.push(fn);
this._handlerByType[type] = funByType;
}
// Mark reference ...
fn.internal = Boolean(internal);
return this;
}
fireEvent(typeName: string, eventArgs?): Events {
const type = Events._normalizeEventName(typeName);
const events = this._handlerByType[type];
if (!events) return this;
const args = Array.isArray(eventArgs) ? eventArgs : [eventArgs];
events.forEach(((fn) => {
fn.apply(this, args);
}));
return this;
}
removeEvent(typeName: string, fn?): Events {
const type = Events._normalizeEventName(typeName);
const events = this._handlerByType[type];
if (events && !fn.internal) {
const index = events.indexOf(fn);
if (index !== -1) events.splice(index, 1);
}
return this;
}
}
export default Events;

View File

@ -16,12 +16,12 @@
* limitations under the License. * limitations under the License.
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import { $msg } from '../Messages'; import { $msg } from '@wisemapping/mindplot/src/components/Messages';
import PersistenceManager from '../PersistenceManager'; import PersistenceManager from '@wisemapping/mindplot/src/components/PersistenceManager';
import { $notify } from './ToolbarNotifier'; import { $notify } from '@wisemapping/mindplot/src/components/widget/ToolbarNotifier';
import { $notifyModal } from './ModalDialogNotifier'; import { $notifyModal } from '../menu/ModalDialogNotifier';
import Designer from '../Designer'; import Designer from '@wisemapping/mindplot/src/components/Designer';
import ToolbarItem from './ToolbarItem'; import ToolbarItem from '../menu/ToolbarItem';
class IMenu { class IMenu {
private _designer: Designer; private _designer: Designer;

View File

@ -17,7 +17,8 @@
*/ */
import $ from 'jquery'; import $ from 'jquery';
import ToolbarPaneItem from './ToolbarPaneItem'; import ToolbarPaneItem from './ToolbarPaneItem';
import ImageIcon from '../ImageIcon'; import { ImageIcon } from '@wisemapping/mindplot';
class IconPanel extends ToolbarPaneItem { class IconPanel extends ToolbarPaneItem {
_updateSelectedItem() { _updateSelectedItem() {

View File

@ -15,16 +15,17 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import BootstrapDialog from '../libraries/bootstrap/BootstrapDialog'; import BootstrapDialog from '../bootstrap/BootstrapDialog';
import { $msg } from '../Messages'; import { $msg } from '@wisemapping/mindplot';
class KeyboardShortcutDialog extends BootstrapDialog { class KeyboardShortcutDialog extends BootstrapDialog {
constructor() { constructor() {
super($msg('SHORTCUTS'), { super($msg('SHORTCUTS'), {
closeButton: true, closeButton: true,
acceptButton: false, acceptButton: false,
}); });
this.setContent(`<div id="keyboardTable"> this.setContent(`<div id="keyboardTable">
<table> <table>
<colgroup> <colgroup>
<col width="40%"/> <col width="40%"/>
@ -128,8 +129,8 @@ class KeyboardShortcutDialog extends BootstrapDialog {
</tbody> </tbody>
</table> </table>
</div>`); </div>`);
this.show(); this.show();
} }
} }
export default KeyboardShortcutDialog; export default KeyboardShortcutDialog;

View File

@ -17,7 +17,7 @@
*/ */
import $ from 'jquery'; import $ from 'jquery';
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import FloatingTip from './FloatingTip'; import FloatingTip from '@wisemapping/mindplot/src/components/widget/FloatingTip';
class KeyboardShortcutTooltip extends FloatingTip { class KeyboardShortcutTooltip extends FloatingTip {
constructor(buttonElem, text) { constructor(buttonElem, text) {

View File

@ -17,8 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
import $ from 'jquery'; import $ from 'jquery';
import { $msg } from '../Messages'; import { Designer } from '@wisemapping/mindplot';
import IMenu from './IMenu';
import FontFamilyPanel from './FontFamilyPanel'; import FontFamilyPanel from './FontFamilyPanel';
import FontSizePanel from './FontSizePanel'; import FontSizePanel from './FontSizePanel';
import TopicShapePanel from './TopicShapePanel'; import TopicShapePanel from './TopicShapePanel';
@ -28,7 +27,8 @@ import ToolbarItem from './ToolbarItem';
import KeyboardShortcutTooltip from './KeyboardShortcutTooltip'; import KeyboardShortcutTooltip from './KeyboardShortcutTooltip';
import KeyboardShortcutDialog from './KeyboardShortcutDialog'; import KeyboardShortcutDialog from './KeyboardShortcutDialog';
import AccountSettingsPanel from './AccountSettingsPanel'; import AccountSettingsPanel from './AccountSettingsPanel';
import Designer from '../Designer'; import IMenu from './IMenu';
import { $msg } from '@wisemapping/mindplot';
class Menu extends IMenu { class Menu extends IMenu {
constructor(designer: Designer, containerId: string, readOnly = false, baseUrl = '') { constructor(designer: Designer, containerId: string, readOnly = false, baseUrl = '') {

View File

@ -16,7 +16,6 @@
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import $ from 'jquery'; import $ from 'jquery';
import AlertImage from '../../../assets/images/alert-sign.png';
class ModalDialogNotifier { class ModalDialogNotifier {
show(message, title) { show(message, title) {
@ -29,7 +28,6 @@ class ModalDialogNotifier {
<div class="modal-body"> <div class="modal-body">
</div> </div>
<div class="alert alert-block alert-warning"> <div class="alert alert-block alert-warning">
<img src="${AlertImage}">
<div style="display: inline-block" class="alert-content"></div> <div style="display: inline-block" class="alert-content"></div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">

View File

@ -17,7 +17,7 @@
*/ */
import $ from 'jquery'; import $ from 'jquery';
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import Events from '../Events'; import Events from './Events';
class ToolbarItem extends Events { class ToolbarItem extends Events {
constructor(buttonId, fn, options) { constructor(buttonId, fn, options) {

View File

@ -17,7 +17,7 @@
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import ToolbarItem from './ToolbarItem'; import ToolbarItem from './ToolbarItem';
import FloatingTip from './FloatingTip'; import FloatingTip from '@wisemapping/mindplot/src/components/widget/FloatingTip';
class ToolbarPaneItem extends ToolbarItem { class ToolbarPaneItem extends ToolbarItem {
constructor(buttonId, model, delayInit) { constructor(buttonId, model, delayInit) {

View File

@ -13,6 +13,7 @@ import {
} from '@wisemapping/mindplot'; } from '@wisemapping/mindplot';
import './global-styled.css'; import './global-styled.css';
import I18nMsg from './classes/i18n-msg'; import I18nMsg from './classes/i18n-msg';
import Menu from './classes/menu/Menu';
declare global { declare global {
// used in mindplot // used in mindplot
@ -74,6 +75,7 @@ const Editor = ({
DesignerKeyboard.pause(); DesignerKeyboard.pause();
} }
}, [options.enableKeyboardEvents]); }, [options.enableKeyboardEvents]);
const onLoadDesigner = (mapId: string, options: EditorOptions, persistenceManager: PersistenceManager): Designer => { const onLoadDesigner = (mapId: string, options: EditorOptions, persistenceManager: PersistenceManager): Designer => {
const buildOptions = DesignerOptionsBuilder.buildOptions({ const buildOptions = DesignerOptionsBuilder.buildOptions({
persistenceManager, persistenceManager,
@ -85,7 +87,19 @@ const Editor = ({
}); });
// Build designer ... // Build designer ...
return buildDesigner(buildOptions); const result = buildDesigner(buildOptions);
// Register toolbar event ...
if (options.mode === 'edition-owner' || options.mode === 'edition-editor' || options.mode === 'showcase') {
const menu = new Menu(designer, 'toolbar');
// If a node has focus, focus can be move to another node using the keys.
designer.cleanScreen = () => {
menu.clear();
};
}
return result;
}; };
const locale = options.locale; const locale = options.locale;

View File

@ -1,7 +1,7 @@
{ {
"include": [ "include": [
"src/**/*" "src/**/*"
], , "../mindplot/src/components/widget/FloatingTip.ts" ],
"compilerOptions": { "compilerOptions": {
"jsx": "react", "jsx": "react",
"outDir": "./dist/", "outDir": "./dist/",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -19,7 +19,6 @@ import { $assert } from '@wisemapping/core-js';
import $ from 'jquery'; import $ from 'jquery';
import PersistenceManager from './PersistenceManager'; import PersistenceManager from './PersistenceManager';
import Designer from './Designer'; import Designer from './Designer';
import Menu from './widget/Menu';
import { DesignerOptions } from './DesignerOptionsBuilder'; import { DesignerOptions } from './DesignerOptionsBuilder';
let designer: Designer; let designer: Designer;
@ -36,16 +35,6 @@ export function buildDesigner(options: DesignerOptions): Designer {
$assert(persistence, 'persistence must be defined'); $assert(persistence, 'persistence must be defined');
PersistenceManager.init(persistence); PersistenceManager.init(persistence);
// Register toolbar event ...
if (options.mode === 'edition-owner' || options.mode === 'edition-editor' || options.mode === 'showcase') {
const menu = new Menu(designer, 'toolbar');
// If a node has focus, focus can be move to another node using the keys.
designer.cleanScreen = () => {
menu.clear();
};
}
return designer; return designer;
} }

View File

@ -19,11 +19,11 @@ import { $assert } from '@wisemapping/core-js';
import $ from 'jquery'; import $ from 'jquery';
import { $msg } from './Messages'; import { $msg } from './Messages';
import Icon from './Icon'; import Icon from './Icon';
import FloatingTip from './widget/FloatingTip';
import NotesImage from '../../assets/icons/notes.svg'; import NotesImage from '../../assets/icons/notes.svg';
import Topic from './Topic'; import Topic from './Topic';
import NoteModel from './model/NoteModel'; import NoteModel from './model/NoteModel';
import FeatureModel from './model/FeatureModel'; import FeatureModel from './model/FeatureModel';
import FloatingTip from './widget/FloatingTip';
class NoteIcon extends Icon { class NoteIcon extends Icon {
private _linksModel: NoteModel; private _linksModel: NoteModel;
@ -56,6 +56,7 @@ class NoteIcon extends Icon {
event.stopPropagation(); event.stopPropagation();
}); });
} }
this._tip = new FloatingTip($(me.getImage().peer._native), { this._tip = new FloatingTip($(me.getImage().peer._native), {
title: $msg('NOTE'), title: $msg('NOTE'),
// Content can also be a function of the target element! // Content can also be a function of the target element!

View File

@ -32,9 +32,13 @@ const defaultOptions = {
}; };
class FloatingTip extends Events { class FloatingTip extends Events {
private options;
private element;
constructor(element, options) { constructor(element, options) {
super();
const opts = { ...defaultOptions, ...options }; const opts = { ...defaultOptions, ...options };
super(element, opts);
this.setOptions(opts); this.setOptions(opts);
this.element = element; this.element = element;
this._createPopover(); this._createPopover();

View File

@ -18,7 +18,7 @@
import $ from 'jquery'; import $ from 'jquery';
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import { $msg } from '../Messages'; import { $msg } from '../Messages';
import BootstrapDialog from '../libraries/bootstrap/BootstrapDialog'; import BootstrapDialog from './bootstrap/BootstrapDialog';
class LinkEditor extends BootstrapDialog { class LinkEditor extends BootstrapDialog {
/** /**

View File

@ -17,7 +17,7 @@
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import $ from 'jquery'; import $ from 'jquery';
import BootstrapDialog from '../libraries/bootstrap/BootstrapDialog'; import BootstrapDialog from '../../../../editor/src/classes/bootstrap/BootstrapDialog';
import { $msg } from '../Messages'; import { $msg } from '../Messages';
class NoteEditor extends BootstrapDialog { class NoteEditor extends BootstrapDialog {

View File

@ -23,21 +23,26 @@ import Designer from './components/Designer';
import LocalStorageManager from './components/LocalStorageManager'; import LocalStorageManager from './components/LocalStorageManager';
import RESTPersistenceManager from './components/RestPersistenceManager'; import RESTPersistenceManager from './components/RestPersistenceManager';
import MockPersistenceManager from './components/MockPersistenceManager'; import MockPersistenceManager from './components/MockPersistenceManager';
import Menu from './components/widget/Menu';
import DesignerOptionsBuilder from './components/DesignerOptionsBuilder'; import DesignerOptionsBuilder from './components/DesignerOptionsBuilder';
import ImageExporterFactory from './components/export/ImageExporterFactory'; import ImageExporterFactory from './components/export/ImageExporterFactory';
import TextExporterFactory from './components/export/TextExporterFactory'; import TextExporterFactory from './components/export/TextExporterFactory';
import Exporter from './components/export/Exporter'; import Exporter from './components/export/Exporter';
import DesignerKeyboard from './components/DesignerKeyboard'; import DesignerKeyboard from './components/DesignerKeyboard';
import EditorRenderMode from './components/EditorRenderMode'; import EditorRenderMode from './components/EditorRenderMode';
import ImageIcon from './components/ImageIcon';
import { import {
buildDesigner, buildDesigner,
} from './components/DesignerBuilder'; } from './components/DesignerBuilder';
import { import {
$notify, $notify,
} from './components/widget/ToolbarNotifier'; } from './components/widget/ToolbarNotifier';
import {
$msg,
} from './components/Messages';
// This hack is required to initialize Bootstrap. In future, this should be removed. // This hack is required to initialize Bootstrap. In future, this should be removed.
const globalAny: any = global; const globalAny: any = global;
globalAny.jQuery = jquery; globalAny.jQuery = jquery;
@ -46,7 +51,6 @@ require('../../../libraries/bootstrap/js/bootstrap.min');
export { export {
Mindmap, Mindmap,
Designer, Designer,
Menu,
DesignerBuilder, DesignerBuilder,
PersistenceManager, PersistenceManager,
RESTPersistenceManager, RESTPersistenceManager,
@ -58,6 +62,8 @@ export {
TextExporterFactory, TextExporterFactory,
ImageExporterFactory, ImageExporterFactory,
Exporter, Exporter,
ImageIcon,
$notify, $notify,
$msg,
DesignerKeyboard, DesignerKeyboard,
}; };

View File

@ -15,7 +15,7 @@
}, },
"include": [ "include": [
"src/**/*" "src/**/*"
], , "../editor/src/classes/menu/AccountSettingsPanel.js", "../editor/src/classes/menu/IMenu.ts", "../editor/src/classes/bootstrap" ],
"exclude": [ "exclude": [
"node_modules" "node_modules"
] ]

View File

@ -35,6 +35,6 @@ export default class EditorOptionsBulder {
} }
static loadMapId(): number { static loadMapId(): number {
return !AppConfig.isDevelopEnv() ? global.mapId : 555; return !AppConfig.isDevelopEnv() ? global.mapId : 11;
} }
} }