Export fixes.

This commit is contained in:
Matias Arriola 2022-01-31 21:07:59 +00:00 committed by Paulo Veiga
parent a502498c42
commit 7c9effaa5d
13 changed files with 252 additions and 209 deletions

View File

@ -0,0 +1,25 @@
import styled from 'styled-components';
const ActionButton = styled.div`
cursor: pointer;
margin: 0px 10px;
font-family: Arial, Helvetica, sans-serif;
user-select: none;
vertical-align: middle;
justify-content: center;
padding: 10px 25px;
font-size: 15px;
min-width: 64px;
box-sizing: border-box;
font-weight: 600;
border-radius: 9px;
color: white;
background-color: #ffa800;
display: inline-block;
&:hover {
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
}
`;
export default ActionButton;

View File

@ -1,11 +1,12 @@
import React from 'react'; import React from 'react';
import { StyledLogo } from './styled'; import { StyledLogo, Notifier } from './styled';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import KeyboardSvg from '../../../images/keyboard.svg'; import KeyboardSvg from '../../../images/keyboard.svg';
import AddSvg from '../../../images/add.svg'; import AddSvg from '../../../images/add.svg';
import MinusSvg from '../../../images/minus.svg'; import MinusSvg from '../../../images/minus.svg';
import CenterFocusSvg from '../../../images/center_focus.svg'; import CenterFocusSvg from '../../../images/center_focus.svg';
import ActionButton from '../action-button';
export type FooterPropsType = { export type FooterPropsType = {
showTryPanel?: boolean; showTryPanel?: boolean;
@ -35,15 +36,15 @@ const Footer = ({ showTryPanel }: FooterPropsType): React.ReactElement => {
</div> </div>
</div> </div>
<StyledLogo id="bottom-logo"></StyledLogo> <StyledLogo id="bottom-logo"></StyledLogo>
<div id="headerNotifier"></div> <Notifier id="headerNotifier"></Notifier>
{showTryPanel && ( {showTryPanel && (
<div id="tryInfoPanel"> <div id="tryInfoPanel">
<p>{intl.formatMessage({ id: 'editor.try-welcome' })}</p> <p>{intl.formatMessage({ id: 'editor.try-welcome' })}</p>
<p>{intl.formatMessage({ id: 'editor.try-welcome-description' })}</p> <p>{intl.formatMessage({ id: 'editor.try-welcome-description' })}</p>
<a href="/c/registration"> <a href="/c/registration">
<div className="actionButton"> <ActionButton>
{intl.formatMessage({ id: 'login.signup', defaultMessage: 'Sign Up' })} {intl.formatMessage({ id: 'login.signup', defaultMessage: 'Sign Up' })}
</div> </ActionButton>
</a> </a>
</div> </div>
)} )}

View File

@ -15,4 +15,17 @@ export const StyledLogo = styled.div`
background: url(${LogoTextBlackSvg}) no-repeat; background: url(${LogoTextBlackSvg}) no-repeat;
width: 90px; width: 90px;
height: 40px; height: 40px;
` `;
export const Notifier = styled.div`
border: 1px solid rgb(241, 163, 39);
background-color: rgb(252, 235, 192);
border-radius: 3px;
position: fixed;
padding: 5px 9px;
color: back;
white-space: nowrap;
margin-top: 5px;
display: none;
bottom: 10px;
`;

View File

@ -25,6 +25,9 @@ import HistorySvg from '../../../images/history.svg';
import PrintSvg from '../../../images/print.svg'; import PrintSvg from '../../../images/print.svg';
import AccountSvg from '../../../images/account.svg'; import AccountSvg from '../../../images/account.svg';
import { HeaderContainer, ToolbarButton, ToolbarButtonExt, ToolbarRightContainer } from './styled';
import ActionButton from '../action-button';
export type ToolbarActionType = 'export' | 'publish' | 'history' | 'print' | 'share'; export type ToolbarActionType = 'export' | 'publish' | 'history' | 'print' | 'share';
export type ToolbarPropsType = { export type ToolbarPropsType = {
@ -40,100 +43,118 @@ export default function Toolbar({
}: ToolbarPropsType): React.ReactElement { }: ToolbarPropsType): React.ReactElement {
const intl = useIntl(); const intl = useIntl();
return ( return (
<div id="toolbar"> <HeaderContainer>
<div id="backToList"> <div id="toolbar">
<img src={BackIconSvg} /> <div id="backToList">
<img src={BackIconSvg} />
</div>
{!memoryPersistence && (
<div id="persist" className="buttonContainer">
<ToolbarButton id="save" className="buttonOn">
<img src={SaveSvg} />
</ToolbarButton>
</div>
)}
{!readOnlyMode && (
<>
<div id="edit" className="buttonContainer">
<ToolbarButton id="undoEdition" className="buttonOn">
<img src={UndoSvg} />
</ToolbarButton>
<ToolbarButton id="redoEdition" className="buttonOn">
<img src={RedoSvg} />
</ToolbarButton>
</div>
<div id="nodeStyle" className="buttonContainer">
<ToolbarButton id="addTopic" className="buttonOn">
<img src={TopicAddSvg} />
</ToolbarButton>
<ToolbarButton id="deleteTopic" className="buttonOn">
<img src={TopicDeleteSvg} />
</ToolbarButton>
<ToolbarButtonExt id="topicBorder" className="buttonExtOn">
<img src={TopicBorderSvg} />
</ToolbarButtonExt>
<ToolbarButtonExt id="topicColor" className="buttonExtOn">
<img src={TopicColorSvg} />
</ToolbarButtonExt>
<ToolbarButtonExt id="topicShape" className="buttonExtOn">
<img src={TopicShapeSvg} />
</ToolbarButtonExt>
</div>
<div id="font" className="buttonContainer">
<ToolbarButton id="fontFamily" className="buttonOn">
<img src={FontTypeSvg} />
</ToolbarButton>
<ToolbarButtonExt id="fontSize" className="buttonExtOn">
<img src={FontSizeSvg} />
</ToolbarButtonExt>
<ToolbarButton id="fontBold" className="buttonOn">
<img src={FontBoldSvg} />
</ToolbarButton>
<ToolbarButton id="fontItalic" className="buttonOn">
<img src={FontItalicSvg} />
</ToolbarButton>
<ToolbarButtonExt id="fontColor" className="buttonExtOn">
<img src={FontColorSvg} />
</ToolbarButtonExt>
</div>
<div id="nodeContent" className="buttonContainer">
<ToolbarButtonExt id="topicIcon" className="buttonExtOn">
<img src={TopicIconSvg} />
</ToolbarButtonExt>
<ToolbarButton id="topicNote" className="buttonOn">
<img src={TopicNoteSvg} />
</ToolbarButton>
<ToolbarButton id="topicLink" className="buttonOn">
<img src={TopicLinkSvg} />
</ToolbarButton>
<ToolbarButton id="topicRelation" className="buttonOn">
<img src={TopicRelationSvg} />
</ToolbarButton>
</div>
<div id="separator" className="buttonContainer"></div>
</>
)}
{!memoryPersistence && (
<ToolbarRightContainer>
<ToolbarButton
id="export"
className="buttonOn"
onClick={() => onAction('export')}
>
<img src={ExportSvg} />
</ToolbarButton>
<ToolbarButton
id="publishIt"
className="buttonOn"
onClick={() => onAction('publish')}
>
<img src={PublicSvg} />
</ToolbarButton>
<ToolbarButton
id="history"
className="buttonOn"
onClick={() => onAction('history')}
>
<img src={HistorySvg} />
</ToolbarButton>
<ToolbarButton
id="print"
className="buttonOn"
onClick={() => onAction('print')}
>
<img src={PrintSvg} />
</ToolbarButton>
<ToolbarButton id="account">
<img src={AccountSvg} />
</ToolbarButton>
<ActionButton onClick={() => onAction('share')}>
{intl.formatMessage({ id: 'action.share', defaultMessage: 'Share' })}
</ActionButton>
</ToolbarRightContainer>
)}
</div> </div>
{!memoryPersistence && ( </HeaderContainer>
<div id="persist" className="buttonContainer">
<div id="save" className="buttonOn">
<img src={SaveSvg} />
</div>
</div>
)}
{!readOnlyMode && (
<>
<div id="edit" className="buttonContainer">
<div id="undoEdition" className="buttonOn">
<img src={UndoSvg} />
</div>
<div id="redoEdition" className="buttonOn">
<img src={RedoSvg} />
</div>
</div>
<div id="nodeStyle" className="buttonContainer">
<div id="addTopic" className="buttonOn">
<img src={TopicAddSvg} />
</div>
<div id="deleteTopic" className="buttonOn">
<img src={TopicDeleteSvg} />
</div>
<div id="topicBorder" className="buttonExtOn">
<img src={TopicBorderSvg} />
</div>
<div id="topicColor" className="buttonExtOn">
<img src={TopicColorSvg} />
</div>
<div id="topicShape" className="buttonExtOn">
<img src={TopicShapeSvg} />
</div>
</div>
<div id="font" className="buttonContainer">
<div id="fontFamily" className="buttonOn">
<img src={FontTypeSvg} />
</div>
<div id="fontSize" className="buttonExtOn">
<img src={FontSizeSvg} />
</div>
<div id="fontBold" className="buttonOn">
<img src={FontBoldSvg} />
</div>
<div id="fontItalic" className="buttonOn">
<img src={FontItalicSvg} />
</div>
<div id="fontColor" className="buttonExtOn">
<img src={FontColorSvg} />
</div>
</div>
<div id="nodeContent" className="buttonContainer">
<div id="topicIcon" className="buttonExtOn">
<img src={TopicIconSvg} />
</div>
<div id="topicNote" className="buttonOn">
<img src={TopicNoteSvg} />
</div>
<div id="topicLink" className="buttonOn">
<img src={TopicLinkSvg} />
</div>
<div id="topicRelation" className="buttonOn">
<img src={TopicRelationSvg} />
</div>
</div>
<div id="separator" className="buttonContainer"></div>
</>
)}
{!memoryPersistence && (
<div id="toolbarRight">
<div id="export" className="buttonOn" onClick={() => onAction('export')}>
<img src={ExportSvg} />
</div>
<div id="publishIt" className="buttonOn" onClick={() => onAction('publish')}>
<img src={PublicSvg} />
</div>
<div id="history" className="buttonOn" onClick={() => onAction('history')}>
<img src={HistorySvg} />
</div>
<div id="print" className="buttonOn" onClick={() => onAction('print')}>
<img src={PrintSvg} />
</div>
<div id="account">
<img src={AccountSvg} />
</div>
<div id="share" className="actionButton" onClick={() => onAction('share')}>
{ intl.formatMessage({ id: 'action.share', defaultMessage: 'Share' }) }
</div>
</div>
)}
</div>
); );
} }

View File

@ -0,0 +1,50 @@
import styled from 'styled-components';
export const HeaderContainer = styled.div`
width: 100%;
height: 0px;
background: #202020;
z-index: 1000;
position: absolute;
top: 0;
display: flex;
`;
export const ToolbarContainer = styled.div`
display: flex;
flex-direction: column;
flex: 1;
`;
export const ToolbarButton = styled.div`
width: 28px;
height: 28px;
text-align: center;
z-index: 4;
margin-top: 3px;
padding-top: 2px;
padding-left: 2px;
margin-left: 3px;
display: inline-block;
`;
export const ToolbarButtonExt = styled(ToolbarButton)`
width: 40px;
text-align: left;
padding-left: 5px;
`;
export const AccountButton = styled.div`
display: inline-block;
margin-top: 3px;
`;
export const ToolbarRightContainer = styled.div`
flex-shrink: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
height: 100%;
overflow: hidden;
`;

View File

@ -2,7 +2,14 @@ import React from 'react';
import Toolbar, { ToolbarActionType } from './components/toolbar'; import Toolbar, { ToolbarActionType } from './components/toolbar';
import Footer from './components/footer'; import Footer from './components/footer';
import { IntlProvider } from 'react-intl'; import { IntlProvider } from 'react-intl';
import { $notify, buildDesigner, LocalStorageManager, PersistenceManager, RESTPersistenceManager, DesignerOptionsBuilder } from '@wisemapping/mindplot'; import {
$notify,
buildDesigner,
LocalStorageManager,
PersistenceManager,
RESTPersistenceManager,
DesignerOptionsBuilder,
} from '@wisemapping/mindplot';
declare global { declare global {
var memoryPersistence: boolean; var memoryPersistence: boolean;
@ -28,9 +35,8 @@ export type EditorPropsType = {
}; };
const initMindplot = () => { const initMindplot = () => {
// Change page title ... // Change page title ...
document.title = `${global.mapTitle} | WiseMapping ` document.title = `${global.mapTitle} | WiseMapping `;
// Configure persistence manager ... // Configure persistence manager ...
let persistence; let persistence;
@ -44,7 +50,8 @@ const initMindplot = () => {
}); });
} else { } else {
persistence = new LocalStorageManager( persistence = new LocalStorageManager(
`/c/restful/maps/{id}/${global.historyId ? `${global.historyId}/` : ''}document/xml${!global.isAuth ? '-pub' : '' `/c/restful/maps/{id}/${global.historyId ? `${global.historyId}/` : ''}document/xml${
!global.isAuth ? '-pub' : ''
}`, }`,
true true
); );
@ -58,7 +65,11 @@ const initMindplot = () => {
readOnly: Boolean(global.readOnly || false), readOnly: Boolean(global.readOnly || false),
mapId: String(global.mapId), mapId: String(global.mapId),
container: 'mindplot', container: 'mindplot',
zoom: zoomParam || (global.userOptions?.zoom != undefined ? Number.parseFloat(global.userOptions.zoom as string) : 0.8), zoom:
zoomParam ||
(global.userOptions?.zoom != undefined
? Number.parseFloat(global.userOptions.zoom as string)
: 0.8),
locale: global.locale, locale: global.locale,
}); });
@ -83,20 +94,17 @@ export default function Editor({
locale = 'en', locale = 'en',
onAction, onAction,
}: EditorPropsType): React.ReactElement { }: EditorPropsType): React.ReactElement {
React.useEffect(initCallback, []); React.useEffect(initCallback, []);
return ( return (
<IntlProvider locale={locale} defaultLocale="en" messages={{}}> <IntlProvider locale={locale} defaultLocale="en" messages={{}}>
<div id="header"> <Toolbar
<Toolbar memoryPersistence={memoryPersistence}
memoryPersistence={memoryPersistence} readOnlyMode={readOnlyMode}
readOnlyMode={readOnlyMode} onAction={onAction}
onAction={onAction} />
/>
</div>
<div id="mindplot"></div> <div id="mindplot"></div>
<Footer showTryPanel={memoryPersistence} /> <Footer showTryPanel={memoryPersistence} />
</IntlProvider> </IntlProvider>
); );
} }

View File

@ -1,80 +1,6 @@
@import "toolbar.css"; @import "toolbar.css";
div#header {
width: 100%;
height: 0px;
background: #202020;
z-index: 1000;
position: absolute;
top: 0;
}
div#headerActions span {
border-bottom: 3px solid rgb(247, 201, 49);
}
div#headerActions a {
color: white;
text-decoration: none;
}
div#headerNotifier {
border: 1px solid rgb(241, 163, 39);
background-color: rgb(252, 235, 192);
border-radius: 3px;
position: fixed;
padding: 5px 9px;
color: back;
white-space: nowrap;
margin-top: 5px;
display: none;
bottom: 10px;
}
div#toolbarRight {
float: right;
white-space: nowrap;
vertical-align: middle;
justify-content: center;
margin: 6px 10px;
height: 100%;
}
#account {
float: right;
display: inline;
}
#account >img {
width: 36x;
height: 36px;
}
#accountSettingsPanel{ #accountSettingsPanel{
padding:10px 10px; padding:10px 10px;
}
#share {
margin: 0 30px;
}
.actionButton {
float: right;
cursor: pointer;
margin: 0px 10px;
font-family: Arial, Helvetica, sans-serif;
user-select: none;
vertical-align: middle;
justify-content: center;
padding: 10px 25px;
font-size: 15px;
min-width: 64px;
box-sizing: border-box;
font-weight: 600;
border-radius: 9px;
color: white;
background-color: #ffa800;
}
.actionButton:hover {
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
} }

View File

@ -1,6 +1,4 @@
const path = require('path'); const path = require('path');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = { module.exports = {
output: { output: {
@ -40,7 +38,4 @@ module.exports = {
}, },
], ],
}, },
plugins: [
new CleanWebpackPlugin(),
]
} }

View File

@ -36,7 +36,10 @@ const playgroundConfig = {
], ],
}, },
plugins: [ plugins: [
new CleanWebpackPlugin(), new CleanWebpackPlugin({
dangerouslyAllowCleanPatternsOutsideProject: true,
dry: false,
}),
new CopyPlugin({ new CopyPlugin({
patterns: [ patterns: [
{ from: 'test/playground/map-render/images/favicon.ico', to: 'favicon.ico' }, { from: 'test/playground/map-render/images/favicon.ico', to: 'favicon.ico' },

View File

@ -1,5 +1,6 @@
const { merge } = require('webpack-merge'); const { merge } = require('webpack-merge');
const common = require('./webpack.common'); const common = require('./webpack.common');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const prodConfig = { const prodConfig = {
optimization: { optimization: {
@ -8,9 +9,12 @@ const prodConfig = {
}, },
externals: { externals: {
react: 'react', react: 'react',
reactDOM: 'react-dom', "react-dom": 'react-dom',
reactIntl: 'react-intl', "react-intl": 'react-intl',
}, },
plugins: [
new CleanWebpackPlugin(),
]
}; };
module.exports = merge(common, prodConfig); module.exports = merge(common, prodConfig);

View File

@ -20,8 +20,8 @@ import { $assert } from '@wisemapping/core-js';
import $ from 'jquery'; import $ from 'jquery';
class ToolbarNotifier { class ToolbarNotifier {
constructor() { get container() {
this.container = $('#headerNotifier'); return $('#headerNotifier');
} }
hide() { hide() {
@ -31,7 +31,7 @@ class ToolbarNotifier {
logMessage(msg) { logMessage(msg) {
$assert(msg, 'msg can not be null'); $assert(msg, 'msg can not be null');
// In case of print,embedded no message is displayed .... // In case of print,embedded no message is displayed ....
if (this.container && !this.container.data('transitioning')) { if (this.container && this.container.length && !this.container.data('transitioning')) {
this.container.data('transitioning', true); this.container.data('transitioning', true);
this.container.text(msg); this.container.text(msg);
this.container.css({ this.container.css({

View File

@ -61,6 +61,7 @@
"@material-ui/lab": "^4.0.0-alpha.57", "@material-ui/lab": "^4.0.0-alpha.57",
"@reduxjs/toolkit": "^1.5.0", "@reduxjs/toolkit": "^1.5.0",
"@wisemapping/editor": "^0.4.0", "@wisemapping/editor": "^0.4.0",
"@wisemapping/mindplot": "^5.0.2",
"axios": "^0.21.0", "axios": "^0.21.0",
"dayjs": "^1.10.4", "dayjs": "^1.10.4",
"react": "^17.0.0", "react": "^17.0.0",

View File

@ -10,7 +10,7 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
import Radio from '@material-ui/core/Radio'; import Radio from '@material-ui/core/Radio';
import Select from '@material-ui/core/Select'; import Select from '@material-ui/core/Select';
import MenuItem from '@material-ui/core/MenuItem'; import MenuItem from '@material-ui/core/MenuItem';
import { Designer, TextExporterFactory, ImageExporterFactory, Exporter, Mindmap, RESTPersistenceManager } from '@wisemapping/mindplot'; import { Designer, TextExporterFactory, ImageExporterFactory, Exporter, Mindmap, LocalStorageManager } from '@wisemapping/mindplot';
type ExportFormat = 'svg' | 'jpg' | 'png' | 'txt' | 'mm' | 'wxml' | 'xls' | 'md'; type ExportFormat = 'svg' | 'jpg' | 'png' | 'txt' | 'mm' | 'wxml' | 'xls' | 'md';
type ExportGroup = 'image' | 'document' | 'mindmap-tool'; type ExportGroup = 'image' | 'document' | 'mindmap-tool';
@ -29,6 +29,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 [exportGroup, setExportGroup] = React.useState<ExportGroup>( const [exportGroup, setExportGroup] = React.useState<ExportGroup>(
enableImgExport ? 'image' : 'document' enableImgExport ? 'image' : 'document'
@ -83,15 +84,11 @@ const ExportDialog = ({
mindmap = designer.getMindmap(); mindmap = designer.getMindmap();
} else { } else {
// Load mindmap ... // Load mindmap ...
const persistence = new RESTPersistenceManager({ const persistence = new LocalStorageManager(
documentUrl: '/c/restful/maps/{id}/document', `/c/restful/maps/{id}/document/xml`,
revertUrl: '/c/restful/maps/{id}/history/latest', true
lockUrl: '/c/restful/maps/{id}/lock', );
timestamp: global.lockTimestamp, mindmap = persistence.load(mapId.toString());
session: global.lockSession,
});
mindmap = persistence.load(global.mapId)
} }
let exporter: Exporter; let exporter: Exporter;
@ -116,7 +113,6 @@ const ExportDialog = ({
}; };
useEffect(() => { useEffect(() => {
const { map } = fetchMapById(mapId);
if (submit) { if (submit) {
exporter(exportFormat) exporter(exportFormat)
.then((url: string) => { .then((url: string) => {