mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-22 14:47:56 +01:00
Add support for emoji
Update core libraries.
This commit is contained in:
parent
906c284c24
commit
c60254aca1
@ -1,7 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
e2e:
|
e2e:
|
||||||
image: cypress/included:10.8.0
|
image: cypress/included:10.11.0
|
||||||
container_name: wisemapping-integration-tests
|
container_name: wisemapping-integration-tests
|
||||||
entrypoint: '/bin/sh -c "yarn install && yarn bootstrap && yarn build && yarn test:integration"'
|
entrypoint: '/bin/sh -c "yarn install && yarn bootstrap && yarn build && yarn test:integration"'
|
||||||
working_dir: /e2e
|
working_dir: /e2e
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
e2e:
|
e2e:
|
||||||
image: cypress/included:10.8.0
|
image: cypress/included:10.11.0
|
||||||
container_name: wisemapping-integration-tests
|
container_name: wisemapping-integration-tests
|
||||||
entrypoint: '/bin/sh -c "yarn bootstrap && yarn build && yarn test:integration"'
|
entrypoint: '/bin/sh -c "yarn bootstrap && yarn build && yarn test:integration"'
|
||||||
working_dir: /e2e
|
working_dir: /e2e
|
||||||
|
35
packages/editor/.eslintrc.json
Normal file
35
packages/editor/.eslintrc.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"prettier",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": 12,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"ignorePatterns": [
|
||||||
|
"**/dist/**/*"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"react",
|
||||||
|
"@typescript-eslint",
|
||||||
|
"react-hooks"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "error",
|
||||||
|
"@typescript-eslint/no-unused-vars": "error",
|
||||||
|
"react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
|
||||||
|
"react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
|
||||||
|
}
|
||||||
|
}
|
@ -17,52 +17,41 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": false,
|
"private": false,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/preset-env": "^7.18.6",
|
"@babel/preset-env": "^7.19.4",
|
||||||
"@babel/preset-react": "^7.18.6",
|
"@formatjs/cli": "^5.1.3",
|
||||||
"@babel/preset-typescript": "^7.16.5",
|
|
||||||
"@formatjs/cli": "^4.8.1",
|
|
||||||
"@testing-library/react": "^12.0.0",
|
"@testing-library/react": "^12.0.0",
|
||||||
"@types/jest": "^29.0.0",
|
"@types/jest": "^29.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.8.1",
|
|
||||||
"@typescript-eslint/parser": "^4.8.1",
|
|
||||||
"babel-plugin-transform-require-context": "^0.1.1",
|
"babel-plugin-transform-require-context": "^0.1.1",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"compression-webpack-plugin": "^9.2.0",
|
|
||||||
"copy-webpack-plugin": "^10.2.1",
|
"copy-webpack-plugin": "^10.2.1",
|
||||||
|
"css-loader": "^6.7.1",
|
||||||
"cypress": "^8.4.1",
|
"cypress": "^8.4.1",
|
||||||
"cypress-image-snapshot": "^4.0.1",
|
"cypress-image-snapshot": "^4.0.1",
|
||||||
"eslint": "^7.14.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-config-prettier": "^8.0.0",
|
|
||||||
"eslint-plugin-cypress": "^2.12.1",
|
|
||||||
"eslint-plugin-react": "^7.21.5",
|
|
||||||
"eslint-plugin-react-hooks": "^4.2.0",
|
|
||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"jest-transform-stub": "^2.0.0",
|
"jest-transform-stub": "^2.0.0",
|
||||||
"prettier": "^2.2.1",
|
"react": "^18.2.0",
|
||||||
"react": "^17.0.2",
|
"style-loader": "^3.3.1",
|
||||||
"react-dom": "^17.0.2",
|
|
||||||
"ts-jest": "^27.1.0",
|
"ts-jest": "^27.1.0",
|
||||||
"ts-loader": "^8.0.11",
|
"typescript": "^4.8.4",
|
||||||
"ts-node": "^9.0.0",
|
|
||||||
"typescript": "^4.1.2",
|
|
||||||
"webpack": "^5.74.0",
|
"webpack": "^5.74.0",
|
||||||
"webpack-dev-server": "^4.7.3",
|
|
||||||
"webpack-merge": "^5.8.0"
|
"webpack-merge": "^5.8.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wisemapping/mindplot": "^5.0.1",
|
"@emotion/styled": "^11.10.5",
|
||||||
"react-color": "^2.19.3"
|
"@wisemapping/mindplot": "^5.0.15",
|
||||||
|
"emoji-picker-react": "^4.4.4",
|
||||||
|
"react-color": "^2.19.3",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"styled-components": "^5.3.6"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@emotion/react": "^11.10.4",
|
"@emotion/styled": "^11.10.5",
|
||||||
"@emotion/styled": "^11.10.4",
|
|
||||||
"@mui/icons-material": "^5.9.3",
|
"@mui/icons-material": "^5.9.3",
|
||||||
"@mui/material": "^5.9.3",
|
"@mui/material": "^5.10.11",
|
||||||
"@types/styled-components": "^5.1.26",
|
"react": "^18.2.0",
|
||||||
"react": "^17.0.2",
|
"react-intl": "^5.25.1",
|
||||||
"react-dom": "^17.0.2",
|
"styled-components": "^5.3.6"
|
||||||
"react-intl": "^5.24.3",
|
|
||||||
"styled-components": "^5.3.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,30 +15,23 @@
|
|||||||
* 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 FR from './../../compiled-lang/fr.json';
|
|
||||||
import ES from './../../compiled-lang/es.json';
|
|
||||||
import EN from './../../compiled-lang/en.json';
|
|
||||||
import DE from './../../compiled-lang/de.json';
|
|
||||||
import RU from './../../compiled-lang/ru.json';
|
|
||||||
import ZH from './../../compiled-lang/zh.json';
|
|
||||||
|
|
||||||
class I18nMsg {
|
class I18nMsg {
|
||||||
static loadLocaleData(locale: string) {
|
static loadLocaleData(locale: string): Record<string, string> {
|
||||||
switch (locale) {
|
switch (locale) {
|
||||||
case 'fr':
|
case 'fr':
|
||||||
return FR;
|
return require('./../../compiled-lang/fr.json');
|
||||||
case 'en':
|
case 'en':
|
||||||
return EN;
|
return require('./../../compiled-lang/en.json');
|
||||||
case 'es':
|
case 'es':
|
||||||
return ES;
|
return require('./../../compiled-lang/es.json');
|
||||||
case 'de':
|
case 'de':
|
||||||
return DE;
|
return require('./../../compiled-lang/de.json');
|
||||||
case 'ru':
|
case 'ru':
|
||||||
return RU;
|
return require('./../../compiled-lang/ru.json');
|
||||||
case 'zh':
|
case 'zh':
|
||||||
return ZH;
|
return require('./../../compiled-lang/zh.json');
|
||||||
default:
|
default:
|
||||||
return EN;
|
return require('./../../compiled-lang/en.json');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,12 @@
|
|||||||
* 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 { Designer, MindplotWebComponent, PersistenceManager } from '@wisemapping/mindplot';
|
import {
|
||||||
|
Designer,
|
||||||
|
MindplotWebComponent,
|
||||||
|
PersistenceManager,
|
||||||
|
DesignerModel,
|
||||||
|
} from '@wisemapping/mindplot';
|
||||||
import Capability from '../../action/capability';
|
import Capability from '../../action/capability';
|
||||||
|
|
||||||
class Editor {
|
class Editor {
|
||||||
@ -43,15 +48,19 @@ class Editor {
|
|||||||
return this.component?.getDesigner();
|
return this.component?.getDesigner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getDesignerModel(): DesignerModel | undefined {
|
||||||
|
return this.getDesigner().getModel();
|
||||||
|
}
|
||||||
|
|
||||||
loadMindmap(mapId: string, persistenceManager: PersistenceManager, widgetManager): void {
|
loadMindmap(mapId: string, persistenceManager: PersistenceManager, widgetManager): void {
|
||||||
this.component.buildDesigner(persistenceManager, widgetManager);
|
this.component.buildDesigner(persistenceManager, widgetManager);
|
||||||
this.component.loadMap(mapId);
|
this.component.loadMap(mapId);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerEvents(canvasUpdate: (timestamp: number) => void, capability: Capability) {
|
registerEvents(canvasUpdate: (timestamp: number) => void, capability: Capability) {
|
||||||
const desiger = this.component.getDesigner();
|
const designer = this.component.getDesigner();
|
||||||
const onNodeBlurHandler = () => {
|
const onNodeBlurHandler = () => {
|
||||||
if (!desiger.getModel().selectedTopic()) {
|
if (!designer.getModel().selectedTopic()) {
|
||||||
canvasUpdate(Date.now());
|
canvasUpdate(Date.now());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Designer } from '@wisemapping/mindplot';
|
import { Designer, Topic } from '@wisemapping/mindplot';
|
||||||
import NodeProperty from '../node-property';
|
import NodeProperty from '../node-property';
|
||||||
import {
|
import {
|
||||||
getTheUniqueValueOrNull,
|
getTheUniqueValueOrNull,
|
||||||
@ -8,10 +8,6 @@ import {
|
|||||||
getNextValue,
|
getNextValue,
|
||||||
} from '../../../components/toolbar/ToolbarValueModelBuilder';
|
} from '../../../components/toolbar/ToolbarValueModelBuilder';
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a designer build NodePropertyValueModel instances for the mindplot node properties
|
|
||||||
*/
|
|
||||||
|
|
||||||
class NodePropertyBuilder {
|
class NodePropertyBuilder {
|
||||||
designer: Designer;
|
designer: Designer;
|
||||||
|
|
||||||
@ -26,24 +22,20 @@ class NodePropertyBuilder {
|
|||||||
noteModel: NodeProperty;
|
noteModel: NodeProperty;
|
||||||
linkModel: NodeProperty;
|
linkModel: NodeProperty;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param designer designer to change node properties values
|
|
||||||
*/
|
|
||||||
constructor(designer: Designer) {
|
constructor(designer: Designer) {
|
||||||
this.designer = designer;
|
this.designer = designer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private selectedTopic() {
|
private selectedTopic() {
|
||||||
return designer.getModel().selectedTopic();
|
return this.designer.getModel().selectedTopic();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getFontSize() {
|
private getFontSize() {
|
||||||
return designer.getModel().selectedTopic()?.getFontSize();
|
return this.designer.getModel().selectedTopic()?.getFontSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private uniqueOrNull(propertyGetter: (Topic) => any | null) {
|
private uniqueOrNull(propertyGetter: (Topic: Topic) => any | null) {
|
||||||
const nodes = designer.getModel().filterSelectedTopics();
|
const nodes = this.designer.getModel().filterSelectedTopics();
|
||||||
return getTheUniqueValueOrNull(nodes, propertyGetter);
|
return getTheUniqueValueOrNull(nodes, propertyGetter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,8 +45,8 @@ class NodePropertyBuilder {
|
|||||||
*/
|
*/
|
||||||
fontWeigthModel(): NodeProperty {
|
fontWeigthModel(): NodeProperty {
|
||||||
return {
|
return {
|
||||||
getValue: () => designer.getModel().selectedTopic()?.getFontWeight(),
|
getValue: () => this.designer.getModel().selectedTopic()?.getFontWeight(),
|
||||||
switchValue: () => designer.changeFontWeight(),
|
switchValue: () => this.designer.changeFontWeight(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +66,7 @@ class NodePropertyBuilder {
|
|||||||
if (direction === SwitchValueDirection.up) {
|
if (direction === SwitchValueDirection.up) {
|
||||||
newValue = getNextValue(fontSizes, this.getFontSize());
|
newValue = getNextValue(fontSizes, this.getFontSize());
|
||||||
}
|
}
|
||||||
designer.changeFontSize(newValue);
|
this.designer.changeFontSize(newValue);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return this.fontSizeModel;
|
return this.fontSizeModel;
|
||||||
@ -87,8 +79,8 @@ class NodePropertyBuilder {
|
|||||||
getSelectedTopicColorModel(): NodeProperty {
|
getSelectedTopicColorModel(): NodeProperty {
|
||||||
if (!this.selectedTopicColorModel)
|
if (!this.selectedTopicColorModel)
|
||||||
this.selectedTopicColorModel = {
|
this.selectedTopicColorModel = {
|
||||||
getValue: () => designer.getModel().selectedTopic()?.getBackgroundColor(),
|
getValue: () => this.designer.getModel().selectedTopic()?.getBackgroundColor(),
|
||||||
setValue: (color) => designer.changeBackgroundColor(color),
|
setValue: (color) => this.designer.changeBackgroundColor(color),
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.selectedTopicColorModel;
|
return this.selectedTopicColorModel;
|
||||||
@ -122,7 +114,7 @@ class NodePropertyBuilder {
|
|||||||
if (!this.borderColorModel)
|
if (!this.borderColorModel)
|
||||||
this.borderColorModel = {
|
this.borderColorModel = {
|
||||||
getValue: () => this.uniqueOrNull((node) => node.getBorderColor()),
|
getValue: () => this.uniqueOrNull((node) => node.getBorderColor()),
|
||||||
setValue: (hex: string) => designer.changeBorderColor(hex),
|
setValue: (hex: string) => this.designer.changeBorderColor(hex),
|
||||||
};
|
};
|
||||||
return this.borderColorModel;
|
return this.borderColorModel;
|
||||||
}
|
}
|
||||||
@ -135,7 +127,7 @@ class NodePropertyBuilder {
|
|||||||
if (!this.fontColorModel)
|
if (!this.fontColorModel)
|
||||||
this.fontColorModel = {
|
this.fontColorModel = {
|
||||||
getValue: () => this.uniqueOrNull((node) => node.getFontColor()),
|
getValue: () => this.uniqueOrNull((node) => node.getFontColor()),
|
||||||
setValue: (hex: string) => designer.changeFontColor(hex),
|
setValue: (hex: string) => this.designer.changeFontColor(hex),
|
||||||
};
|
};
|
||||||
return this.fontColorModel;
|
return this.fontColorModel;
|
||||||
}
|
}
|
||||||
@ -148,7 +140,10 @@ class NodePropertyBuilder {
|
|||||||
if (!this.topicIconModel)
|
if (!this.topicIconModel)
|
||||||
this.topicIconModel = {
|
this.topicIconModel = {
|
||||||
getValue: () => null,
|
getValue: () => null,
|
||||||
setValue: (value: string) => designer.addIconType(value),
|
setValue: (value: string) => {
|
||||||
|
const values = value.split(':');
|
||||||
|
this.designer.addIconType(values[0] as 'image' | 'emoji', values[1]);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
return this.topicIconModel;
|
return this.topicIconModel;
|
||||||
}
|
}
|
||||||
@ -177,7 +172,7 @@ class NodePropertyBuilder {
|
|||||||
if (!this.fontFamilyModel)
|
if (!this.fontFamilyModel)
|
||||||
this.fontFamilyModel = {
|
this.fontFamilyModel = {
|
||||||
getValue: () => this.uniqueOrNull((node) => node.getFontFamily()),
|
getValue: () => this.uniqueOrNull((node) => node.getFontFamily()),
|
||||||
setValue: (value: string) => designer.changeFontFamily(value),
|
setValue: (value: string) => this.designer.changeFontFamily(value),
|
||||||
};
|
};
|
||||||
return this.fontFamilyModel;
|
return this.fontFamilyModel;
|
||||||
}
|
}
|
||||||
@ -190,7 +185,7 @@ class NodePropertyBuilder {
|
|||||||
if (!this.fontStyleModel)
|
if (!this.fontStyleModel)
|
||||||
this.fontStyleModel = {
|
this.fontStyleModel = {
|
||||||
getValue: () => this.selectedTopic()?.getFontStyle(),
|
getValue: () => this.selectedTopic()?.getFontStyle(),
|
||||||
switchValue: () => designer.changeFontStyle(),
|
switchValue: () => this.designer.changeFontStyle(),
|
||||||
};
|
};
|
||||||
return this.fontStyleModel;
|
return this.fontStyleModel;
|
||||||
}
|
}
|
||||||
@ -203,7 +198,7 @@ class NodePropertyBuilder {
|
|||||||
if (!this.topicShapeModel)
|
if (!this.topicShapeModel)
|
||||||
this.topicShapeModel = {
|
this.topicShapeModel = {
|
||||||
getValue: () => this.uniqueOrNull((node) => node.getShapeType()),
|
getValue: () => this.uniqueOrNull((node) => node.getShapeType()),
|
||||||
setValue: (value: string) => designer.changeTopicShape(value),
|
setValue: (value: string) => this.designer.changeTopicShape(value),
|
||||||
};
|
};
|
||||||
return this.topicShapeModel;
|
return this.topicShapeModel;
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,12 @@ const UndoAndRedo = ({ configuration, disabledCondition, model }: UndoAndRedo) =
|
|||||||
setDisabled(!isDisabled);
|
setDisabled(!isDisabled);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
designer.removeEvent('modelUpdate', handleUpdate);
|
model.getDesigner().removeEvent('modelUpdate', handleUpdate);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
if (model.getDesigner()) {
|
if (model.getDesigner()) {
|
||||||
designer.addEvent('modelUpdate', handleUpdate);
|
model.getDesigner().addEvent('modelUpdate', handleUpdate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [model?.isMapLoadded()]);
|
}, [model?.isMapLoadded()]);
|
||||||
@ -52,7 +52,7 @@ const UndoAndRedo = ({ configuration, disabledCondition, model }: UndoAndRedo) =
|
|||||||
...configuration,
|
...configuration,
|
||||||
disabled: () => disabled,
|
disabled: () => disabled,
|
||||||
}}
|
}}
|
||||||
></ToolbarMenuItem>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default UndoAndRedo;
|
export default UndoAndRedo;
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import React from 'react';
|
||||||
|
import iconGroups from './iconGroups.json';
|
||||||
|
import { SvgImageIcon } from '@wisemapping/mindplot';
|
||||||
|
import NodeProperty from '../../../../../classes/model/node-property';
|
||||||
|
|
||||||
|
type IconImageTab = {
|
||||||
|
iconModel: NodeProperty;
|
||||||
|
};
|
||||||
|
const IconImageTab = ({ iconModel }: IconImageTab) => {
|
||||||
|
return (
|
||||||
|
<Box sx={{ width: '350px' }}>
|
||||||
|
{iconGroups.map((family, i) => (
|
||||||
|
<span>
|
||||||
|
{family.icons.map((icon) => (
|
||||||
|
<img
|
||||||
|
className="panelIcon"
|
||||||
|
key={icon}
|
||||||
|
src={SvgImageIcon.getImageUrl(icon)}
|
||||||
|
onClick={() => {
|
||||||
|
iconModel.setValue(`image:${icon}`);
|
||||||
|
}}
|
||||||
|
></img>
|
||||||
|
))}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default IconImageTab;
|
@ -15,78 +15,57 @@
|
|||||||
* 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 Box from '@mui/material/Box';
|
import React, { useEffect } from 'react';
|
||||||
import Tab from '@mui/material/Tab';
|
|
||||||
import Tabs from '@mui/material/Tabs';
|
|
||||||
import React from 'react';
|
|
||||||
import iconGroups from './iconGroups.json';
|
|
||||||
import { ImageIcon } from '@wisemapping/mindplot';
|
|
||||||
import NodeProperty from '../../../../classes/model/node-property';
|
import NodeProperty from '../../../../classes/model/node-property';
|
||||||
|
import EmojiPicker, { EmojiClickData } from 'emoji-picker-react';
|
||||||
|
import DesignerKeyboard from '@wisemapping/mindplot/src/components/DesignerKeyboard';
|
||||||
|
import IconImageTab from './image-icon-tab';
|
||||||
|
import Switch from '@mui/material/Switch';
|
||||||
|
import FormGroup from '@mui/material/FormGroup';
|
||||||
|
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||||
|
|
||||||
/**
|
type IconPickerProp = {
|
||||||
* emoji picker for editor toolbar
|
closeModal: () => void;
|
||||||
*/
|
iconModel: NodeProperty;
|
||||||
const IconPicker = (props: { closeModal: () => void; iconModel: NodeProperty }) => {
|
};
|
||||||
const [value, setValue] = React.useState(0);
|
|
||||||
|
|
||||||
const handleChange = (event: React.SyntheticEvent, newValue: number) => {
|
const IconPicker = ({ closeModal, iconModel }: IconPickerProp) => {
|
||||||
setValue(newValue);
|
const [checked, setChecked] = React.useState(true);
|
||||||
|
|
||||||
|
const handleCheck = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setChecked(!checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Review ...
|
||||||
|
useEffect(() => {
|
||||||
|
DesignerKeyboard.pause();
|
||||||
|
return () => { DesignerKeyboard.resume(); }
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
const handleEmojiSelect = (emoji: EmojiClickData) => {
|
||||||
|
const emojiChar = emoji.emoji;
|
||||||
|
iconModel.setValue(`emoji:${emojiChar}`);
|
||||||
|
closeModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: '250px' }}>
|
<div style={{ padding: '5px' }}>
|
||||||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
<FormGroup>
|
||||||
<Tabs variant="fullWidth" value={value} onChange={handleChange} aria-label="Icons tabs">
|
<FormControlLabel label="Show Images" control={<Switch onChange={handleCheck} />} />
|
||||||
{iconGroups.map((family, i) => (
|
</FormGroup>
|
||||||
<Tab
|
|
||||||
key={family.id}
|
{checked && (
|
||||||
icon={<img className="panelIcon" src={ImageIcon.getImageUrl(family.icons[0])} />}
|
<EmojiPicker
|
||||||
{...a11yProps(i)}
|
onEmojiClick={handleEmojiSelect}
|
||||||
|
lazyLoadEmojis={true}
|
||||||
|
autoFocusSearch={true}
|
||||||
|
previewConfig={{ showPreview: false }}
|
||||||
/>
|
/>
|
||||||
))}
|
)}
|
||||||
</Tabs>
|
|
||||||
</Box>
|
|
||||||
{iconGroups.map((family, i) => (
|
|
||||||
<TabPanel key={family.id} value={value} index={i}>
|
|
||||||
{family.icons.map((icon) => (
|
|
||||||
<img
|
|
||||||
className="panelIcon"
|
|
||||||
key={icon}
|
|
||||||
src={ImageIcon.getImageUrl(icon)}
|
|
||||||
onClick={() => {
|
|
||||||
props.iconModel.setValue(icon);
|
|
||||||
props.closeModal();
|
|
||||||
}}
|
|
||||||
></img>
|
|
||||||
))}
|
|
||||||
</TabPanel>
|
|
||||||
))}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
{!checked && <IconImageTab iconModel={iconModel} />}
|
||||||
* tab panel used for display icon families in tabs
|
|
||||||
*/
|
|
||||||
const TabPanel = (props: { children?: React.ReactNode; index: number; value: number }) => {
|
|
||||||
const { children, value, index } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
role="tabpanel"
|
|
||||||
hidden={value !== index}
|
|
||||||
id={`simple-tabpanel-${index}`}
|
|
||||||
aria-labelledby={`simple-tab-${index}`}
|
|
||||||
>
|
|
||||||
{value === index && <Box>{children}</Box>}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const a11yProps = (index: number) => {
|
|
||||||
return {
|
|
||||||
id: `simple-tab-${index}`,
|
|
||||||
'aria-controls': `simple-tabpanel-${index}`,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export default IconPicker;
|
export default IconPicker;
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
* 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 { $msg } from '@wisemapping/mindplot';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ const AppBar = ({ model, mapInfo, capability, onAction, accountConfig }: AppBarP
|
|||||||
intl.formatMessage({ id: 'appbar.tooltip-undo', defaultMessage: 'Undo' }),
|
intl.formatMessage({ id: 'appbar.tooltip-undo', defaultMessage: 'Undo' }),
|
||||||
'Z',
|
'Z',
|
||||||
),
|
),
|
||||||
onClick: () => designer.undo(),
|
onClick: () => model.getDesigner().undo(),
|
||||||
}}
|
}}
|
||||||
disabledCondition={(event) => event.undoSteps > 0}
|
disabledCondition={(event) => event.undoSteps > 0}
|
||||||
model={model}
|
model={model}
|
||||||
@ -134,7 +134,7 @@ const AppBar = ({ model, mapInfo, capability, onAction, accountConfig }: AppBarP
|
|||||||
intl.formatMessage({ id: 'appbar.tooltip-redo', defaultMessage: 'Redo' }),
|
intl.formatMessage({ id: 'appbar.tooltip-redo', defaultMessage: 'Redo' }),
|
||||||
'Shift + Z',
|
'Shift + Z',
|
||||||
),
|
),
|
||||||
onClick: () => designer.redo(),
|
onClick: () => model.getDesigner().redo(),
|
||||||
}}
|
}}
|
||||||
disabledCondition={(event) => event.redoSteps > 0}
|
disabledCondition={(event) => event.redoSteps > 0}
|
||||||
model={model}
|
model={model}
|
||||||
|
@ -146,7 +146,7 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
disabled: () => designer.getModel().filterSelectedTopics().length === 0,
|
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -230,7 +230,7 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
disabled: () => designer.getModel().filterSelectedTopics().length === 0,
|
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,9 +243,9 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
defaultMessage: 'Add Relationship',
|
defaultMessage: 'Add Relationship',
|
||||||
}),
|
}),
|
||||||
onClick: (e) => {
|
onClick: (e) => {
|
||||||
designer.showRelPivot(e);
|
model.getDesigner().showRelPivot(e);
|
||||||
},
|
},
|
||||||
disabled: () => designer.getModel().filterSelectedTopics().length === 0,
|
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -268,7 +268,7 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
disabled: () => designer.getModel().filterSelectedTopics().length === 0,
|
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -292,7 +292,7 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
disabled: () => designer.getModel().filterSelectedTopics().length === 0,
|
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -304,6 +304,7 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
id: 'editor-panel.tooltip-add-icon',
|
id: 'editor-panel.tooltip-add-icon',
|
||||||
defaultMessage: 'Add Icon',
|
defaultMessage: 'Add Icon',
|
||||||
}),
|
}),
|
||||||
|
useClickToClose: true,
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
tooltip: 'Node icon',
|
tooltip: 'Node icon',
|
||||||
@ -315,7 +316,7 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
disabled: () => designer.getModel().filterSelectedTopics().length === 0,
|
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const addNodeToolbarConfiguration = {
|
const addNodeToolbarConfiguration = {
|
||||||
@ -323,9 +324,10 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
tooltip:
|
tooltip:
|
||||||
intl.formatMessage({ id: 'editor-panel.tooltip-add-topic', defaultMessage: 'Add Topic' }) +
|
intl.formatMessage({ id: 'editor-panel.tooltip-add-topic', defaultMessage: 'Add Topic' }) +
|
||||||
' (Enter)',
|
' (Enter)',
|
||||||
onClick: () => designer.createSiblingForSelectedNode(),
|
onClick: () => model.getDesigner().createSiblingForSelectedNode(),
|
||||||
disabled: () => designer.getModel().filterSelectedTopics().length === 0,
|
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteNodeToolbarConfiguration = {
|
const deleteNodeToolbarConfiguration = {
|
||||||
icon: <RemoveCircleOutlineIcon />,
|
icon: <RemoveCircleOutlineIcon />,
|
||||||
tooltip:
|
tooltip:
|
||||||
@ -333,9 +335,10 @@ export function buildEditorPanelConfig(model: Editor): ActionConfig[] {
|
|||||||
id: 'editor-panel.tooltip-delete-topic',
|
id: 'editor-panel.tooltip-delete-topic',
|
||||||
defaultMessage: 'Delete Topic',
|
defaultMessage: 'Delete Topic',
|
||||||
}) + ' (Delete)',
|
}) + ' (Delete)',
|
||||||
onClick: () => designer.deleteSelectedEntities(),
|
onClick: () => model.getDesigner().deleteSelectedEntities(),
|
||||||
disabled: () => designer.getModel().filterSelectedTopics().length === 0,
|
disabled: () => model.getDesigner().getModel().filterSelectedTopics().length === 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return [
|
return [
|
||||||
addNodeToolbarConfiguration,
|
addNodeToolbarConfiguration,
|
||||||
deleteNodeToolbarConfiguration,
|
deleteNodeToolbarConfiguration,
|
||||||
|
@ -93,7 +93,6 @@ const Editor = ({
|
|||||||
// Initialize locate ...
|
// Initialize locate ...
|
||||||
const locale = options.locale;
|
const locale = options.locale;
|
||||||
const msg = I18nMsg.loadLocaleData(locale);
|
const msg = I18nMsg.loadLocaleData(locale);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={editorTheme}>
|
<ThemeProvider theme={editorTheme}>
|
||||||
<IntlProvider locale={locale} messages={msg}>
|
<IntlProvider locale={locale} messages={msg}>
|
||||||
|
@ -53,7 +53,7 @@ export function buildZoomToolbarConfig(model: Editor, capability: Capability): A
|
|||||||
%
|
%
|
||||||
{!model?.isMapLoadded()
|
{!model?.isMapLoadded()
|
||||||
? 100
|
? 100
|
||||||
: Math.floor((1 / designer.getWorkSpace()?.getZoom()) * 100)}
|
: Math.floor((1 / model.getDesigner().getWorkSpace()?.getZoom()) * 100)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
),
|
),
|
||||||
|
@ -19,8 +19,8 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.panelIcon {
|
.panelIcon {
|
||||||
width: 20px;
|
width: 25px;
|
||||||
height: 20px;
|
height: 25px;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -33,6 +33,7 @@ import {
|
|||||||
Exporter,
|
Exporter,
|
||||||
Importer,
|
Importer,
|
||||||
TextImporterFactory,
|
TextImporterFactory,
|
||||||
|
XMLSerializerFactory,
|
||||||
} from '@wisemapping/mindplot';
|
} from '@wisemapping/mindplot';
|
||||||
|
|
||||||
import Editor from './components';
|
import Editor from './components';
|
||||||
@ -41,7 +42,6 @@ import MapInfo from './classes/model/map-info';
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// used in mindplot
|
// used in mindplot
|
||||||
var designer: Designer;
|
|
||||||
var accountEmail: string;
|
var accountEmail: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +70,7 @@ export {
|
|||||||
TextImporterFactory,
|
TextImporterFactory,
|
||||||
EditorOptions,
|
EditorOptions,
|
||||||
MapInfo,
|
MapInfo,
|
||||||
|
XMLSerializerFactory,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Editor;
|
export default Editor;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import { createRoot } from 'react-dom/client';
|
||||||
import Editor, { EditorOptions } from '../../../../src/index';
|
import Editor, { EditorOptions } from '../../../../src/index';
|
||||||
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
||||||
import MapInfoImpl from './MapInfoImpl';
|
import MapInfoImpl from './MapInfoImpl';
|
||||||
@ -37,13 +37,14 @@ const options: EditorOptions = {
|
|||||||
enableKeyboardEvents: true,
|
enableKeyboardEvents: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
ReactDOM.render(
|
const container = document.getElementById('root');
|
||||||
|
const root = createRoot(container!);
|
||||||
|
root.render(
|
||||||
<Editor
|
<Editor
|
||||||
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
||||||
options={options}
|
options={options}
|
||||||
persistenceManager={persistence}
|
persistenceManager={persistence}
|
||||||
onAction={(action) => console.log('action called:', action)}
|
onAction={(action) => console.log('action called:', action)}
|
||||||
onLoad={initialization}
|
onLoad={initialization}
|
||||||
/>,
|
/>
|
||||||
document.getElementById('root'),
|
|
||||||
);
|
);
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import { createRoot } from 'react-dom/client';
|
||||||
import Editor, { EditorOptions } from '../../../../src/index';
|
import Editor, { EditorOptions } from '../../../../src/index';
|
||||||
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
||||||
import MapInfoImpl from './MapInfoImpl';
|
import MapInfoImpl from './MapInfoImpl';
|
||||||
@ -38,13 +38,14 @@ const options: EditorOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const mapInfo = new MapInfoImpl('welcome', 'Develop WiseMapping', true);
|
const mapInfo = new MapInfoImpl('welcome', 'Develop WiseMapping', true);
|
||||||
ReactDOM.render(
|
|
||||||
<Editor
|
const container = document.getElementById('root');
|
||||||
|
const root = createRoot(container!);
|
||||||
|
root.render(<Editor
|
||||||
mapInfo={mapInfo}
|
mapInfo={mapInfo}
|
||||||
options={options}
|
options={options}
|
||||||
persistenceManager={persistence}
|
persistenceManager={persistence}
|
||||||
onAction={(action) => console.log('action called:', action)}
|
onAction={(action) => console.log('action called:', action)}
|
||||||
onLoad={initialization}
|
onLoad={initialization}
|
||||||
/>,
|
/>
|
||||||
document.getElementById('root'),
|
|
||||||
);
|
);
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import Editor, { EditorOptions } from '../../../../src/index';
|
import Editor, { EditorOptions } from '../../../../src/index';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
||||||
import MapInfoImpl from './MapInfoImpl';
|
import MapInfoImpl from './MapInfoImpl';
|
||||||
|
|
||||||
@ -38,7 +38,9 @@ const options: EditorOptions = {
|
|||||||
enableKeyboardEvents: true,
|
enableKeyboardEvents: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
ReactDOM.render(
|
const container = document.getElementById('app');
|
||||||
|
const root = createRoot(container!);
|
||||||
|
root.render(
|
||||||
<Editor
|
<Editor
|
||||||
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
||||||
options={options}
|
options={options}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import '../css/viewmode.css';
|
import '../css/viewmode.css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import Editor, { EditorOptions } from '../../../../src/index';
|
import Editor, { EditorOptions } from '../../../../src/index';
|
||||||
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
import { LocalStorageManager, Designer } from '@wisemapping/mindplot';
|
||||||
import MapInfoImpl from './MapInfoImpl';
|
import MapInfoImpl from './MapInfoImpl';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
const initialization = (designer: Designer) => {
|
const initialization = (designer: Designer) => {
|
||||||
designer.addEvent('loadSuccess', () => {
|
designer.addEvent('loadSuccess', () => {
|
||||||
@ -38,13 +38,13 @@ const options: EditorOptions = {
|
|||||||
enableKeyboardEvents: true,
|
enableKeyboardEvents: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
ReactDOM.render(
|
const container = document.getElementById('root');
|
||||||
|
const root = createRoot(container!);
|
||||||
|
root.render(
|
||||||
<Editor
|
<Editor
|
||||||
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
mapInfo={new MapInfoImpl('welcome', 'Develop Map Title', false)}
|
||||||
options={options}
|
options={options}
|
||||||
persistenceManager={persistence}
|
persistenceManager={persistence}
|
||||||
onAction={(action) => console.log('action called:', action)}
|
onAction={(action) => console.log('action called:', action)}
|
||||||
onLoad={initialization}
|
onLoad={initialization}
|
||||||
/>,
|
/>);
|
||||||
document.getElementById('root'),
|
|
||||||
);
|
|
||||||
|
@ -9,7 +9,6 @@ const prodConfig = {
|
|||||||
},
|
},
|
||||||
externals: {
|
externals: {
|
||||||
react: 'react',
|
react: 'react',
|
||||||
'react-dom': 'react-dom',
|
|
||||||
'react-intl': 'react-intl',
|
'react-intl': 'react-intl',
|
||||||
},
|
},
|
||||||
plugins: [new CleanWebpackPlugin()],
|
plugins: [new CleanWebpackPlugin()],
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
"@types/jquery": "^3.5.11",
|
"@types/jquery": "^3.5.11",
|
||||||
"@wisemapping/core-js": "^0.4.0",
|
"@wisemapping/core-js": "^0.4.0",
|
||||||
"@wisemapping/web2d": "^0.4.0",
|
"@wisemapping/web2d": "^0.4.0",
|
||||||
|
"emoji-picker-react": "^4.4.3",
|
||||||
"jest": "^27.4.5",
|
"jest": "^27.4.5",
|
||||||
"jquery": "3.6.0",
|
"jquery": "3.6.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
@ -873,16 +873,16 @@ class Designer extends Events {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addIconType(iconType: string): void {
|
addIconType(type: 'image' | 'emoji', iconType: string): void {
|
||||||
const topicsIds = this.getModel().filterTopicsIds();
|
const topicsIds = this.getModel().filterTopicsIds();
|
||||||
|
|
||||||
|
const featureType: FeatureType = (
|
||||||
|
type === 'emoji' ? TopicFeatureFactory.EmojiIcon.id : TopicFeatureFactory.SvgIcon.id
|
||||||
|
) as FeatureType;
|
||||||
if (topicsIds.length > 0) {
|
if (topicsIds.length > 0) {
|
||||||
this._actionDispatcher.addFeatureToTopic(
|
this._actionDispatcher.addFeatureToTopic(topicsIds[0], featureType, {
|
||||||
topicsIds[0],
|
|
||||||
TopicFeatureFactory.Icon.id as FeatureType,
|
|
||||||
{
|
|
||||||
id: iconType,
|
id: iconType,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
99
packages/mindplot/src/components/EmojiCharIcon.ts
Normal file
99
packages/mindplot/src/components/EmojiCharIcon.ts
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* 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 { Text, Group, ElementClass, Point } from '@wisemapping/web2d';
|
||||||
|
import { $assert } from '@wisemapping/core-js';
|
||||||
|
|
||||||
|
import Icon from './Icon';
|
||||||
|
import IconGroup from './IconGroup';
|
||||||
|
import SvgIconModel from './model/SvgIconModel';
|
||||||
|
import SizeType from './SizeType';
|
||||||
|
import Topic from './Topic';
|
||||||
|
import ActionDispatcher from './ActionDispatcher';
|
||||||
|
|
||||||
|
class EmojiCharIcon implements Icon {
|
||||||
|
private char: string;
|
||||||
|
|
||||||
|
private element: ElementClass;
|
||||||
|
|
||||||
|
private group: IconGroup;
|
||||||
|
|
||||||
|
private iconModel: SvgIconModel;
|
||||||
|
|
||||||
|
private topic: Topic;
|
||||||
|
|
||||||
|
constructor(topic: Topic, iconModel: SvgIconModel, readOnly: boolean) {
|
||||||
|
$assert(iconModel, 'iconModel can not be null');
|
||||||
|
$assert(topic, 'topic can not be null');
|
||||||
|
this.iconModel = iconModel;
|
||||||
|
this.topic = topic;
|
||||||
|
|
||||||
|
this.element = new Group({
|
||||||
|
width: 90,
|
||||||
|
height: 90,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
coordSizeWidth: 15,
|
||||||
|
coordSizeHeight: 15,
|
||||||
|
coordOriginY: 2,
|
||||||
|
});
|
||||||
|
const iconText = new Text();
|
||||||
|
iconText.setText(iconModel.getIconType());
|
||||||
|
this.element.append(iconText);
|
||||||
|
|
||||||
|
// Add events ...
|
||||||
|
if (!readOnly) {
|
||||||
|
this.element.setCursor('pointer');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getElement(): ElementClass {
|
||||||
|
return this.element;
|
||||||
|
}
|
||||||
|
|
||||||
|
setGroup(group: IconGroup) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroup(): IconGroup {
|
||||||
|
return this.group;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSize(): SizeType {
|
||||||
|
return this.group.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
getPosition(): Point {
|
||||||
|
return this.group.getPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
addEvent(type: string, fnc: any): void {
|
||||||
|
this.element.addEvent(type, fnc);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
const actionDispatcher = ActionDispatcher.getInstance();
|
||||||
|
const featureId = this.iconModel.getId();
|
||||||
|
actionDispatcher.removeFeatureFromTopic(this.topic.getId(), featureId);
|
||||||
|
}
|
||||||
|
|
||||||
|
getModel(): SvgIconModel {
|
||||||
|
return this.iconModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EmojiCharIcon;
|
@ -1,70 +1,23 @@
|
|||||||
/*
|
import { Point, ElementClass } from '@wisemapping/web2d';
|
||||||
* 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 { $assert } from '@wisemapping/core-js';
|
|
||||||
import { Image, Point } from '@wisemapping/web2d';
|
|
||||||
import IconGroup from './IconGroup';
|
import IconGroup from './IconGroup';
|
||||||
import SizeType from './SizeType';
|
import SizeType from './SizeType';
|
||||||
import FeatureModel from './model/FeatureModel';
|
|
||||||
|
|
||||||
abstract class Icon {
|
interface Icon {
|
||||||
protected _image: Image;
|
getElement(): ElementClass;
|
||||||
|
|
||||||
protected _group: IconGroup;
|
setGroup(group: IconGroup);
|
||||||
|
|
||||||
constructor(url: string) {
|
getGroup(): IconGroup;
|
||||||
$assert(url, 'image url can not be null');
|
|
||||||
this._image = new Image();
|
|
||||||
this._image.setHref(url);
|
|
||||||
this._image.setSize(Icon.SIZE, Icon.SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
getImage(): Image {
|
getSize(): SizeType;
|
||||||
return this._image;
|
|
||||||
}
|
|
||||||
|
|
||||||
setGroup(group: IconGroup) {
|
getPosition(): Point;
|
||||||
this._group = group;
|
|
||||||
}
|
|
||||||
|
|
||||||
getGroup(): IconGroup {
|
addEvent(type: string, fnc): void;
|
||||||
return this._group;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSize(): SizeType {
|
remove(): void;
|
||||||
return this._image.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
getPosition(): Point {
|
getModel();
|
||||||
return this._image.getPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
addEvent(type: string, fnc): void {
|
|
||||||
this._image.addEvent(type, fnc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line class-methods-use-this
|
|
||||||
remove() {
|
|
||||||
throw new Error('Unsupported operation');
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract getModel(): FeatureModel;
|
|
||||||
|
|
||||||
static SIZE = 90;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Icon;
|
export default Icon;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
import { $assert, $defined } from '@wisemapping/core-js';
|
import { $assert, $defined } from '@wisemapping/core-js';
|
||||||
import { Group, ElementClass, Point } from '@wisemapping/web2d';
|
import { Group, ElementClass, Point } from '@wisemapping/web2d';
|
||||||
import IconGroupRemoveTip from './IconGroupRemoveTip';
|
import IconGroupRemoveTip from './IconGroupRemoveTip';
|
||||||
import Icon from './Icon';
|
import ImageIcon from './ImageIcon';
|
||||||
import SizeType from './SizeType';
|
import SizeType from './SizeType';
|
||||||
import FeatureModel from './model/FeatureModel';
|
import FeatureModel from './model/FeatureModel';
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ ORDER_BY_TYPE.set('note', 1);
|
|||||||
ORDER_BY_TYPE.set('link', 2);
|
ORDER_BY_TYPE.set('link', 2);
|
||||||
|
|
||||||
class IconGroup {
|
class IconGroup {
|
||||||
private _icons: Icon[];
|
private _icons: ImageIcon[];
|
||||||
|
|
||||||
private _group: any;
|
private _group: any;
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ class IconGroup {
|
|||||||
this._resize(this._icons.length);
|
this._resize(this._icons.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
addIcon(icon: Icon, remove: boolean) {
|
addIcon(icon: ImageIcon, remove: boolean) {
|
||||||
$defined(icon, 'icon is not defined');
|
$defined(icon, 'icon is not defined');
|
||||||
|
|
||||||
// Order could have change, need to re-add all.
|
// Order could have change, need to re-add all.
|
||||||
@ -104,7 +104,7 @@ class IconGroup {
|
|||||||
this._resize(this._icons.length);
|
this._resize(this._icons.length);
|
||||||
this._icons.forEach((i, index) => {
|
this._icons.forEach((i, index) => {
|
||||||
this._positionIcon(i, index);
|
this._positionIcon(i, index);
|
||||||
const imageShape = i.getImage();
|
const imageShape = i.getElement();
|
||||||
this._group.append(imageShape);
|
this._group.append(imageShape);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -140,11 +140,11 @@ class IconGroup {
|
|||||||
this._removeIcon(icon);
|
this._removeIcon(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _removeIcon(icon: Icon) {
|
private _removeIcon(icon: ImageIcon) {
|
||||||
$assert(icon, 'icon can not be null');
|
$assert(icon, 'icon can not be null');
|
||||||
|
|
||||||
this._removeTip.close(0);
|
this._removeTip.close(0);
|
||||||
this._group.removeChild(icon.getImage());
|
this._group.removeChild(icon.getElement());
|
||||||
|
|
||||||
this._icons = this._icons.filter((i) => i !== icon);
|
this._icons = this._icons.filter((i) => i !== icon);
|
||||||
this._resize(this._icons.length);
|
this._resize(this._icons.length);
|
||||||
@ -175,13 +175,15 @@ class IconGroup {
|
|||||||
private _resize(iconsLength: number) {
|
private _resize(iconsLength: number) {
|
||||||
this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height);
|
this._group.setSize(iconsLength * this._iconSize.width, this._iconSize.height);
|
||||||
|
|
||||||
const iconSize = Icon.SIZE + IconGroup.ICON_PADDING * 2;
|
const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2;
|
||||||
this._group.setCoordSize(iconsLength * iconSize, iconSize);
|
this._group.setCoordSize(iconsLength * iconSize, iconSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _positionIcon(icon: Icon, order: number) {
|
private _positionIcon(icon: ImageIcon, order: number) {
|
||||||
const iconSize = Icon.SIZE + IconGroup.ICON_PADDING * 2;
|
const iconSize = ImageIcon.SIZE + IconGroup.ICON_PADDING * 2;
|
||||||
icon.getImage().setPosition(iconSize * order + IconGroup.ICON_PADDING, IconGroup.ICON_PADDING);
|
icon
|
||||||
|
.getElement()
|
||||||
|
.setPosition(iconSize * order + IconGroup.ICON_PADDING, IconGroup.ICON_PADDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ICON_PADDING = 5;
|
static ICON_PADDING = 5;
|
||||||
|
@ -1,338 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { $assert } from '@wisemapping/core-js';
|
|
||||||
import Icon from './Icon';
|
|
||||||
import ActionDispatcher from './ActionDispatcher';
|
|
||||||
|
|
||||||
function importAll(r) {
|
|
||||||
const images = {};
|
|
||||||
r.keys().forEach((item) => {
|
|
||||||
images[item.replace('./', '')] = r(item);
|
|
||||||
});
|
|
||||||
return images;
|
|
||||||
}
|
|
||||||
|
|
||||||
const images = importAll(require.context('../../assets/icons', false, /\.(png|svg)$/));
|
|
||||||
|
|
||||||
class ImageIcon extends Icon {
|
|
||||||
constructor(topic, iconModel, readOnly) {
|
|
||||||
$assert(iconModel, 'iconModel can not be null');
|
|
||||||
$assert(topic, 'topic can not be null');
|
|
||||||
|
|
||||||
// Build graph image representation ...
|
|
||||||
let iconType = iconModel.getIconType();
|
|
||||||
|
|
||||||
// Hack for overwrite wrong icon. Remove in couple of months ...
|
|
||||||
if (iconType === 'meeetapps_facebook-messenger') {
|
|
||||||
iconType = 'meetapps_facebook-messenger';
|
|
||||||
}
|
|
||||||
|
|
||||||
const imgUrl = ImageIcon.getImageUrl(iconType);
|
|
||||||
super(imgUrl);
|
|
||||||
|
|
||||||
this._topicId = topic.getId();
|
|
||||||
this._featureModel = iconModel;
|
|
||||||
|
|
||||||
if (!readOnly) {
|
|
||||||
// Icon
|
|
||||||
const image = this.getImage();
|
|
||||||
const me = this;
|
|
||||||
image.addEvent('click', () => {
|
|
||||||
const iconTypeClick = iconModel.getIconType();
|
|
||||||
const newIconType = ImageIcon._getNextFamilyIconId(iconTypeClick);
|
|
||||||
iconModel.setIconType(newIconType);
|
|
||||||
|
|
||||||
me._image.setHref(ImageIcon.getImageUrl(newIconType));
|
|
||||||
});
|
|
||||||
this._image.setCursor('pointer');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static getImageUrl(iconId) {
|
|
||||||
let result = images[`${iconId}.svg`];
|
|
||||||
if (!result) {
|
|
||||||
result = images[`${iconId}.png`];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
getModel() {
|
|
||||||
return this._featureModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _getNextFamilyIconId(iconId) {
|
|
||||||
const familyIcons = ImageIcon._getFamilyIcons(iconId);
|
|
||||||
$assert(familyIcons !== null, `Family Icon not found: ${iconId}`);
|
|
||||||
|
|
||||||
let result = null;
|
|
||||||
for (let i = 0; i < familyIcons.length && result == null; i++) {
|
|
||||||
if (familyIcons[i] === iconId) {
|
|
||||||
// Is last one?
|
|
||||||
if (i === familyIcons.length - 1) {
|
|
||||||
[result] = familyIcons;
|
|
||||||
} else {
|
|
||||||
result = familyIcons[i + 1];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _getFamilyIcons(iconId) {
|
|
||||||
$assert(iconId != null, 'id must not be null');
|
|
||||||
$assert(iconId.indexOf('_') !== -1, `Invalid icon id (it must contain '_'). Id: ${iconId}`);
|
|
||||||
|
|
||||||
let result = null;
|
|
||||||
for (let i = 0; i < ImageIcon.prototype.ICON_FAMILIES.length; i++) {
|
|
||||||
const family = ImageIcon.prototype.ICON_FAMILIES[i];
|
|
||||||
const iconFamilyId = iconId.substr(0, iconId.indexOf('_'));
|
|
||||||
|
|
||||||
if (family.id === iconFamilyId) {
|
|
||||||
result = family.icons;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
remove() {
|
|
||||||
const actionDispatcher = ActionDispatcher.getInstance();
|
|
||||||
const featureId = this._featureModel.getId();
|
|
||||||
const topicId = this._topicId;
|
|
||||||
actionDispatcher.removeFeatureFromTopic(topicId, featureId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageIcon.prototype.ICON_FAMILIES = [
|
|
||||||
{
|
|
||||||
id: 'face',
|
|
||||||
icons: ['face_plain', 'face_sad', 'face_crying', 'face_smile', 'face_surprise', 'face_wink'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'funy',
|
|
||||||
icons: ['funy_angel', 'funy_devilish', 'funy_glasses', 'funy_grin', 'funy_kiss', 'funy_monkey'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'sport',
|
|
||||||
icons: [
|
|
||||||
'sport_basketball',
|
|
||||||
'sport_football',
|
|
||||||
'sport_golf',
|
|
||||||
'sport_raquet',
|
|
||||||
'sport_shuttlecock',
|
|
||||||
'sport_soccer',
|
|
||||||
'sport_tennis',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'bulb',
|
|
||||||
icons: ['bulb_light_on', 'bulb_light_off'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'thumb',
|
|
||||||
icons: ['thumb_thumb_up', 'thumb_thumb_down'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'tick',
|
|
||||||
icons: ['tick_tick', 'tick_cross'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'onoff',
|
|
||||||
icons: [
|
|
||||||
'onoff_clock',
|
|
||||||
'onoff_clock_red',
|
|
||||||
'onoff_add',
|
|
||||||
'onoff_delete',
|
|
||||||
'onoff_status_offline',
|
|
||||||
'onoff_status_online',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'money',
|
|
||||||
icons: [
|
|
||||||
'money_money',
|
|
||||||
'money_dollar',
|
|
||||||
'money_euro',
|
|
||||||
'money_pound',
|
|
||||||
'money_yen',
|
|
||||||
'money_coins',
|
|
||||||
'money_ruby',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'time',
|
|
||||||
icons: ['time_calendar', 'time_clock', 'time_hourglass'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'number',
|
|
||||||
icons: [
|
|
||||||
'number_1',
|
|
||||||
'number_2',
|
|
||||||
'number_3',
|
|
||||||
'number_4',
|
|
||||||
'number_5',
|
|
||||||
'number_6',
|
|
||||||
'number_7',
|
|
||||||
'number_8',
|
|
||||||
'number_9',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'chart',
|
|
||||||
icons: ['chart_bar', 'chart_line', 'chart_curve', 'chart_pie', 'chart_organisation'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'sign',
|
|
||||||
icons: ['sign_warning', 'sign_info', 'sign_stop', 'sign_help', 'sign_cancel'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'hard',
|
|
||||||
icons: [
|
|
||||||
'hard_cd',
|
|
||||||
'hard_computer',
|
|
||||||
'hard_controller',
|
|
||||||
'hard_driver_disk',
|
|
||||||
'hard_ipod',
|
|
||||||
'hard_keyboard',
|
|
||||||
'hard_mouse',
|
|
||||||
'hard_printer',
|
|
||||||
'hard_webcam',
|
|
||||||
'hard_microphone',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'things',
|
|
||||||
icons: [
|
|
||||||
'things_address_book',
|
|
||||||
'things_wrench',
|
|
||||||
'things_pin',
|
|
||||||
'things_window-layout',
|
|
||||||
'things_bubbles',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'soft',
|
|
||||||
icons: [
|
|
||||||
'soft_bug',
|
|
||||||
'soft_cursor',
|
|
||||||
'soft_database_table',
|
|
||||||
'soft_database',
|
|
||||||
'soft_feed',
|
|
||||||
'soft_folder_explore',
|
|
||||||
'soft_rss',
|
|
||||||
'soft_penguin',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'arrow',
|
|
||||||
icons: ['arrow_up', 'arrow_down', 'arrow_left', 'arrow_right'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'arrowc',
|
|
||||||
icons: [
|
|
||||||
'arrowc_rotate_anticlockwise',
|
|
||||||
'arrowc_rotate_clockwise',
|
|
||||||
'arrowc_turn_left',
|
|
||||||
'arrowc_turn_right',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'people',
|
|
||||||
icons: ['people_group', 'people_male1', 'people_male2', 'people_female1', 'people_female2'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'mail',
|
|
||||||
icons: ['mail_envelop', 'mail_mailbox', 'mail_edit', 'mail_list'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'flag',
|
|
||||||
icons: ['flag_blue', 'flag_green', 'flag_orange', 'flag_pink', 'flag_purple', 'flag_yellow'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'social',
|
|
||||||
icons: [
|
|
||||||
'social_facebook',
|
|
||||||
'social_twitter',
|
|
||||||
'social_redit',
|
|
||||||
'social_instagram',
|
|
||||||
'social_google-plus',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'meetapps',
|
|
||||||
icons: [
|
|
||||||
'meetapps_slack',
|
|
||||||
'meetapps_google-meet',
|
|
||||||
'meetapps_whatapp',
|
|
||||||
'meetapps_ms-teams',
|
|
||||||
'meetapps_zoom',
|
|
||||||
'meetapps_facebook-messenger',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'appsgoogle',
|
|
||||||
icons: ['appsgoogle_youtube', 'appsgoogle_gmail', 'appsgoogle_maps'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'tag',
|
|
||||||
icons: ['tag_blue', 'tag_green', 'tag_orange', 'tag_red', 'tag_pink', 'tag_yellow'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'object',
|
|
||||||
icons: [
|
|
||||||
'object_bell',
|
|
||||||
'object_clanbomber',
|
|
||||||
'object_key',
|
|
||||||
'object_pencil',
|
|
||||||
'object_phone',
|
|
||||||
'object_magnifier',
|
|
||||||
'object_clip',
|
|
||||||
'object_music',
|
|
||||||
'object_star',
|
|
||||||
'object_wizard',
|
|
||||||
'object_house',
|
|
||||||
'object_cake',
|
|
||||||
'object_camera',
|
|
||||||
'object_palette',
|
|
||||||
'object_rainbow',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'weather',
|
|
||||||
icons: [
|
|
||||||
'weather_clear-night',
|
|
||||||
'weather_clear',
|
|
||||||
'weather_few-clouds-night',
|
|
||||||
'weather_few-clouds',
|
|
||||||
'weather_overcast',
|
|
||||||
'weather_severe-alert',
|
|
||||||
'weather_showers-scattered',
|
|
||||||
'weather_showers',
|
|
||||||
'weather_snow',
|
|
||||||
'weather_storm',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'task',
|
|
||||||
icons: ['task_0', 'task_25', 'task_50', 'task_75', 'task_100'],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default ImageIcon;
|
|
71
packages/mindplot/src/components/ImageIcon.ts
Normal file
71
packages/mindplot/src/components/ImageIcon.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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 { $assert } from '@wisemapping/core-js';
|
||||||
|
import { Image, Point, ElementClass } from '@wisemapping/web2d';
|
||||||
|
import IconGroup from './IconGroup';
|
||||||
|
import SizeType from './SizeType';
|
||||||
|
import FeatureModel from './model/FeatureModel';
|
||||||
|
import Icon from './Icon';
|
||||||
|
|
||||||
|
abstract class ImageIcon implements Icon {
|
||||||
|
protected _image: Image;
|
||||||
|
|
||||||
|
protected _group: IconGroup;
|
||||||
|
|
||||||
|
constructor(url: string) {
|
||||||
|
$assert(url, 'image url can not be null');
|
||||||
|
this._image = new Image();
|
||||||
|
this._image.setHref(url);
|
||||||
|
this._image.setSize(ImageIcon.SIZE, ImageIcon.SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
getElement(): ElementClass {
|
||||||
|
return this._image;
|
||||||
|
}
|
||||||
|
|
||||||
|
setGroup(group: IconGroup) {
|
||||||
|
this._group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroup(): IconGroup {
|
||||||
|
return this._group;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSize(): SizeType {
|
||||||
|
return this._image.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
getPosition(): Point {
|
||||||
|
return this._image.getPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
addEvent(type: string, fnc): void {
|
||||||
|
this._image.addEvent(type, fnc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line class-methods-use-this
|
||||||
|
remove() {
|
||||||
|
throw new Error('Unsupported operation');
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract getModel(): FeatureModel;
|
||||||
|
|
||||||
|
static SIZE = 90;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ImageIcon;
|
@ -16,14 +16,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { $assert } from '@wisemapping/core-js';
|
import { $assert } from '@wisemapping/core-js';
|
||||||
import Icon from './Icon';
|
import ImageIcon from './ImageIcon';
|
||||||
import LinksImage from '../../assets/icons/links.svg';
|
import LinksImage from '../../assets/icons/links.svg';
|
||||||
import LinkModel from './model/LinkModel';
|
import LinkModel from './model/LinkModel';
|
||||||
import Topic from './Topic';
|
import Topic from './Topic';
|
||||||
import FeatureModel from './model/FeatureModel';
|
import FeatureModel from './model/FeatureModel';
|
||||||
import WidgetManager from './WidgetManager';
|
import WidgetManager from './WidgetManager';
|
||||||
|
|
||||||
class LinkIcon extends Icon {
|
class LinkIcon extends ImageIcon {
|
||||||
private _linksModel: FeatureModel;
|
private _linksModel: FeatureModel;
|
||||||
|
|
||||||
private _topic: Topic;
|
private _topic: Topic;
|
||||||
|
@ -16,14 +16,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { $assert } from '@wisemapping/core-js';
|
import { $assert } from '@wisemapping/core-js';
|
||||||
import Icon from './Icon';
|
|
||||||
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 WidgetManager from './WidgetManager';
|
import WidgetManager from './WidgetManager';
|
||||||
|
import ImageIcon from './ImageIcon';
|
||||||
|
|
||||||
class NoteIcon extends Icon {
|
class NoteIcon extends ImageIcon {
|
||||||
private _linksModel: NoteModel;
|
private _linksModel: NoteModel;
|
||||||
|
|
||||||
private _topic: Topic;
|
private _topic: Topic;
|
||||||
|
132
packages/mindplot/src/components/SvgImageIcon.js
Normal file
132
packages/mindplot/src/components/SvgImageIcon.js
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* 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 { $assert } from '@wisemapping/core-js';
|
||||||
|
import ImageIcon from './ImageIcon';
|
||||||
|
import ActionDispatcher from './ActionDispatcher';
|
||||||
|
import iconFamily from './model/SvgIconFamily.json';
|
||||||
|
|
||||||
|
function importAll(r) {
|
||||||
|
const images = {};
|
||||||
|
r.keys().forEach((item) => {
|
||||||
|
images[item.replace('./', '')] = r(item);
|
||||||
|
});
|
||||||
|
return images;
|
||||||
|
}
|
||||||
|
|
||||||
|
const images = importAll(require.context('../../assets/icons', false, /\.(png|svg)$/));
|
||||||
|
|
||||||
|
class SvgImageIcon extends ImageIcon {
|
||||||
|
constructor(topic, iconModel, readOnly) {
|
||||||
|
$assert(iconModel, 'iconModel can not be null');
|
||||||
|
$assert(topic, 'topic can not be null');
|
||||||
|
|
||||||
|
// Build graph image representation ...
|
||||||
|
const iconType = iconModel.getIconType();
|
||||||
|
const imgUrl = SvgImageIcon.getImageUrl(iconType);
|
||||||
|
super(imgUrl);
|
||||||
|
|
||||||
|
this._topicId = topic.getId();
|
||||||
|
this._featureModel = iconModel;
|
||||||
|
|
||||||
|
if (!readOnly) {
|
||||||
|
// Icon
|
||||||
|
const image = this.getElement();
|
||||||
|
const me = this;
|
||||||
|
image.addEvent('click', () => {
|
||||||
|
const iconTypeClick = iconModel.getIconType();
|
||||||
|
const newIconType = SvgImageIcon._getNextFamilyIconId(iconTypeClick);
|
||||||
|
iconModel.setIconType(newIconType);
|
||||||
|
|
||||||
|
me._image.setHref(SvgImageIcon.getImageUrl(newIconType));
|
||||||
|
});
|
||||||
|
this._image.setCursor('pointer');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getImageUrl(iconId) {
|
||||||
|
let result = images[`${iconId}.svg`];
|
||||||
|
if (!result) {
|
||||||
|
result = images[`${iconId}.png`];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getModel() {
|
||||||
|
return this._featureModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
static _getNextFamilyIconId(iconId) {
|
||||||
|
const familyIcons = SvgImageIcon._getFamilyIcons(iconId);
|
||||||
|
$assert(familyIcons !== null, `Family Icon not found: ${iconId}`);
|
||||||
|
|
||||||
|
let result = null;
|
||||||
|
for (let i = 0; i < familyIcons.length && result == null; i++) {
|
||||||
|
if (familyIcons[i] === iconId) {
|
||||||
|
// Is last one?
|
||||||
|
if (i === familyIcons.length - 1) {
|
||||||
|
[result] = familyIcons;
|
||||||
|
} else {
|
||||||
|
result = familyIcons[i + 1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static _getNextUnicode(iconId) {
|
||||||
|
let result = null;
|
||||||
|
for (let i = 0; i < iconFamily.length; i++) {
|
||||||
|
const family = iconFamily[i];
|
||||||
|
const iconFamilyId = iconId.substr(0, iconId.indexOf('_'));
|
||||||
|
|
||||||
|
if (family.id === iconFamilyId) {
|
||||||
|
result = family.icons;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static _getFamilyIcons(iconId) {
|
||||||
|
$assert(iconId != null, 'id must not be null');
|
||||||
|
$assert(iconId.indexOf('_') !== -1, `Invalid icon id (it must contain '_'). Id: ${iconId}`);
|
||||||
|
|
||||||
|
let result = null;
|
||||||
|
for (let i = 0; i < iconFamily.length; i++) {
|
||||||
|
const family = iconFamily[i];
|
||||||
|
const iconFamilyId = iconId.substr(0, iconId.indexOf('_'));
|
||||||
|
|
||||||
|
if (family.id === iconFamilyId) {
|
||||||
|
result = family.icons;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
const actionDispatcher = ActionDispatcher.getInstance();
|
||||||
|
const featureId = this._featureModel.getId();
|
||||||
|
const topicId = this._topicId;
|
||||||
|
actionDispatcher.removeFeatureFromTopic(topicId, featureId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SvgImageIcon;
|
@ -40,7 +40,7 @@ import NoteModel from './model/NoteModel';
|
|||||||
import LinkModel from './model/LinkModel';
|
import LinkModel from './model/LinkModel';
|
||||||
import SizeType from './SizeType';
|
import SizeType from './SizeType';
|
||||||
import FeatureModel from './model/FeatureModel';
|
import FeatureModel from './model/FeatureModel';
|
||||||
import Icon from './Icon';
|
import ImageIcon from './ImageIcon';
|
||||||
|
|
||||||
const ICON_SCALING_FACTOR = 1.3;
|
const ICON_SCALING_FACTOR = 1.3;
|
||||||
|
|
||||||
@ -322,13 +322,18 @@ abstract class Topic extends NodeGraph {
|
|||||||
const featuresModel = model.getFeatures();
|
const featuresModel = model.getFeatures();
|
||||||
featuresModel.forEach((f) => {
|
featuresModel.forEach((f) => {
|
||||||
const icon = TopicFeatureFactory.createIcon(this, f, this.isReadOnly());
|
const icon = TopicFeatureFactory.createIcon(this, f, this.isReadOnly());
|
||||||
result.addIcon(icon, f.getType() === TopicFeatureFactory.Icon.id && !this.isReadOnly());
|
|
||||||
|
const type = f.getType();
|
||||||
|
const addRemoveAction =
|
||||||
|
type === TopicFeatureFactory.SvgIcon.id || type === TopicFeatureFactory.EmojiIcon.id;
|
||||||
|
|
||||||
|
result.addIcon(icon, addRemoveAction && !this.isReadOnly());
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
addFeature(featureModel: FeatureModel): Icon {
|
addFeature(featureModel: FeatureModel): ImageIcon {
|
||||||
const iconGroup = this.getOrBuildIconGroup();
|
const iconGroup = this.getOrBuildIconGroup();
|
||||||
this.closeEditors();
|
this.closeEditors();
|
||||||
|
|
||||||
@ -336,11 +341,11 @@ abstract class Topic extends NodeGraph {
|
|||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
model.addFeature(featureModel);
|
model.addFeature(featureModel);
|
||||||
|
|
||||||
const result: Icon = TopicFeatureFactory.createIcon(this, featureModel, this.isReadOnly());
|
const result: ImageIcon = TopicFeatureFactory.createIcon(this, featureModel, this.isReadOnly());
|
||||||
iconGroup.addIcon(
|
const isIcon =
|
||||||
result,
|
featureModel.getType() === TopicFeatureFactory.SvgIcon.id ||
|
||||||
featureModel.getType() === TopicFeatureFactory.Icon.id && !this.isReadOnly(),
|
featureModel.getType() === TopicFeatureFactory.EmojiIcon.id;
|
||||||
);
|
iconGroup.addIcon(result, isIcon && !this.isReadOnly());
|
||||||
|
|
||||||
this.adjustShapes();
|
this.adjustShapes();
|
||||||
return result;
|
return result;
|
||||||
@ -533,7 +538,7 @@ abstract class Topic extends NodeGraph {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
setBackgroundColor(color: string) {
|
setBackgroundColor(color: string): void {
|
||||||
this._setBackgroundColor(color, true);
|
this._setBackgroundColor(color, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,7 +557,6 @@ abstract class Topic extends NodeGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
getBackgroundColor(): string {
|
getBackgroundColor(): string {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getBackgroundColor();
|
let result = model.getBackgroundColor();
|
||||||
|
@ -17,15 +17,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { $assert } from '@wisemapping/core-js';
|
import { $assert } from '@wisemapping/core-js';
|
||||||
import ImageIcon from './ImageIcon';
|
import EmojiCharIcon from './EmojiCharIcon';
|
||||||
|
import SvgImageIcon from './SvgImageIcon';
|
||||||
import LinkIcon from './LinkIcon';
|
import LinkIcon from './LinkIcon';
|
||||||
import NoteIcon from './NoteIcon';
|
import NoteIcon from './NoteIcon';
|
||||||
|
|
||||||
const TopicFeatureFactory = {
|
const TopicFeatureFactory = {
|
||||||
/** the icon object */
|
/** the icon object */
|
||||||
Icon: {
|
SvgIcon: {
|
||||||
id: 'icon',
|
id: 'icon',
|
||||||
icon: ImageIcon,
|
icon: SvgImageIcon,
|
||||||
|
},
|
||||||
|
|
||||||
|
EmojiIcon: {
|
||||||
|
id: 'eicon',
|
||||||
|
icon: EmojiCharIcon,
|
||||||
},
|
},
|
||||||
|
|
||||||
/** the link object */
|
/** the link object */
|
||||||
@ -52,7 +58,8 @@ const TopicFeatureFactory = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TopicFeatureFactory._featuresMetadataById = [
|
TopicFeatureFactory._featuresMetadataById = [
|
||||||
TopicFeatureFactory.Icon,
|
TopicFeatureFactory.SvgIcon,
|
||||||
|
TopicFeatureFactory.EmojiIcon,
|
||||||
TopicFeatureFactory.Link,
|
TopicFeatureFactory.Link,
|
||||||
TopicFeatureFactory.Note,
|
TopicFeatureFactory.Note,
|
||||||
];
|
];
|
||||||
|
@ -72,15 +72,15 @@ class WidgetManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createTooltipForLink(topic: Topic, linkModel: LinkModel, linkIcon: LinkIcon) {
|
createTooltipForLink(topic: Topic, linkModel: LinkModel, linkIcon: LinkIcon) {
|
||||||
this.createTooltip(linkIcon.getImage().peer, $msg('LINK'), linkModel, undefined);
|
this.createTooltip(linkIcon.getElement().peer, $msg('LINK'), linkModel, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
createTooltipForNote(topic: Topic, noteModel: NoteModel, noteIcon: NoteIcon) {
|
createTooltipForNote(topic: Topic, noteModel: NoteModel, noteIcon: NoteIcon) {
|
||||||
this.createTooltip(noteIcon.getImage().peer, $msg('NOTE'), undefined, noteModel);
|
this.createTooltip(noteIcon.getElement().peer, $msg('NOTE'), undefined, noteModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
configureEditorForLink(topic: Topic, linkModel: LinkModel, linkIcon: LinkIcon) {
|
configureEditorForLink(topic: Topic, linkModel: LinkModel, linkIcon: LinkIcon) {
|
||||||
const htmlImage = linkIcon.getImage().peer;
|
const htmlImage = linkIcon.getElement().peer;
|
||||||
htmlImage.addEvent('click', (evt) => {
|
htmlImage.addEvent('click', (evt) => {
|
||||||
this.showEditorForLink(topic, linkModel, linkIcon);
|
this.showEditorForLink(topic, linkModel, linkIcon);
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
@ -88,7 +88,7 @@ class WidgetManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
configureEditorForNote(topic: Topic, noteModel: NoteModel, noteIcon: NoteIcon) {
|
configureEditorForNote(topic: Topic, noteModel: NoteModel, noteIcon: NoteIcon) {
|
||||||
const htmlImage = noteIcon.getImage().peer;
|
const htmlImage = noteIcon.getElement().peer;
|
||||||
htmlImage.addEvent('click', (evt) => {
|
htmlImage.addEvent('click', (evt) => {
|
||||||
this.showEditorForNote(topic, noteModel, noteIcon);
|
this.showEditorForNote(topic, noteModel, noteIcon);
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
|
@ -2,7 +2,7 @@ import xmlFormatter from 'xml-formatter';
|
|||||||
import { Mindmap } from '../..';
|
import { Mindmap } from '../..';
|
||||||
import INodeModel, { TopicShape } from '../model/INodeModel';
|
import INodeModel, { TopicShape } from '../model/INodeModel';
|
||||||
import RelationshipModel from '../model/RelationshipModel';
|
import RelationshipModel from '../model/RelationshipModel';
|
||||||
import IconModel from '../model/IconModel';
|
import SvgIconModel from '../model/SvgIconModel';
|
||||||
import FeatureModel from '../model/FeatureModel';
|
import FeatureModel from '../model/FeatureModel';
|
||||||
import LinkModel from '../model/LinkModel';
|
import LinkModel from '../model/LinkModel';
|
||||||
import NoteModel from '../model/NoteModel';
|
import NoteModel from '../model/NoteModel';
|
||||||
@ -228,7 +228,7 @@ class FreemindExporter extends Exporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'icon') {
|
if (type === 'icon') {
|
||||||
const icon = feature as IconModel;
|
const icon = feature as SvgIconModel;
|
||||||
const freemindIcon: Icon = new Icon();
|
const freemindIcon: Icon = new Icon();
|
||||||
freemindIcon.setBuiltin(icon.getIconType());
|
freemindIcon.setBuiltin(icon.getIconType());
|
||||||
freemindNode.setArrowlinkOrCloudOrEdge(freemindIcon);
|
freemindNode.setArrowlinkOrCloudOrEdge(freemindIcon);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import IconModel from '../model/IconModel';
|
import SvgIconModel from '../model/SvgIconModel';
|
||||||
|
|
||||||
export default class FreemindIconConverter {
|
export default class FreemindIconConverter {
|
||||||
private static freeIdToIcon: Map<string, IconModel> = new Map<string, IconModel>();
|
private static freeIdToIcon: Map<string, SvgIconModel> = new Map<string, SvgIconModel>();
|
||||||
|
|
||||||
public static toWiseId(iconId: string): number | null {
|
public static toWiseId(iconId: string): number | null {
|
||||||
const result: IconModel = this.freeIdToIcon.get(iconId);
|
const result: SvgIconModel = this.freeIdToIcon.get(iconId);
|
||||||
return result ? result.getId() : null;
|
return result ? result.getId() : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
36
packages/mindplot/src/components/model/EmojiIconModel.ts
Normal file
36
packages/mindplot/src/components/model/EmojiIconModel.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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 { $assert } from '@wisemapping/core-js';
|
||||||
|
import FeatureModel from './FeatureModel';
|
||||||
|
|
||||||
|
class EmojiIconModel extends FeatureModel {
|
||||||
|
constructor(attributes) {
|
||||||
|
super('eicon');
|
||||||
|
this.setIconType(attributes.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
getIconType(): string {
|
||||||
|
return this.getAttribute('id') as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIconType(iconType: string): void {
|
||||||
|
$assert(iconType, 'iconType id can not be null');
|
||||||
|
this.setAttribute('id', iconType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default EmojiIconModel;
|
@ -1,9 +1,10 @@
|
|||||||
import { $assert } from '@wisemapping/core-js';
|
import { $assert } from '@wisemapping/core-js';
|
||||||
import IconModel from './IconModel';
|
import SvgIconModel from './SvgIconModel';
|
||||||
import LinkModel from './LinkModel';
|
import LinkModel from './LinkModel';
|
||||||
import NoteModel from './NoteModel';
|
import NoteModel from './NoteModel';
|
||||||
import FeatureModel from './FeatureModel';
|
import FeatureModel from './FeatureModel';
|
||||||
import FeatureType from './FeatureType';
|
import FeatureType from './FeatureType';
|
||||||
|
import EmojiIconModel from './EmojiIconModel';
|
||||||
|
|
||||||
interface NodeById {
|
interface NodeById {
|
||||||
id: FeatureType;
|
id: FeatureType;
|
||||||
@ -14,7 +15,11 @@ class FeatureModelFactory {
|
|||||||
static modelById: Array<NodeById> = [
|
static modelById: Array<NodeById> = [
|
||||||
{
|
{
|
||||||
id: 'icon',
|
id: 'icon',
|
||||||
model: IconModel,
|
model: SvgIconModel,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'eicon',
|
||||||
|
model: EmojiIconModel,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'link',
|
id: 'link',
|
||||||
|
@ -15,6 +15,6 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
type FeatureType = 'note' | 'link' | 'icon';
|
type FeatureType = 'note' | 'link' | 'icon' | 'eicon';
|
||||||
|
|
||||||
export default FeatureType;
|
export default FeatureType;
|
||||||
|
293
packages/mindplot/src/components/model/SvgIconFamily.json
Normal file
293
packages/mindplot/src/components/model/SvgIconFamily.json
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "face",
|
||||||
|
"icons": [
|
||||||
|
"face_plain",
|
||||||
|
"face_sad",
|
||||||
|
"face_crying",
|
||||||
|
"face_smile",
|
||||||
|
"face_surprise",
|
||||||
|
"face_wink"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "funy",
|
||||||
|
"icons": [
|
||||||
|
"funy_angel",
|
||||||
|
"funy_devilish",
|
||||||
|
"funy_glasses",
|
||||||
|
"funy_grin",
|
||||||
|
"funy_kiss",
|
||||||
|
"funy_monkey"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sport",
|
||||||
|
"icons": [
|
||||||
|
"sport_basketball",
|
||||||
|
"sport_football",
|
||||||
|
"sport_golf",
|
||||||
|
"sport_raquet",
|
||||||
|
"sport_shuttlecock",
|
||||||
|
"sport_soccer",
|
||||||
|
"sport_tennis"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bulb",
|
||||||
|
"icons": [
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "thumb",
|
||||||
|
"icons": [
|
||||||
|
"thumb_thumb_up",
|
||||||
|
"thumb_thumb_down"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tick",
|
||||||
|
"icons": [
|
||||||
|
"tick_tick",
|
||||||
|
"tick_cross"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "onoff",
|
||||||
|
"icons": [
|
||||||
|
"onoff_clock",
|
||||||
|
"onoff_clock_red",
|
||||||
|
"onoff_add",
|
||||||
|
"onoff_delete",
|
||||||
|
"onoff_status_offline",
|
||||||
|
"onoff_status_online"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "money",
|
||||||
|
"icons": [
|
||||||
|
"money_money",
|
||||||
|
"money_dollar",
|
||||||
|
"money_euro",
|
||||||
|
"money_pound",
|
||||||
|
"money_yen",
|
||||||
|
"money_coins",
|
||||||
|
"money_ruby"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "time",
|
||||||
|
"icons": [
|
||||||
|
"time_calendar",
|
||||||
|
"time_clock",
|
||||||
|
"time_hourglass"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "number",
|
||||||
|
"icons": [
|
||||||
|
"number_1",
|
||||||
|
"number_2",
|
||||||
|
"number_3",
|
||||||
|
"number_4",
|
||||||
|
"number_5",
|
||||||
|
"number_6",
|
||||||
|
"number_7",
|
||||||
|
"number_8",
|
||||||
|
"number_9"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "chart",
|
||||||
|
"icons": [
|
||||||
|
"chart_bar",
|
||||||
|
"chart_line",
|
||||||
|
"chart_curve",
|
||||||
|
"chart_pie",
|
||||||
|
"chart_organisation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "sign",
|
||||||
|
"icons": [
|
||||||
|
"sign_warning",
|
||||||
|
"sign_info",
|
||||||
|
"sign_stop",
|
||||||
|
"sign_help",
|
||||||
|
"sign_cancel"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hard",
|
||||||
|
"icons": [
|
||||||
|
"hard_cd",
|
||||||
|
"hard_computer",
|
||||||
|
"hard_controller",
|
||||||
|
"hard_driver_disk",
|
||||||
|
"hard_ipod",
|
||||||
|
"hard_keyboard",
|
||||||
|
"hard_mouse",
|
||||||
|
"hard_printer",
|
||||||
|
"hard_webcam",
|
||||||
|
"hard_microphone"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "things",
|
||||||
|
"icons": [
|
||||||
|
"things_address_book",
|
||||||
|
"things_wrench",
|
||||||
|
"things_pin",
|
||||||
|
"things_window-layout",
|
||||||
|
"things_bubbles"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "soft",
|
||||||
|
"icons": [
|
||||||
|
"soft_bug",
|
||||||
|
"soft_cursor",
|
||||||
|
"soft_database_table",
|
||||||
|
"soft_database",
|
||||||
|
"soft_feed",
|
||||||
|
"soft_folder_explore",
|
||||||
|
"soft_rss",
|
||||||
|
"soft_penguin"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "arrow",
|
||||||
|
"icons": [
|
||||||
|
"arrow_up",
|
||||||
|
"arrow_down",
|
||||||
|
"arrow_left",
|
||||||
|
"arrow_right"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "arrowc",
|
||||||
|
"icons": [
|
||||||
|
"arrowc_rotate_anticlockwise",
|
||||||
|
"arrowc_rotate_clockwise",
|
||||||
|
"arrowc_turn_left",
|
||||||
|
"arrowc_turn_right"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "people",
|
||||||
|
"icons": [
|
||||||
|
"people_group",
|
||||||
|
"people_male1",
|
||||||
|
"people_male2",
|
||||||
|
"people_female1",
|
||||||
|
"people_female2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "mail",
|
||||||
|
"icons": [
|
||||||
|
"mail_envelop",
|
||||||
|
"mail_mailbox",
|
||||||
|
"mail_edit",
|
||||||
|
"mail_list"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flag",
|
||||||
|
"icons": [
|
||||||
|
"flag_blue",
|
||||||
|
"flag_green",
|
||||||
|
"flag_orange",
|
||||||
|
"flag_pink",
|
||||||
|
"flag_purple",
|
||||||
|
"flag_yellow"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "social",
|
||||||
|
"icons": [
|
||||||
|
"social_facebook",
|
||||||
|
"social_twitter",
|
||||||
|
"social_redit",
|
||||||
|
"social_instagram",
|
||||||
|
"social_google-plus"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "meetapps",
|
||||||
|
"icons": [
|
||||||
|
"meetapps_slack",
|
||||||
|
"meetapps_google-meet",
|
||||||
|
"meetapps_whatapp",
|
||||||
|
"meetapps_ms-teams",
|
||||||
|
"meetapps_zoom",
|
||||||
|
"meetapps_facebook-messenger"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "appsgoogle",
|
||||||
|
"icons": [
|
||||||
|
"appsgoogle_youtube",
|
||||||
|
"appsgoogle_gmail",
|
||||||
|
"appsgoogle_maps"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tag",
|
||||||
|
"icons": [
|
||||||
|
"tag_blue",
|
||||||
|
"tag_green",
|
||||||
|
"tag_orange",
|
||||||
|
"tag_red",
|
||||||
|
"tag_pink",
|
||||||
|
"tag_yellow"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "object",
|
||||||
|
"icons": [
|
||||||
|
"object_bell",
|
||||||
|
"object_clanbomber",
|
||||||
|
"object_key",
|
||||||
|
"object_pencil",
|
||||||
|
"object_phone",
|
||||||
|
"object_magnifier",
|
||||||
|
"object_clip",
|
||||||
|
"object_music",
|
||||||
|
"object_star",
|
||||||
|
"object_wizard",
|
||||||
|
"object_house",
|
||||||
|
"object_cake",
|
||||||
|
"object_camera",
|
||||||
|
"object_palette",
|
||||||
|
"object_rainbow"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "weather",
|
||||||
|
"icons": [
|
||||||
|
"weather_clear-night",
|
||||||
|
"weather_clear",
|
||||||
|
"weather_few-clouds-night",
|
||||||
|
"weather_few-clouds",
|
||||||
|
"weather_overcast",
|
||||||
|
"weather_severe-alert",
|
||||||
|
"weather_showers-scattered",
|
||||||
|
"weather_showers",
|
||||||
|
"weather_snow",
|
||||||
|
"weather_storm"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "task",
|
||||||
|
"icons": [
|
||||||
|
"task_0",
|
||||||
|
"task_25",
|
||||||
|
"task_50",
|
||||||
|
"task_75",
|
||||||
|
"task_100"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -18,7 +18,7 @@
|
|||||||
import { $assert } from '@wisemapping/core-js';
|
import { $assert } from '@wisemapping/core-js';
|
||||||
import FeatureModel from './FeatureModel';
|
import FeatureModel from './FeatureModel';
|
||||||
|
|
||||||
class IconModel extends FeatureModel {
|
class SvgIconModel extends FeatureModel {
|
||||||
constructor(attributes) {
|
constructor(attributes) {
|
||||||
super('icon');
|
super('icon');
|
||||||
this.setIconType(attributes.id);
|
this.setIconType(attributes.id);
|
||||||
@ -33,4 +33,5 @@ class IconModel extends FeatureModel {
|
|||||||
this.setAttribute('id', iconType);
|
this.setAttribute('id', iconType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default IconModel;
|
|
||||||
|
export default SvgIconModel;
|
@ -172,7 +172,7 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
const cdata = document.createCDATASection(this._rmXmlInv(value));
|
const cdata = document.createCDATASection(this._rmXmlInv(value));
|
||||||
featureDom.appendChild(cdata);
|
featureDom.appendChild(cdata);
|
||||||
} else {
|
} else {
|
||||||
featureDom.setAttribute(key, this._rmXmlInv(value));
|
featureDom.setAttribute(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentTopic.appendChild(featureDom);
|
parentTopic.appendChild(featureDom);
|
||||||
|
@ -31,8 +31,10 @@ import Exporter from './components/export/Exporter';
|
|||||||
import Importer from './components/import/Importer';
|
import Importer from './components/import/Importer';
|
||||||
import DesignerKeyboard from './components/DesignerKeyboard';
|
import DesignerKeyboard from './components/DesignerKeyboard';
|
||||||
import EditorRenderMode from './components/EditorRenderMode';
|
import EditorRenderMode from './components/EditorRenderMode';
|
||||||
|
import DesignerModel from './components/DesignerModel';
|
||||||
|
|
||||||
|
import SvgImageIcon from './components/SvgImageIcon';
|
||||||
|
|
||||||
import ImageIcon from './components/ImageIcon';
|
|
||||||
import MindplotWebComponent, {
|
import MindplotWebComponent, {
|
||||||
MindplotWebComponentInterface,
|
MindplotWebComponentInterface,
|
||||||
} from './components/MindplotWebComponent';
|
} from './components/MindplotWebComponent';
|
||||||
@ -48,8 +50,13 @@ import WidgetManager from './components/WidgetManager';
|
|||||||
import { buildDesigner } from './components/DesignerBuilder';
|
import { buildDesigner } from './components/DesignerBuilder';
|
||||||
|
|
||||||
import { $notify } from './components/widget/ToolbarNotifier';
|
import { $notify } from './components/widget/ToolbarNotifier';
|
||||||
|
import XMLSerializerFactory from './components/persistence/XMLSerializerFactory';
|
||||||
|
|
||||||
import { $msg } from './components/Messages';
|
declare global {
|
||||||
|
// Todo: There are some global references that needs to be removed inside mindplot.
|
||||||
|
// eslint-disable-next-line vars-on-top, no-var
|
||||||
|
var designer: Designer;
|
||||||
|
}
|
||||||
|
|
||||||
const globalAny: any = global;
|
const globalAny: any = global;
|
||||||
globalAny.jQuery = jquery;
|
globalAny.jQuery = jquery;
|
||||||
@ -62,6 +69,7 @@ if (!customElements.get('mindplot-component')) {
|
|||||||
export {
|
export {
|
||||||
Mindmap,
|
Mindmap,
|
||||||
Designer,
|
Designer,
|
||||||
|
DesignerModel,
|
||||||
DesignerBuilder,
|
DesignerBuilder,
|
||||||
PersistenceManager,
|
PersistenceManager,
|
||||||
RESTPersistenceManager,
|
RESTPersistenceManager,
|
||||||
@ -74,10 +82,9 @@ export {
|
|||||||
ImageExporterFactory,
|
ImageExporterFactory,
|
||||||
TextImporterFactory,
|
TextImporterFactory,
|
||||||
Exporter,
|
Exporter,
|
||||||
|
SvgImageIcon,
|
||||||
Importer,
|
Importer,
|
||||||
ImageIcon,
|
|
||||||
$notify,
|
$notify,
|
||||||
$msg,
|
|
||||||
DesignerKeyboard,
|
DesignerKeyboard,
|
||||||
MindplotWebComponent,
|
MindplotWebComponent,
|
||||||
MindplotWebComponentInterface,
|
MindplotWebComponentInterface,
|
||||||
@ -87,4 +94,5 @@ export {
|
|||||||
NoteModel,
|
NoteModel,
|
||||||
WidgetManager,
|
WidgetManager,
|
||||||
Topic,
|
Topic,
|
||||||
|
XMLSerializerFactory,
|
||||||
};
|
};
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.18.13",
|
"@babel/core": "^7.18.13",
|
||||||
"@babel/plugin-transform-modules-commonjs": "^7.14.5",
|
"@babel/plugin-transform-modules-commonjs": "^7.14.5",
|
||||||
"@babel/preset-env": "^7.14.7",
|
"@babel/preset-env": "^7.19.4",
|
||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^8.2.2",
|
||||||
"clean-webpack-plugin": "^4.0.0",
|
"clean-webpack-plugin": "^4.0.0",
|
||||||
"core-js": "^3.15.2",
|
"core-js": "^3.15.2",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable no-alert */
|
/* eslint-disable no-alert */
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { Toolkit, Workspace, Line, Group, Elipse } from '../../src';
|
import { Workspace, Line, Group, Elipse } from '../../src';
|
||||||
|
|
||||||
global.$ = $;
|
global.$ = $;
|
||||||
|
|
||||||
|
@ -23,11 +23,14 @@
|
|||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"react",
|
"react",
|
||||||
"@typescript-eslint"
|
"@typescript-eslint",
|
||||||
|
"react-hooks"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
"@typescript-eslint/explicit-module-boundary-types": "error",
|
"@typescript-eslint/explicit-module-boundary-types": "error",
|
||||||
"@typescript-eslint/no-unused-vars": "error"
|
"@typescript-eslint/no-unused-vars": "error",
|
||||||
|
"react-hooks/rules-of-hooks": "warn" // Checks rules of Hooks
|
||||||
|
// "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,6 +11,9 @@
|
|||||||
"accountinfo.firstname": {
|
"accountinfo.firstname": {
|
||||||
"defaultMessage": "Primer nombre"
|
"defaultMessage": "Primer nombre"
|
||||||
},
|
},
|
||||||
|
"registration.page-title": {
|
||||||
|
"defaultMessage": "Registrarse | WiseMapping"
|
||||||
|
},
|
||||||
"accountinfo.lastname": {
|
"accountinfo.lastname": {
|
||||||
"defaultMessage": "Apellido"
|
"defaultMessage": "Apellido"
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
"accountinfo.lastname": {
|
"accountinfo.lastname": {
|
||||||
"defaultMessage": "Nom de famille"
|
"defaultMessage": "Nom de famille"
|
||||||
},
|
},
|
||||||
|
"registration.page-title": {
|
||||||
|
"defaultMessage": "Inscription | WiseMapping"
|
||||||
|
},
|
||||||
"accountinfo.title": {
|
"accountinfo.title": {
|
||||||
"defaultMessage": "Informations de compte"
|
"defaultMessage": "Informations de compte"
|
||||||
},
|
},
|
||||||
|
@ -25,57 +25,40 @@
|
|||||||
"@formatjs/cli": "^2.13.15",
|
"@formatjs/cli": "^2.13.15",
|
||||||
"@testing-library/cypress": "^7.0.3",
|
"@testing-library/cypress": "^7.0.3",
|
||||||
"@types/testing-library__cypress": "^5.0.8",
|
"@types/testing-library__cypress": "^5.0.8",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.8.1",
|
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
||||||
"@typescript-eslint/parser": "^4.8.1",
|
"@typescript-eslint/parser": "^5.41.0",
|
||||||
"brotli-webpack-plugin": "^1.1.0",
|
"clean-webpack-plugin": "^3.0.05.10.11",
|
||||||
"clean-webpack-plugin": "^3.0.0",
|
|
||||||
"compression-webpack-plugin": "^7.1.2",
|
|
||||||
"copy-webpack-plugin": "^7.0.0",
|
"copy-webpack-plugin": "^7.0.0",
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"css-loader": "^5.0.1",
|
|
||||||
"cypress": "^8.4.1",
|
"cypress": "^8.4.1",
|
||||||
"cypress-image-snapshot": "^4.0.1",
|
"cypress-image-snapshot": "^4.0.1",
|
||||||
"eslint": "^7.14.0",
|
"eslint": "^7.14.0",
|
||||||
"eslint-config-prettier": "^8.0.0",
|
"eslint-config-prettier": "^8.0.0",
|
||||||
"eslint-plugin-react": "^7.21.5",
|
"eslint-plugin-react": "^7.21.5",
|
||||||
"eslint-plugin-react-hooks": "^4.2.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"file-loader": "^6.2.0",
|
|
||||||
"html-webpack-dynamic-env-plugin": "^0.0.2",
|
|
||||||
"html-webpack-plugin": "^5.1.0",
|
"html-webpack-plugin": "^5.1.0",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"sass-loader": "^10.1.0",
|
|
||||||
"start-server-and-test": "^1.12.0",
|
"start-server-and-test": "^1.12.0",
|
||||||
"style-loader": "^2.0.0",
|
"typescript": "^4.8.4",
|
||||||
"ts-loader": "^8.0.11",
|
|
||||||
"ts-node": "^9.0.0",
|
|
||||||
"typescript": "^4.1.2",
|
|
||||||
"url-loader": "^4.1.1",
|
|
||||||
"webpack": "^5.74.0",
|
"webpack": "^5.74.0",
|
||||||
"webpack-bundle-analyzer": "^4.4.0",
|
"webpack-bundle-analyzer": "^4.4.0",
|
||||||
"webpack-cli": "^4.2.0",
|
|
||||||
"webpack-dev-server": "^3.11.0",
|
|
||||||
"webpack-merge": "^5.7.3"
|
"webpack-merge": "^5.7.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.10.4",
|
"@emotion/react": "^11.10.4",
|
||||||
"@emotion/styled": "^11.10.4",
|
|
||||||
"@mui/icons-material": "^5.9.3",
|
"@mui/icons-material": "^5.9.3",
|
||||||
"@mui/lab": "^5.0.0-alpha.98",
|
"@mui/lab": "^5.0.0-alpha.98",
|
||||||
"@mui/material": "^5.9.3",
|
"@mui/material": "^5.10.11",
|
||||||
"@mui/styles": "^5.9.3",
|
"@mui/styles": "^5.9.3",
|
||||||
"@reduxjs/toolkit": "^1.5.0",
|
"@reduxjs/toolkit": "^1.5.0",
|
||||||
"@wisemapping/editor": "^0.4.0",
|
"@wisemapping/editor": "^0.4.0",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
"react": "^17.0.2",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^17.0.2",
|
|
||||||
"react-ga4": "^1.4.1",
|
"react-ga4": "^1.4.1",
|
||||||
"react-google-recaptcha": "^2.1.0",
|
"react-google-recaptcha": "^2.1.0",
|
||||||
"react-intl": "^4.7.6",
|
"react-intl": "^5.25.1",
|
||||||
"react-query": "^3.39.1",
|
"react-query": "^3.39.1",
|
||||||
"react-redux": "^7.2.2",
|
"react-redux": "^7.2.2",
|
||||||
"react-router": "^5.1.8",
|
"react-router-dom": "^5.2.0"
|
||||||
"react-router-dom": "^5.2.0",
|
|
||||||
"styled-components": "^5.3.5"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { fetchAccount } from './../../redux/clientSlice';
|
import { useFetchAccount } from './../../redux/clientSlice';
|
||||||
import 'dayjs/locale/fr';
|
import 'dayjs/locale/fr';
|
||||||
import 'dayjs/locale/en';
|
import 'dayjs/locale/en';
|
||||||
import 'dayjs/locale/es';
|
import 'dayjs/locale/es';
|
||||||
@ -26,7 +26,7 @@ export default abstract class AppI18n {
|
|||||||
const isTryPage = window.location.pathname.endsWith('/try');
|
const isTryPage = window.location.pathname.endsWith('/try');
|
||||||
let result: Locale;
|
let result: Locale;
|
||||||
if (!isTryPage) {
|
if (!isTryPage) {
|
||||||
const account = fetchAccount();
|
const account = useFetchAccount();
|
||||||
result = account?.locale ? account.locale : this.getDefaultLocale();
|
result = account?.locale ? account.locale : this.getDefaultLocale();
|
||||||
|
|
||||||
// If the local storage value is different, update ...
|
// If the local storage value is different, update ...
|
||||||
|
@ -873,6 +873,12 @@
|
|||||||
"value": "Apellido"
|
"value": "Apellido"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"registration.page-title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Registrarse | WiseMapping"
|
||||||
|
}
|
||||||
|
],
|
||||||
"registration.password": [
|
"registration.password": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
|
@ -919,6 +919,12 @@
|
|||||||
"value": "Nom de famille"
|
"value": "Nom de famille"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"registration.page-title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Inscription | WiseMapping"
|
||||||
|
}
|
||||||
|
],
|
||||||
"registration.password": [
|
"registration.password": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
LocalStorageManager,
|
LocalStorageManager,
|
||||||
Mindmap,
|
Mindmap,
|
||||||
MockPersistenceManager,
|
MockPersistenceManager,
|
||||||
XMLSerializerTango,
|
XMLSerializerFactory,
|
||||||
} from '@wisemapping/editor';
|
} from '@wisemapping/editor';
|
||||||
|
|
||||||
export const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
|
export const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
|
||||||
@ -54,7 +54,7 @@ export const getMindmapFromPersistence = (mapId: string): Mindmap => {
|
|||||||
'text/xml',
|
'text/xml',
|
||||||
);
|
);
|
||||||
|
|
||||||
const serializer = new XMLSerializerTango();
|
const serializer = XMLSerializerFactory.getSerializer('tango');
|
||||||
mindmap = serializer.loadFromDom(xmlDoc, String(mapId));
|
mindmap = serializer.loadFromDom(xmlDoc, String(mapId));
|
||||||
}
|
}
|
||||||
return mindmap;
|
return mindmap;
|
||||||
|
@ -25,7 +25,7 @@ import AppI18n, { Locales } from '../../classes/app-i18n';
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { hotkeysEnabled } from '../../redux/editorSlice';
|
import { hotkeysEnabled } from '../../redux/editorSlice';
|
||||||
import ReactGA from 'react-ga4';
|
import ReactGA from 'react-ga4';
|
||||||
import { fetchAccount, fetchMapById } from '../../redux/clientSlice';
|
import { useFetchAccount, useFetchMapById } from '../../redux/clientSlice';
|
||||||
import EditorOptionsBuilder from './EditorOptionsBuilder';
|
import EditorOptionsBuilder from './EditorOptionsBuilder';
|
||||||
import { buildPersistenceManagerForEditor } from './PersistenceManagerUtils';
|
import { buildPersistenceManagerForEditor } from './PersistenceManagerUtils';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
@ -50,14 +50,14 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
|||||||
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` });
|
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: `Map Editor` });
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const findEditorMode = (isTryMode: boolean, mapId: number): EditorRenderMode | null => {
|
const useFindEditorMode = (isTryMode: boolean, mapId: number): EditorRenderMode | null => {
|
||||||
let result: EditorRenderMode = null;
|
let result: EditorRenderMode = null;
|
||||||
if (isTryMode) {
|
if (isTryMode) {
|
||||||
result = 'showcase';
|
result = 'showcase';
|
||||||
} else if (global.mindmapLocked) {
|
} else if (global.mindmapLocked) {
|
||||||
result = 'viewonly';
|
result = 'viewonly';
|
||||||
} else {
|
} else {
|
||||||
const fetchResult = fetchMapById(mapId);
|
const fetchResult = useFetchMapById(mapId);
|
||||||
if (!fetchResult.isLoading) {
|
if (!fetchResult.isLoading) {
|
||||||
if (fetchResult.error) {
|
if (fetchResult.error) {
|
||||||
throw new Error(`Map info could not be loaded: ${JSON.stringify(fetchResult.error)}`);
|
throw new Error(`Map info could not be loaded: ${JSON.stringify(fetchResult.error)}`);
|
||||||
@ -76,11 +76,11 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
|||||||
|
|
||||||
// What is the role ?
|
// What is the role ?
|
||||||
const mapId = EditorOptionsBuilder.loadMapId();
|
const mapId = EditorOptionsBuilder.loadMapId();
|
||||||
const mode = findEditorMode(isTryMode, mapId);
|
const mode = useFindEditorMode(isTryMode, mapId);
|
||||||
|
|
||||||
// Account settings can be null and editor cannot be initilized multiple times. This creates problems
|
// Account settings can be null and editor cannot be initilized multiple times. This creates problems
|
||||||
// at the i18n resource loading.
|
// at the i18n resource loading.
|
||||||
const isAccountLoaded = mode === 'showcase' || fetchAccount;
|
const isAccountLoaded = mode === 'showcase' || useFetchAccount;
|
||||||
const loadCompleted = mode && isAccountLoaded;
|
const loadCompleted = mode && isAccountLoaded;
|
||||||
|
|
||||||
let options, persistence: PersistenceManager;
|
let options, persistence: PersistenceManager;
|
||||||
@ -99,10 +99,10 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (options?.mapTitle) {
|
if (mapInfo) {
|
||||||
document.title = `${options.mapTitle} | WiseMapping `;
|
document.title = `${mapInfo.getTitle()} | WiseMapping `;
|
||||||
}
|
}
|
||||||
}, [loadCompleted]);
|
}, [mapInfo]);
|
||||||
|
|
||||||
return loadCompleted ? (
|
return loadCompleted ? (
|
||||||
<IntlProvider
|
<IntlProvider
|
||||||
|
@ -13,32 +13,6 @@ import Link from '@mui/material/Link';
|
|||||||
import ReactGA from 'react-ga4';
|
import ReactGA from 'react-ga4';
|
||||||
import { getCsrfToken, getCsrfTokenParameter } from '../../utils';
|
import { getCsrfToken, getCsrfTokenParameter } from '../../utils';
|
||||||
|
|
||||||
type ConfigStatusProps = {
|
|
||||||
enabled?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ConfigStatusMessage = ({ enabled = false }: ConfigStatusProps): React.ReactElement => {
|
|
||||||
let result;
|
|
||||||
if (enabled === true) {
|
|
||||||
result = (
|
|
||||||
<div className="db-warn-msg">
|
|
||||||
<p>
|
|
||||||
<FormattedMessage
|
|
||||||
id="login.hsqldbcofig"
|
|
||||||
defaultMessage="Although HSQLDB is bundled with WiseMapping by default during the installation, we do not recommend this database for production use. Please consider using MySQL 5.7 instead. You can find more information how to configure MySQL"
|
|
||||||
description="Missing production database configured"
|
|
||||||
/>
|
|
||||||
<a href="https://wisemapping.atlassian.net/wiki/display/WS/Database+Configuration">
|
|
||||||
{' '}
|
|
||||||
here
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return result || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const LoginError = () => {
|
const LoginError = () => {
|
||||||
// @Todo: This must be reviewed to be based on navigation state.
|
// @Todo: This must be reviewed to be based on navigation state.
|
||||||
// Login error example: http://localhost:8080/c/login?login.error=2
|
// Login error example: http://localhost:8080/c/login?login.error=2
|
||||||
@ -132,7 +106,6 @@ const LoginPage = (): React.ReactElement => {
|
|||||||
<Link component={RouterLink} to="/c/forgot-password">
|
<Link component={RouterLink} to="/c/forgot-password">
|
||||||
<FormattedMessage id="login.forgotpwd" defaultMessage="Forgot Password ?" />
|
<FormattedMessage id="login.forgotpwd" defaultMessage="Forgot Password ?" />
|
||||||
</Link>
|
</Link>
|
||||||
<ConfigStatusMessage />
|
|
||||||
</FormContainer>
|
</FormContainer>
|
||||||
|
|
||||||
<Footer />
|
<Footer />
|
||||||
|
@ -5,7 +5,7 @@ import Client, { ErrorInfo } from '../../../../classes/client';
|
|||||||
import Input from '../../../form/input';
|
import Input from '../../../form/input';
|
||||||
import BaseDialog from '../../action-dispatcher/base-dialog';
|
import BaseDialog from '../../action-dispatcher/base-dialog';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { activeInstance, fetchAccount } from '../../../../redux/clientSlice';
|
import { activeInstance, useFetchAccount } from '../../../../redux/clientSlice';
|
||||||
|
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import FormControl from '@mui/material/FormControl';
|
import FormControl from '@mui/material/FormControl';
|
||||||
@ -63,7 +63,7 @@ const AccountInfoDialog = ({ onClose }: AccountInfoDialogProps): React.ReactElem
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const account = fetchAccount();
|
const account = useFetchAccount();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (account) {
|
if (account) {
|
||||||
setModel({
|
setModel({
|
||||||
|
@ -7,7 +7,7 @@ import SettingsApplicationsOutlined from '@mui/icons-material/SettingsApplicatio
|
|||||||
import AccountCircle from '@mui/icons-material/AccountCircle';
|
import AccountCircle from '@mui/icons-material/AccountCircle';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { fetchAccount } from '../../../redux/clientSlice';
|
import { useFetchAccount } from '../../../redux/clientSlice';
|
||||||
import AccountInfoDialog from './account-info-dialog';
|
import AccountInfoDialog from './account-info-dialog';
|
||||||
import ChangePasswordDialog from './change-password-dialog';
|
import ChangePasswordDialog from './change-password-dialog';
|
||||||
import LockOpenOutlined from '@mui/icons-material/LockOpenOutlined';
|
import LockOpenOutlined from '@mui/icons-material/LockOpenOutlined';
|
||||||
@ -34,7 +34,7 @@ const AccountMenu = (): React.ReactElement => {
|
|||||||
elem.submit();
|
elem.submit();
|
||||||
};
|
};
|
||||||
|
|
||||||
const account = fetchAccount();
|
const account = useFetchAccount();
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
@ -12,7 +12,7 @@ import LabelOutlined from '@mui/icons-material/LabelOutlined';
|
|||||||
import HistoryOutlined from '@mui/icons-material/HistoryOutlined';
|
import HistoryOutlined from '@mui/icons-material/HistoryOutlined';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { fetchMapById } from '../../../redux/clientSlice';
|
import { useFetchMapById } from '../../../redux/clientSlice';
|
||||||
import Menu from '@mui/material/Menu';
|
import Menu from '@mui/material/Menu';
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
@ -52,7 +52,7 @@ const ActionChooser = (props: ActionProps): React.ReactElement => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const role = mapId ? fetchMapById(mapId)?.map?.role : undefined;
|
const role = mapId ? useFetchMapById(mapId)?.map?.role : undefined;
|
||||||
return (
|
return (
|
||||||
<Menu
|
<Menu
|
||||||
anchorEl={anchor}
|
anchorEl={anchor}
|
||||||
|
@ -3,7 +3,7 @@ import { FormattedMessage, useIntl } from 'react-intl';
|
|||||||
import { useMutation, useQueryClient } from 'react-query';
|
import { useMutation, useQueryClient } from 'react-query';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import Client, { ErrorInfo } from '../../../../classes/client';
|
import Client, { ErrorInfo } from '../../../../classes/client';
|
||||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice';
|
import { activeInstance, useFetchMapById } from '../../../../redux/clientSlice';
|
||||||
import { SimpleDialogProps, handleOnMutationSuccess } from '..';
|
import { SimpleDialogProps, handleOnMutationSuccess } from '..';
|
||||||
import BaseDialog from '../base-dialog';
|
import BaseDialog from '../base-dialog';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
@ -30,7 +30,7 @@ const DeleteDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
mutation.mutate(mapId);
|
mutation.mutate(mapId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { map } = fetchMapById(mapId);
|
const { map } = useFetchMapById(mapId);
|
||||||
const alertTitle = `${intl.formatMessage({
|
const alertTitle = `${intl.formatMessage({
|
||||||
id: 'action.delete-title',
|
id: 'action.delete-title',
|
||||||
defaultMessage: 'Delete',
|
defaultMessage: 'Delete',
|
||||||
|
@ -5,7 +5,7 @@ import FormControl from '@mui/material/FormControl';
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
|
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
|
||||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice';
|
import { activeInstance, useFetchMapById } from '../../../../redux/clientSlice';
|
||||||
import Input from '../../../form/input';
|
import Input from '../../../form/input';
|
||||||
import { SimpleDialogProps } from '..';
|
import { SimpleDialogProps } from '..';
|
||||||
import BaseDialog from '../base-dialog';
|
import BaseDialog from '../base-dialog';
|
||||||
@ -56,7 +56,7 @@ const DuplicateDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElem
|
|||||||
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
const { map } = fetchMapById(mapId);
|
const { map } = useFetchMapById(mapId);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (map) {
|
if (map) {
|
||||||
setModel(map);
|
setModel(map);
|
||||||
|
@ -3,7 +3,7 @@ import { FormattedMessage, useIntl } from 'react-intl';
|
|||||||
import BaseDialog from '../base-dialog';
|
import BaseDialog from '../base-dialog';
|
||||||
import { useStyles } from './style';
|
import { useStyles } from './style';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import { fetchMapById } from '../../../../redux/clientSlice';
|
import { useFetchMapById } from '../../../../redux/clientSlice';
|
||||||
import FormControl from '@mui/material/FormControl';
|
import FormControl from '@mui/material/FormControl';
|
||||||
import RadioGroup from '@mui/material/RadioGroup';
|
import RadioGroup from '@mui/material/RadioGroup';
|
||||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||||
@ -39,7 +39,7 @@ const ExportDialog = ({
|
|||||||
}: ExportDialogProps): React.ReactElement => {
|
}: ExportDialogProps): React.ReactElement => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [submit, setSubmit] = React.useState<boolean>(false);
|
const [submit, setSubmit] = React.useState<boolean>(false);
|
||||||
const { map } = fetchMapById(mapId);
|
const { map } = useFetchMapById(mapId);
|
||||||
|
|
||||||
const [exportGroup, setExportGroup] = React.useState<ExportGroup>(
|
const [exportGroup, setExportGroup] = React.useState<ExportGroup>(
|
||||||
enableImgExport ? 'image' : 'document',
|
enableImgExport ? 'image' : 'document',
|
||||||
|
@ -34,11 +34,13 @@ const ActionDispatcher = ({
|
|||||||
fromEditor,
|
fromEditor,
|
||||||
}: ActionDialogProps): React.ReactElement => {
|
}: ActionDialogProps): React.ReactElement => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (action) {
|
||||||
ReactGA.event({
|
ReactGA.event({
|
||||||
category: 'map metadata',
|
category: 'map metadata',
|
||||||
action: action,
|
action: action,
|
||||||
nonInteraction: true,
|
nonInteraction: true,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}, [action]);
|
}, [action]);
|
||||||
|
|
||||||
const handleOnClose = (success?: boolean): void => {
|
const handleOnClose = (success?: boolean): void => {
|
||||||
|
@ -6,7 +6,7 @@ import BaseDialog from '../base-dialog';
|
|||||||
import { SimpleDialogProps } from '..';
|
import { SimpleDialogProps } from '..';
|
||||||
import { useStyles } from './style';
|
import { useStyles } from './style';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { fetchMapById } from '../../../../redux/clientSlice';
|
import { useFetchMapById } from '../../../../redux/clientSlice';
|
||||||
import Paper from '@mui/material/Paper';
|
import Paper from '@mui/material/Paper';
|
||||||
import Card from '@mui/material/Card';
|
import Card from '@mui/material/Card';
|
||||||
import ListItem from '@mui/material/ListItem';
|
import ListItem from '@mui/material/ListItem';
|
||||||
@ -18,7 +18,7 @@ import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
|||||||
dayjs.extend(LocalizedFormat);
|
dayjs.extend(LocalizedFormat);
|
||||||
|
|
||||||
const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||||
const { map } = fetchMapById(mapId);
|
const { map } = useFetchMapById(mapId);
|
||||||
const [error, setError] = React.useState<ErrorInfo>();
|
const [error, setError] = React.useState<ErrorInfo>();
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
@ -3,7 +3,7 @@ import { FormattedMessage, useIntl } from 'react-intl';
|
|||||||
import { useMutation, useQueryClient } from 'react-query';
|
import { useMutation, useQueryClient } from 'react-query';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import Client, { ErrorInfo } from '../../../../classes/client';
|
import Client, { ErrorInfo } from '../../../../classes/client';
|
||||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice';
|
import { activeInstance, useFetchMapById } from '../../../../redux/clientSlice';
|
||||||
import BaseDialog from '../base-dialog';
|
import BaseDialog from '../base-dialog';
|
||||||
import { handleOnMutationSuccess, SimpleDialogProps } from '..';
|
import { handleOnMutationSuccess, SimpleDialogProps } from '..';
|
||||||
import { useStyles } from './style';
|
import { useStyles } from './style';
|
||||||
@ -17,11 +17,11 @@ import Tab from '@mui/material/Tab';
|
|||||||
import TabPanel from '@mui/lab/TabPanel';
|
import TabPanel from '@mui/lab/TabPanel';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import TextareaAutosize from '@mui/material/TextareaAutosize';
|
import TextareaAutosize from '@mui/material/TextareaAutosize';
|
||||||
import Box from '@mui/system/Box';
|
|
||||||
import AppConfig from '../../../../classes/app-config';
|
import AppConfig from '../../../../classes/app-config';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
|
||||||
const PublishDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
const PublishDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||||
const { map } = fetchMapById(mapId);
|
const { map } = useFetchMapById(mapId);
|
||||||
|
|
||||||
const client: Client = useSelector(activeInstance);
|
const client: Client = useSelector(activeInstance);
|
||||||
const [model, setModel] = React.useState<boolean>(map ? map.isPublic : false);
|
const [model, setModel] = React.useState<boolean>(map ? map.isPublic : false);
|
||||||
@ -38,6 +38,7 @@ const PublishDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElemen
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setModel(model);
|
setModel(model);
|
||||||
handleOnMutationSuccess(onClose, queryClient);
|
handleOnMutationSuccess(onClose, queryClient);
|
||||||
|
queryClient.invalidateQueries(`maps-${mapId}`);
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
setError(error);
|
setError(error);
|
||||||
|
@ -3,7 +3,7 @@ import { useIntl } from 'react-intl';
|
|||||||
import { useMutation, useQueryClient } from 'react-query';
|
import { useMutation, useQueryClient } from 'react-query';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
|
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
|
||||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice';
|
import { activeInstance, useFetchMapById } from '../../../../redux/clientSlice';
|
||||||
import { SimpleDialogProps, handleOnMutationSuccess } from '..';
|
import { SimpleDialogProps, handleOnMutationSuccess } from '..';
|
||||||
import Input from '../../../form/input';
|
import Input from '../../../form/input';
|
||||||
import BaseDialog from '../base-dialog';
|
import BaseDialog from '../base-dialog';
|
||||||
@ -58,7 +58,7 @@ const RenameDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
const { map } = fetchMapById(mapId);
|
const { map } = useFetchMapById(mapId);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (map) {
|
if (map) {
|
||||||
setModel(map);
|
setModel(map);
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { alpha, Theme } from '@mui/material/styles';
|
import { alpha, useTheme } from '@mui/material/styles';
|
||||||
|
|
||||||
import createStyles from '@mui/styles/createStyles';
|
import createStyles from '@mui/styles/createStyles';
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
import makeStyles from '@mui/styles/makeStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles((theme: Theme) =>
|
export const useStyles = makeStyles(() =>
|
||||||
createStyles({
|
createStyles({
|
||||||
root: {
|
root: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
},
|
},
|
||||||
paper: {
|
paper: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
marginBottom: theme.spacing(2),
|
marginBottom: useTheme().spacing(2),
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
minWidth: 750,
|
minWidth: 750,
|
||||||
@ -66,14 +66,14 @@ export const useStyles = makeStyles((theme: Theme) =>
|
|||||||
},
|
},
|
||||||
search: {
|
search: {
|
||||||
borderRadius: 9,
|
borderRadius: 9,
|
||||||
backgroundColor: alpha(theme.palette.common.white, 0.15),
|
backgroundColor: alpha(useTheme().palette.common.white, 0.15),
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: alpha(theme.palette.common.white, 0.25),
|
backgroundColor: alpha(useTheme().palette.common.white, 0.25),
|
||||||
},
|
},
|
||||||
margin: '10px 0px',
|
margin: '10px 0px',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
[theme.breakpoints.up('sm')]: {
|
[useTheme().breakpoints.up('sm')]: {
|
||||||
marginLeft: theme.spacing(1),
|
marginLeft: useTheme().spacing(1),
|
||||||
width: 'auto',
|
width: 'auto',
|
||||||
},
|
},
|
||||||
float: 'right',
|
float: 'right',
|
||||||
@ -97,10 +97,10 @@ export const useStyles = makeStyles((theme: Theme) =>
|
|||||||
// vertical padding + font size from searchIcon
|
// vertical padding + font size from searchIcon
|
||||||
border: '1px solid #ffa800',
|
border: '1px solid #ffa800',
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
|
paddingLeft: `calc(1em + ${useTheme().spacing(4)})`,
|
||||||
transition: theme.transitions.create('width'),
|
transition: useTheme().transitions.create('width'),
|
||||||
width: '100%',
|
width: '100%',
|
||||||
[theme.breakpoints.up('sm')]: {
|
[useTheme().breakpoints.up('sm')]: {
|
||||||
width: '12ch',
|
width: '12ch',
|
||||||
'&:focus': {
|
'&:focus': {
|
||||||
width: '20ch',
|
width: '20ch',
|
||||||
|
@ -1,30 +1,19 @@
|
|||||||
import { Theme } from '@mui/material/styles';
|
|
||||||
|
|
||||||
import createStyles from '@mui/styles/createStyles';
|
import createStyles from '@mui/styles/createStyles';
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
import makeStyles from '@mui/styles/makeStyles';
|
||||||
|
|
||||||
const drawerWidth = 300;
|
const drawerWidth = 300;
|
||||||
|
|
||||||
export const useStyles = makeStyles((theme: Theme) =>
|
export const useStyles = makeStyles(() =>
|
||||||
createStyles({
|
createStyles({
|
||||||
root: {
|
root: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
},
|
},
|
||||||
appBar: {
|
appBar: {
|
||||||
zIndex: theme.zIndex.drawer + 1,
|
|
||||||
transition: theme.transitions.create(['width', 'margin'], {
|
|
||||||
easing: theme.transitions.easing.sharp,
|
|
||||||
duration: theme.transitions.duration.leavingScreen,
|
|
||||||
}),
|
|
||||||
background: '#ffffff',
|
background: '#ffffff',
|
||||||
},
|
},
|
||||||
appBarShift: {
|
appBarShift: {
|
||||||
marginLeft: drawerWidth,
|
marginLeft: drawerWidth,
|
||||||
width: `calc(100% - ${drawerWidth}px)`,
|
width: `calc(100% - ${drawerWidth}px)`,
|
||||||
transition: theme.transitions.create(['width', 'margin'], {
|
|
||||||
easing: theme.transitions.easing.sharp,
|
|
||||||
duration: theme.transitions.duration.enteringScreen,
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
newMapButton: {
|
newMapButton: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
@ -48,10 +37,6 @@ export const useStyles = makeStyles((theme: Theme) =>
|
|||||||
drawerOpen: {
|
drawerOpen: {
|
||||||
background: '#ffa800',
|
background: '#ffa800',
|
||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
transition: theme.transitions.create('width', {
|
|
||||||
easing: theme.transitions.easing.sharp,
|
|
||||||
duration: theme.transitions.duration.enteringScreen,
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
toolbar: {
|
toolbar: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import App from './app';
|
import App from './app';
|
||||||
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
async function bootstrapApplication() {
|
async function bootstrapApplication() {
|
||||||
ReactDOM.render(<App />, document.getElementById('root') as HTMLElement);
|
const container = document.getElementById('root') as HTMLElement
|
||||||
|
const root = createRoot(container!);
|
||||||
|
root.render(<App />);
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrapApplication();
|
bootstrapApplication();
|
||||||
|
@ -58,7 +58,7 @@ type MapLoadResult = {
|
|||||||
map: MapInfo | null;
|
map: MapInfo | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchMapById = (id: number): MapLoadResult => {
|
export const useFetchMapById = (id: number): MapLoadResult => {
|
||||||
const client: Client = useSelector(activeInstance);
|
const client: Client = useSelector(activeInstance);
|
||||||
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>(`maps-${id}`, () => {
|
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>(`maps-${id}`, () => {
|
||||||
return client.fetchAllMaps();
|
return client.fetchAllMaps();
|
||||||
@ -85,7 +85,7 @@ export const fetchMapById = (id: number): MapLoadResult => {
|
|||||||
return { isLoading: isLoading, error: errorMsg, map: map };
|
return { isLoading: isLoading, error: errorMsg, map: map };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchAccount = (): AccountInfo | undefined => {
|
export const useFetchAccount = (): AccountInfo | undefined => {
|
||||||
const client: Client = useSelector(activeInstance);
|
const client: Client = useSelector(activeInstance);
|
||||||
const { data } = useQuery<unknown, ErrorInfo, AccountInfo>('account', () => {
|
const { data } = useQuery<unknown, ErrorInfo, AccountInfo>('account', () => {
|
||||||
return client.fetchAccountInfo();
|
return client.fetchAccountInfo();
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import { configureStore } from '@reduxjs/toolkit';
|
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
|
||||||
import rootReducer from './rootReducer';
|
import rootReducer from './rootReducer';
|
||||||
|
|
||||||
// Create Service object...
|
// Create Service object...
|
||||||
const store = configureStore({
|
const store = configureStore({
|
||||||
reducer: rootReducer,
|
reducer: rootReducer,
|
||||||
|
middleware: [
|
||||||
|
...getDefaultMiddleware({
|
||||||
|
serializableCheck: false,
|
||||||
|
}),
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
export default store;
|
export default store;
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
export const getCsrfToken = (): string | null => {
|
export const getCsrfToken = (): string | null => {
|
||||||
const meta = document.head.querySelector('meta[name="_csrf"]');
|
const meta = document.head.querySelector('meta[name="_csrf"]');
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
return meta.getAttribute('content');
|
return meta.getAttribute('content');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCsrfTokenParameter = (): string | null => {
|
export const getCsrfTokenParameter = (): string => {
|
||||||
const meta = document.head.querySelector('meta[name="_csrf_parameter"]');
|
const meta = document.head.querySelector('meta[name="_csrf_parameter"]');
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
return meta.getAttribute('content');
|
return meta.getAttribute('content');
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user