mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-23 15:17:57 +01:00
Add mobile support for mindmap list.
This commit is contained in:
parent
82dcd34dc5
commit
5f67aa8c5c
@ -76,12 +76,12 @@ export class DefaultWidgetManager extends WidgetManager {
|
|||||||
topic.closeEditors();
|
topic.closeEditors();
|
||||||
}
|
}
|
||||||
|
|
||||||
static useCreate(): [boolean, Element | undefined, DefaultWidgetManager] {
|
static useCreate(): [boolean, (boolean) => void, Element | undefined, DefaultWidgetManager] {
|
||||||
const [popoverOpen, setPopoverOpen] = useState(false);
|
const [popoverOpen, setPopoverOpen] = useState(false);
|
||||||
const [popoverTarget, setPopoverTarget] = useState(undefined);
|
const [popoverTarget, setPopoverTarget] = useState(undefined);
|
||||||
const widgetManager = useRef(new DefaultWidgetManager(setPopoverOpen, setPopoverTarget));
|
const widgetManager = useRef(new DefaultWidgetManager(setPopoverOpen, setPopoverTarget));
|
||||||
|
|
||||||
return [popoverOpen, popoverTarget, widgetManager.current];
|
return [popoverOpen, setPopoverOpen, popoverTarget, widgetManager.current];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +34,6 @@ const SaveAndDelete = (props: {
|
|||||||
<FormattedMessage id="action.accept" defaultMessage="Accept" />
|
<FormattedMessage id="action.accept" defaultMessage="Accept" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button color="primary" variant="outlined" onClick={props.closeModal}>
|
|
||||||
<FormattedMessage id="action.cancel" defaultMessage="Cancel" />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{props.model.getValue() && props.model.getValue().trim() !== '' && (
|
{props.model.getValue() && props.model.getValue().trim() !== '' && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -59,7 +59,7 @@ const TopicLink = (props: {
|
|||||||
const isValidUrl = !url || checkURL(url);
|
const isValidUrl = !url || checkURL(url);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box display="flex" sx={{ p: 1 }}>
|
<Box sx={{ p: 1 }}>
|
||||||
<Input
|
<Input
|
||||||
autoFocus
|
autoFocus
|
||||||
error={!isValidUrl}
|
error={!isValidUrl}
|
||||||
@ -87,8 +87,9 @@ const TopicLink = (props: {
|
|||||||
</Link>
|
</Link>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
sx={{ pr: 1 }}
|
margin="dense"
|
||||||
></Input>
|
></Input>
|
||||||
|
<br />
|
||||||
<SaveAndDelete
|
<SaveAndDelete
|
||||||
model={props.urlModel}
|
model={props.urlModel}
|
||||||
closeModal={props.closeModal}
|
closeModal={props.closeModal}
|
||||||
|
@ -29,9 +29,7 @@ import {
|
|||||||
} from '@wisemapping/mindplot';
|
} from '@wisemapping/mindplot';
|
||||||
|
|
||||||
import I18nMsg from '../classes/i18n-msg';
|
import I18nMsg from '../classes/i18n-msg';
|
||||||
import { theme as defaultEditorTheme } from '../theme';
|
|
||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import ThemeProvider from '@mui/material/styles/ThemeProvider';
|
|
||||||
import { Theme } from '@mui/material/styles';
|
import { Theme } from '@mui/material/styles';
|
||||||
import { Notifier } from './warning-dialog/styled';
|
import { Notifier } from './warning-dialog/styled';
|
||||||
import WarningDialog from './warning-dialog';
|
import WarningDialog from './warning-dialog';
|
||||||
@ -42,6 +40,9 @@ import { ToolbarActionType } from './toolbar/ToolbarActionType';
|
|||||||
import MapInfo from '../classes/model/map-info';
|
import MapInfo from '../classes/model/map-info';
|
||||||
import EditorToolbar from './editor-toolbar';
|
import EditorToolbar from './editor-toolbar';
|
||||||
import ZoomPanel from './zoom-panel';
|
import ZoomPanel from './zoom-panel';
|
||||||
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
import { SpinnerCentered } from './style';
|
import { SpinnerCentered } from './style';
|
||||||
|
|
||||||
export type EditorOptions = {
|
export type EditorOptions = {
|
||||||
@ -66,7 +67,6 @@ const Editor = ({
|
|||||||
options,
|
options,
|
||||||
persistenceManager,
|
persistenceManager,
|
||||||
onAction,
|
onAction,
|
||||||
theme,
|
|
||||||
accountConfiguration,
|
accountConfiguration,
|
||||||
}: EditorProps): ReactElement => {
|
}: EditorProps): ReactElement => {
|
||||||
const [model, setModel] = useState<Model | undefined>();
|
const [model, setModel] = useState<Model | undefined>();
|
||||||
@ -75,8 +75,8 @@ const Editor = ({
|
|||||||
// This is required to redraw in case of chansges in the canvas...
|
// This is required to redraw in case of chansges in the canvas...
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const [canvasUpdate, setCanvasUpdate] = useState<number>();
|
const [canvasUpdate, setCanvasUpdate] = useState<number>();
|
||||||
const editorTheme: Theme = theme ? theme : defaultEditorTheme;
|
const [popoverOpen, setPopoverOpen, popoverTarget, widgetManager] =
|
||||||
const [popoverOpen, popoverTarget, widgetManager] = DefaultWidgetManager.useCreate();
|
DefaultWidgetManager.useCreate();
|
||||||
const capability = new Capability(options.mode, mapInfo.isLocked());
|
const capability = new Capability(options.mode, mapInfo.isLocked());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -108,7 +108,6 @@ const Editor = ({
|
|||||||
const locale = options.locale;
|
const locale = options.locale;
|
||||||
const msg = I18nMsg.loadLocaleData(locale);
|
const msg = I18nMsg.loadLocaleData(locale);
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={editorTheme}>
|
|
||||||
<IntlProvider locale={locale} messages={msg}>
|
<IntlProvider locale={locale} messages={msg}>
|
||||||
<AppBar
|
<AppBar
|
||||||
model={model}
|
model={model}
|
||||||
@ -128,6 +127,11 @@ const Editor = ({
|
|||||||
horizontal: 'left',
|
horizontal: 'left',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Box alignItems={'end'}>
|
||||||
|
<IconButton onClick={() => setPopoverOpen(false)} aria-label={'Close'}>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
{widgetManager.getEditorContent()}
|
{widgetManager.getEditorContent()}
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|
||||||
@ -160,7 +164,6 @@ const Editor = ({
|
|||||||
</SpinnerCentered>
|
</SpinnerCentered>
|
||||||
)}
|
)}
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
</ThemeProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default Editor;
|
export default Editor;
|
||||||
|
@ -25,6 +25,7 @@ import '../app-bar/styles.css';
|
|||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import ToolbarPosition from '../../classes/model/toolbar-position';
|
import ToolbarPosition from '../../classes/model/toolbar-position';
|
||||||
import ActionConfig from '../../classes/action/action-config';
|
import ActionConfig from '../../classes/action/action-config';
|
||||||
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common button
|
* Common button
|
||||||
@ -106,7 +107,11 @@ export const ToolbarSubmenu = (props: {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ToolbarButtonOption
|
<ToolbarButtonOption
|
||||||
configuration={{ ...props.configuration, onClick: () => setOpen(true) }}
|
configuration={{
|
||||||
|
...props.configuration,
|
||||||
|
onClick: () => setOpen(true),
|
||||||
|
selected: () => open,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<Popover
|
<Popover
|
||||||
role="submenu"
|
role="submenu"
|
||||||
@ -125,6 +130,13 @@ export const ToolbarSubmenu = (props: {
|
|||||||
}}
|
}}
|
||||||
elevation={props.elevation}
|
elevation={props.elevation}
|
||||||
>
|
>
|
||||||
|
{props.configuration.useClickToClose && (
|
||||||
|
<Box alignItems={'end'}>
|
||||||
|
<IconButton onClick={() => setOpen(false)} aria-label={'Close'}>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
<div style={{ display: 'flex' }} onScroll={(e) => e.stopPropagation()}>
|
<div style={{ display: 'flex' }} onScroll={(e) => e.stopPropagation()}>
|
||||||
{props.configuration.options?.map((o, i) => {
|
{props.configuration.options?.map((o, i) => {
|
||||||
if (o?.visible === false) {
|
if (o?.visible === false) {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @jest-environment jsdom
|
* @jest-environment jsdom
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render, fireEvent, waitFor, screen } from '@testing-library/react';
|
import { render, fireEvent, waitFor, screen, findByLabelText } from '@testing-library/react';
|
||||||
import ThreeDRotation from '@mui/icons-material/ThreeDRotation';
|
import ThreeDRotation from '@mui/icons-material/ThreeDRotation';
|
||||||
import Toolbar, {
|
import Toolbar, {
|
||||||
ToolbarButtonOption,
|
ToolbarButtonOption,
|
||||||
@ -80,6 +80,12 @@ const iconFunctionConfig: ActionConfig = {
|
|||||||
onClick: jest.fn(),
|
onClick: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const submenuOnClickConfig: ActionConfig = {
|
||||||
|
icon: <ThreeDRotation></ThreeDRotation>,
|
||||||
|
useClickToClose: true,
|
||||||
|
options: [config, null, config, null],
|
||||||
|
};
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
@ -192,6 +198,7 @@ describe('Editor Toolbar Submenu', () => {
|
|||||||
const item = screen.getByRole('menuitem');
|
const item = screen.getByRole('menuitem');
|
||||||
fireEvent.mouseOver(item);
|
fireEvent.mouseOver(item);
|
||||||
const clickeableDiv = await screen.findByTestId('custom-render-div');
|
const clickeableDiv = await screen.findByTestId('custom-render-div');
|
||||||
|
expect(screen.queryByRole('submenu')).toBeTruthy();
|
||||||
|
|
||||||
fireEvent.click(clickeableDiv);
|
fireEvent.click(clickeableDiv);
|
||||||
|
|
||||||
@ -206,6 +213,28 @@ describe('Editor Toolbar Submenu', () => {
|
|||||||
|
|
||||||
expect(screen.queryByRole('submenu')).toBeFalsy();
|
expect(screen.queryByRole('submenu')).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Given a useClickToOpen configuration when mouse is over, not shows a submenu ', async () => {
|
||||||
|
render(<ToolbarSubmenu configuration={submenuOnClickConfig}></ToolbarSubmenu>);
|
||||||
|
const item = screen.getByRole('menuitem');
|
||||||
|
|
||||||
|
fireEvent.mouseOver(item);
|
||||||
|
|
||||||
|
expect(screen.queryByRole('submenu')).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Given a useClickToOpen configuration when click, shows a submenu with close button', async () => {
|
||||||
|
render(<ToolbarSubmenu configuration={submenuOnClickConfig}></ToolbarSubmenu>);
|
||||||
|
const item = screen.getByRole('button');
|
||||||
|
|
||||||
|
fireEvent.click(item);
|
||||||
|
|
||||||
|
await screen.findByRole('submenu');
|
||||||
|
const closeButton = await screen.findByLabelText('Close');
|
||||||
|
|
||||||
|
fireEvent.click(closeButton);
|
||||||
|
expect(screen.queryByRole('submenu')).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('toolbar menu item', () => {
|
describe('toolbar menu item', () => {
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
"!@mui/material/test-utils/*"
|
"!@mui/material/test-utils/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"react/no-unknown-property": ["error", { "ignore": ["css"] }]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
context('Editor Page', () => {
|
context('Editor Page', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.visit('c/maps/11/edit');
|
cy.visit('/c/maps/11/edit');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('page loaded', () => {
|
it('page loaded', () => {
|
||||||
|
@ -7,3 +7,43 @@ context('Maps Page', () => {
|
|||||||
// cy.matchImageSnapshot('maps');
|
// cy.matchImageSnapshot('maps');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
context('iphone-5 resolution', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport('iphone-5');
|
||||||
|
cy.visit('/c/maps', {
|
||||||
|
onLoad: (win) => {
|
||||||
|
win.onerror = null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Displays mobile menu button', () => {
|
||||||
|
cy.get('#open-main-drawer').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Displays mobile menu on click', () => {
|
||||||
|
cy.get('.MuiDrawer-root').should('not.be.visible');
|
||||||
|
cy.get('#open-main-drawer').should('be.visible').click();
|
||||||
|
cy.get('.MuiDrawer-root').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Displays a card list', () => {
|
||||||
|
cy.get('.MuiCard-root').should('have.length', 3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('720p resolution', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.viewport(1280, 720);
|
||||||
|
cy.visit('/c/maps');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Displays mobile menu button', () => {
|
||||||
|
cy.get('#open-desktop-drawer').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Displays a table with maps', () => {
|
||||||
|
cy.get('.MuiTableBody-root').should('be.visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -263,6 +263,33 @@
|
|||||||
"info.title": {
|
"info.title": {
|
||||||
"defaultMessage": "Información"
|
"defaultMessage": "Información"
|
||||||
},
|
},
|
||||||
|
"label.add-button": {
|
||||||
|
"defaultMessage": "Agregar etiqueta"
|
||||||
|
},
|
||||||
|
"label.add-for": {
|
||||||
|
"defaultMessage": "Editando etiquetas para el mapa:"
|
||||||
|
},
|
||||||
|
"label.add-placeholder": {
|
||||||
|
"defaultMessage": "Título"
|
||||||
|
},
|
||||||
|
"label.change-color": {
|
||||||
|
"defaultMessage": "Cambiar el color"
|
||||||
|
},
|
||||||
|
"label.delete-description": {
|
||||||
|
"defaultMessage": "será borrado de todos los mapas a los que se encuentra asociado. Desea continuar?"
|
||||||
|
},
|
||||||
|
"label.delete-title": {
|
||||||
|
"defaultMessage": "Confirmación"
|
||||||
|
},
|
||||||
|
"label.description": {
|
||||||
|
"defaultMessage": "Usa las etiquetas para organizar tus mapas."
|
||||||
|
},
|
||||||
|
"label.maps-count": {
|
||||||
|
"defaultMessage": "{count} mapas"
|
||||||
|
},
|
||||||
|
"label.title": {
|
||||||
|
"defaultMessage": "Agregar etiqueta"
|
||||||
|
},
|
||||||
"language.change": {
|
"language.change": {
|
||||||
"defaultMessage": "Cambiar idioma"
|
"defaultMessage": "Cambiar idioma"
|
||||||
},
|
},
|
||||||
|
@ -49,7 +49,6 @@
|
|||||||
"@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.10.11",
|
"@mui/material": "^5.10.11",
|
||||||
"@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",
|
||||||
|
@ -11,21 +11,16 @@ import { QueryClient, QueryClientProvider } from 'react-query';
|
|||||||
import { theme } from './theme';
|
import { theme } from './theme';
|
||||||
import AppI18n, { Locales } from './classes/app-i18n';
|
import AppI18n, { Locales } from './classes/app-i18n';
|
||||||
import CssBaseline from '@mui/material/CssBaseline';
|
import CssBaseline from '@mui/material/CssBaseline';
|
||||||
import { ThemeProvider, Theme, StyledEngineProvider } from '@mui/material/styles';
|
import { ThemeProvider as MuiThemeProvider, StyledEngineProvider } from '@mui/material/styles';
|
||||||
import ReactGA from 'react-ga4';
|
import ReactGA from 'react-ga4';
|
||||||
import AppConfig from './classes/app-config';
|
import AppConfig from './classes/app-config';
|
||||||
import withSessionExpirationHandling from './components/HOCs/withSessionExpirationHandling';
|
|
||||||
import RegistrationSuccessPage from './components/registration-success-page';
|
import RegistrationSuccessPage from './components/registration-success-page';
|
||||||
|
import { ThemeProvider } from '@emotion/react';
|
||||||
import RegistrationCallbackPage from './components/registration-callback';
|
import RegistrationCallbackPage from './components/registration-callback';
|
||||||
|
|
||||||
const EditorPage = React.lazy(() => import('./components/editor-page'));
|
const EditorPage = React.lazy(() => import('./components/editor-page'));
|
||||||
const MapsPage = React.lazy(() => import('./components/maps-page'));
|
const MapsPage = React.lazy(() => import('./components/maps-page'));
|
||||||
|
|
||||||
declare module '@mui/styles/defaultTheme' {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
||||||
interface DefaultTheme extends Theme {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Google Analytics Initialization.
|
// Google Analytics Initialization.
|
||||||
ReactGA.initialize([
|
ReactGA.initialize([
|
||||||
{
|
{
|
||||||
@ -53,7 +48,6 @@ function Redirect({ to }) {
|
|||||||
|
|
||||||
const App = (): ReactElement => {
|
const App = (): ReactElement => {
|
||||||
const locale = AppI18n.getDefaultLocale();
|
const locale = AppI18n.getDefaultLocale();
|
||||||
const EnhacedEditorPage = withSessionExpirationHandling(EditorPage);
|
|
||||||
|
|
||||||
return locale.message ? (
|
return locale.message ? (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
@ -64,6 +58,7 @@ const App = (): ReactElement => {
|
|||||||
messages={locale.message as Record<string, string>}
|
messages={locale.message as Record<string, string>}
|
||||||
>
|
>
|
||||||
<StyledEngineProvider injectFirst>
|
<StyledEngineProvider injectFirst>
|
||||||
|
<MuiThemeProvider theme={theme}>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Router>
|
<Router>
|
||||||
@ -94,12 +89,36 @@ const App = (): ReactElement => {
|
|||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/c/maps/:id/edit"
|
path="/c/maps/:id/edit"
|
||||||
element={<EnhacedEditorPage isTryMode={false} />}
|
element={
|
||||||
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<div>
|
||||||
|
<FormattedMessage id="dialog.loading" defaultMessage="Loading ..." />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<EditorPage isTryMode={false} />
|
||||||
|
</Suspense>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/c/maps/:id/try"
|
||||||
|
element={
|
||||||
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<div>
|
||||||
|
<FormattedMessage id="dialog.loading" defaultMessage="Loading ..." />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<EditorPage isTryMode={true} />
|
||||||
|
</Suspense>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Route path="/c/maps/:id/try" element={<EnhacedEditorPage isTryMode={true} />} />
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
</MuiThemeProvider>
|
||||||
</StyledEngineProvider>
|
</StyledEngineProvider>
|
||||||
</IntlProvider>
|
</IntlProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
@ -386,7 +386,7 @@
|
|||||||
"forgot.oauth.message": [
|
"forgot.oauth.message": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
"value": "You dont need password, please login using Google"
|
"value": "You dont need password, please login using Google."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"forgot.page-title": [
|
"forgot.page-title": [
|
||||||
@ -631,6 +631,12 @@
|
|||||||
"value": "Log into your account"
|
"value": "Log into your account"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"login.division": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "or"
|
||||||
|
}
|
||||||
|
],
|
||||||
"login.email": [
|
"login.email": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
|
@ -555,6 +555,64 @@
|
|||||||
"value": "Información"
|
"value": "Información"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"label.add-button": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Agregar etiqueta"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label.add-for": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Editando etiquetas para el mapa:"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label.add-placeholder": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Título"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label.change-color": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Cambiar el color"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label.delete-description": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "será borrado de todos los mapas a los que se encuentra asociado. Desea continuar?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label.delete-title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Confirmación"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label.description": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Usa las etiquetas para organizar tus mapas."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label.maps-count": [
|
||||||
|
{
|
||||||
|
"type": 1,
|
||||||
|
"value": "count"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": " mapas"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"label.title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Agregar etiqueta"
|
||||||
|
}
|
||||||
|
],
|
||||||
"language.change": [
|
"language.change": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
|
18
packages/webapp/src/components/HOCs/withEmotionStyles.tsx
Normal file
18
packages/webapp/src/components/HOCs/withEmotionStyles.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
import React, { ComponentType } from 'react';
|
||||||
|
|
||||||
|
function withEmotionStyles<T>(css) {
|
||||||
|
return (Component: ComponentType<T>) => {
|
||||||
|
const WithEmotionStyles = (hocProps): React.ReactElement => {
|
||||||
|
return <Component {...hocProps} css={{ ...hocProps.paperCss, ...css }} />;
|
||||||
|
};
|
||||||
|
WithEmotionStyles.displayName = `withEmotionStyles(${getDisplayName(Component)})`;
|
||||||
|
return WithEmotionStyles;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDisplayName(WrappedComponent) {
|
||||||
|
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withEmotionStyles;
|
@ -1,42 +1,5 @@
|
|||||||
import AppConfig from '../../classes/app-config';
|
import AppConfig from '../../classes/app-config';
|
||||||
import exampleMap from '../../classes/client/mock-client/example-map.wxml';
|
import { LocalStorageManager, Mindmap, XMLSerializerFactory } from '@wisemapping/editor';
|
||||||
import {
|
|
||||||
PersistenceManager,
|
|
||||||
RESTPersistenceManager,
|
|
||||||
LocalStorageManager,
|
|
||||||
Mindmap,
|
|
||||||
MockPersistenceManager,
|
|
||||||
XMLSerializerFactory,
|
|
||||||
} from '@wisemapping/editor';
|
|
||||||
|
|
||||||
export const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
|
|
||||||
let persistenceManager: PersistenceManager;
|
|
||||||
if (AppConfig.isRestClient()) {
|
|
||||||
if (mode === 'edition-owner' || mode === 'edition-editor') {
|
|
||||||
persistenceManager = new RESTPersistenceManager({
|
|
||||||
documentUrl: '/c/restful/maps/{id}/document',
|
|
||||||
revertUrl: '/c/restful/maps/{id}/history/latest',
|
|
||||||
lockUrl: '/c/restful/maps/{id}/lock',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
persistenceManager = new LocalStorageManager(
|
|
||||||
`/c/restful/maps/{id}/${
|
|
||||||
globalThis.historyId ? `${globalThis.historyId}/` : ''
|
|
||||||
}document/xml${mode === 'showcase' ? '-pub' : ''}`,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
persistenceManager.addErrorHandler((error) => {
|
|
||||||
if (error.errorType === 'session-expired') {
|
|
||||||
// TODO: this line was in RestPersistenceClient, do something similar here
|
|
||||||
//client.sessionExpired();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
persistenceManager = new MockPersistenceManager(exampleMap);
|
|
||||||
}
|
|
||||||
return persistenceManager;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const fetchMindmap = async (mapId: number): Promise<Mindmap> => {
|
export const fetchMindmap = async (mapId: number): Promise<Mindmap> => {
|
||||||
let mindmap: Mindmap;
|
let mindmap: Mindmap;
|
||||||
|
@ -16,10 +16,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import ActionDispatcher from '../maps-page/action-dispatcher';
|
|
||||||
import { ActionType } from '../maps-page/action-chooser';
|
|
||||||
import Editor from '@wisemapping/editor';
|
import Editor from '@wisemapping/editor';
|
||||||
import { EditorRenderMode, PersistenceManager } from '@wisemapping/editor';
|
import {
|
||||||
|
EditorRenderMode,
|
||||||
|
PersistenceManager,
|
||||||
|
RESTPersistenceManager,
|
||||||
|
LocalStorageManager,
|
||||||
|
MockPersistenceManager,
|
||||||
|
} from '@wisemapping/editor';
|
||||||
import { IntlProvider } from 'react-intl';
|
import { IntlProvider } from 'react-intl';
|
||||||
import AppI18n, { Locales } from '../../classes/app-i18n';
|
import AppI18n, { Locales } from '../../classes/app-i18n';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
@ -27,17 +31,66 @@ import { hotkeysEnabled } from '../../redux/editorSlice';
|
|||||||
import ReactGA from 'react-ga4';
|
import ReactGA from 'react-ga4';
|
||||||
import { useFetchAccount, useFetchMapById } from '../../redux/clientSlice';
|
import { useFetchAccount, useFetchMapById } from '../../redux/clientSlice';
|
||||||
import EditorOptionsBuilder from './EditorOptionsBuilder';
|
import EditorOptionsBuilder from './EditorOptionsBuilder';
|
||||||
import { buildPersistenceManagerForEditor } from './PersistenceManagerUtils';
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import AccountMenu from '../maps-page/account-menu';
|
|
||||||
import MapInfoImpl from '../../classes/editor-map-info';
|
import MapInfoImpl from '../../classes/editor-map-info';
|
||||||
import { MapInfo } from '@wisemapping/editor';
|
import { MapInfo } from '@wisemapping/editor';
|
||||||
import { activeInstance } from '../../redux/clientSlice';
|
import { activeInstance } from '../../redux/clientSlice';
|
||||||
import Client from '../../classes/client';
|
import Client from '../../classes/client';
|
||||||
|
import AppConfig from '../../classes/app-config';
|
||||||
|
import exampleMap from '../../classes/client/mock-client/example-map.wxml';
|
||||||
|
import withSessionExpirationHandling from '../HOCs/withSessionExpirationHandling';
|
||||||
|
|
||||||
|
const buildPersistenceManagerForEditor = (mode: string): PersistenceManager => {
|
||||||
|
let persistenceManager: PersistenceManager;
|
||||||
|
if (AppConfig.isRestClient()) {
|
||||||
|
if (mode === 'edition-owner' || mode === 'edition-editor') {
|
||||||
|
persistenceManager = new RESTPersistenceManager({
|
||||||
|
documentUrl: '/c/restful/maps/{id}/document',
|
||||||
|
revertUrl: '/c/restful/maps/{id}/history/latest',
|
||||||
|
lockUrl: '/c/restful/maps/{id}/lock',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
persistenceManager = new LocalStorageManager(
|
||||||
|
`/c/restful/maps/{id}/${
|
||||||
|
globalThis.historyId ? `${globalThis.historyId}/` : ''
|
||||||
|
}document/xml${mode === 'showcase' ? '-pub' : ''}`,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
persistenceManager.addErrorHandler((error) => {
|
||||||
|
if (error.errorType === 'session-expired') {
|
||||||
|
// TODO: this line was in RestPersistenceClient, do something similar here
|
||||||
|
//client.sessionExpired();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
persistenceManager = new MockPersistenceManager(exampleMap);
|
||||||
|
}
|
||||||
|
return persistenceManager;
|
||||||
|
};
|
||||||
|
|
||||||
export type EditorPropsType = {
|
export type EditorPropsType = {
|
||||||
isTryMode: boolean;
|
isTryMode: boolean;
|
||||||
};
|
};
|
||||||
|
type ActionType =
|
||||||
|
| 'open'
|
||||||
|
| 'share'
|
||||||
|
| 'import'
|
||||||
|
| 'delete'
|
||||||
|
| 'info'
|
||||||
|
| 'create'
|
||||||
|
| 'duplicate'
|
||||||
|
| 'export'
|
||||||
|
| 'label'
|
||||||
|
| 'rename'
|
||||||
|
| 'print'
|
||||||
|
| 'info'
|
||||||
|
| 'publish'
|
||||||
|
| 'history'
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
const ActionDispatcher = React.lazy(() => import('../maps-page/action-dispatcher'));
|
||||||
|
const AccountMenu = React.lazy(() => import('../maps-page/account-menu'));
|
||||||
|
|
||||||
const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
||||||
const [activeDialog, setActiveDialog] = React.useState<ActionType | null>(null);
|
const [activeDialog, setActiveDialog] = React.useState<ActionType | null>(null);
|
||||||
@ -144,4 +197,4 @@ const EditorPage = ({ isTryMode }: EditorPropsType): React.ReactElement => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default EditorPage;
|
export default withSessionExpirationHandling(EditorPage);
|
||||||
|
@ -69,7 +69,7 @@ const ForgotPassword = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormContainer>
|
<FormContainer maxWidth="xs">
|
||||||
<Typography variant="h4" component="h1">
|
<Typography variant="h4" component="h1">
|
||||||
<FormattedMessage id="forgot.title" defaultMessage="Reset your password" />
|
<FormattedMessage id="forgot.title" defaultMessage="Reset your password" />
|
||||||
</Typography>
|
</Typography>
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import withStyles from '@mui/styles/withStyles';
|
import withEmotionStyles from '../../HOCs/withEmotionStyles';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
|
|
||||||
export const StyledAlert = withStyles({
|
export const StyledAlert = withEmotionStyles({
|
||||||
root: {
|
|
||||||
padding: '10px 15px',
|
padding: '10px 15px',
|
||||||
margin: '5px 0px ',
|
margin: '5px 0px ',
|
||||||
},
|
|
||||||
})(Alert);
|
})(Alert);
|
||||||
|
|
||||||
export default StyledAlert;
|
export default StyledAlert;
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
|
import withEmotionStyles from '../../HOCs/withEmotionStyles';
|
||||||
import Container from '@mui/material/Container';
|
import Container from '@mui/material/Container';
|
||||||
import withStyles from '@mui/styles/withStyles';
|
|
||||||
|
|
||||||
const FormContainer = withStyles({
|
const FormContainer = withEmotionStyles({
|
||||||
root: {
|
|
||||||
padding: '20px 10px 0px 20px',
|
padding: '20px 10px 0px 20px',
|
||||||
maxWidth: '380px',
|
maxWidth: '380px !important',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
|
||||||
})(Container);
|
})(Container);
|
||||||
|
|
||||||
export default FormContainer;
|
export default FormContainer;
|
||||||
|
@ -52,7 +52,7 @@ const ActionChooser = (props: ActionProps): React.ReactElement => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const role = mapId ? useFetchMapById(mapId)?.map?.role : undefined;
|
const role = mapId !== undefined ? useFetchMapById(mapId)?.map?.role : undefined;
|
||||||
return (
|
return (
|
||||||
<Menu
|
<Menu
|
||||||
anchorEl={anchor}
|
anchorEl={anchor}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import withStyles from '@mui/styles/withStyles';
|
import withEmotionStyles from '../../HOCs/withEmotionStyles';
|
||||||
|
|
||||||
export const StyledMenuItem = withStyles({
|
export const StyledMenuItem = withEmotionStyles({
|
||||||
root: {
|
root: {
|
||||||
width: '300px',
|
width: '300px',
|
||||||
},
|
},
|
||||||
|
@ -5,9 +5,9 @@ import { StyledDialog, StyledDialogActions, StyledDialogContent, StyledDialogTit
|
|||||||
import GlobalError from '../../../form/global-error';
|
import GlobalError from '../../../form/global-error';
|
||||||
import DialogContentText from '@mui/material/DialogContentText';
|
import DialogContentText from '@mui/material/DialogContentText';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import { PaperProps } from '@mui/material/Paper';
|
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { disableHotkeys, enableHotkeys } from '../../../../redux/editorSlice';
|
import { disableHotkeys, enableHotkeys } from '../../../../redux/editorSlice';
|
||||||
|
import { CSSObject } from '@emotion/react';
|
||||||
|
|
||||||
export type DialogProps = {
|
export type DialogProps = {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@ -21,7 +21,7 @@ export type DialogProps = {
|
|||||||
submitButton?: string;
|
submitButton?: string;
|
||||||
actionUrl?: string;
|
actionUrl?: string;
|
||||||
maxWidth?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false;
|
maxWidth?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false;
|
||||||
PaperProps?: Partial<PaperProps>;
|
paperCss?: CSSObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BaseDialog = (props: DialogProps): React.ReactElement => {
|
const BaseDialog = (props: DialogProps): React.ReactElement => {
|
||||||
@ -32,7 +32,7 @@ const BaseDialog = (props: DialogProps): React.ReactElement => {
|
|||||||
dispatch(enableHotkeys());
|
dispatch(enableHotkeys());
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
const { onClose, onSubmit, maxWidth = 'sm', PaperProps } = props;
|
const { onClose, onSubmit, maxWidth = 'sm', paperCss } = props;
|
||||||
|
|
||||||
const handleOnSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
const handleOnSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -50,7 +50,7 @@ const BaseDialog = (props: DialogProps): React.ReactElement => {
|
|||||||
open={true}
|
open={true}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
maxWidth={maxWidth}
|
maxWidth={maxWidth}
|
||||||
PaperProps={PaperProps}
|
paperCss={{ '& .MuiPaper-root.MuiDialog-paper': paperCss }}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
>
|
>
|
||||||
<form autoComplete="off" onSubmit={handleOnSubmit}>
|
<form autoComplete="off" onSubmit={handleOnSubmit}>
|
||||||
|
@ -2,28 +2,20 @@ import Dialog from '@mui/material/Dialog';
|
|||||||
import DialogActions from '@mui/material/DialogActions';
|
import DialogActions from '@mui/material/DialogActions';
|
||||||
import DialogContent from '@mui/material/DialogContent';
|
import DialogContent from '@mui/material/DialogContent';
|
||||||
import DialogTitle from '@mui/material/DialogTitle';
|
import DialogTitle from '@mui/material/DialogTitle';
|
||||||
import withStyles from '@mui/styles/withStyles';
|
import withEmotionStyles from '../../../HOCs/withEmotionStyles';
|
||||||
|
|
||||||
export const StyledDialogContent = withStyles({
|
export const StyledDialogContent = withEmotionStyles({
|
||||||
root: {
|
|
||||||
padding: '0px 39px',
|
padding: '0px 39px',
|
||||||
},
|
|
||||||
})(DialogContent);
|
})(DialogContent);
|
||||||
|
|
||||||
export const StyledDialogTitle = withStyles({
|
export const StyledDialogTitle = withEmotionStyles({
|
||||||
root: {
|
|
||||||
padding: '39px 39px 10px 39px',
|
padding: '39px 39px 10px 39px',
|
||||||
},
|
|
||||||
})(DialogTitle);
|
})(DialogTitle);
|
||||||
|
|
||||||
export const StyledDialogActions = withStyles({
|
export const StyledDialogActions = withEmotionStyles({
|
||||||
root: {
|
|
||||||
padding: '39px 39px 39px 39px',
|
padding: '39px 39px 39px 39px',
|
||||||
},
|
|
||||||
})(DialogActions);
|
})(DialogActions);
|
||||||
|
|
||||||
export const StyledDialog = withStyles({
|
export const StyledDialog = withEmotionStyles({
|
||||||
root: {
|
|
||||||
borderRadius: '9px',
|
borderRadius: '9px',
|
||||||
},
|
|
||||||
})(Dialog);
|
})(Dialog);
|
||||||
|
@ -185,7 +185,7 @@ const ExportDialog = ({
|
|||||||
<RadioGroup name="export" value={exportGroup} onChange={handleOnGroupChange}>
|
<RadioGroup name="export" value={exportGroup} onChange={handleOnGroupChange}>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
className={classes.label}
|
css={classes.label}
|
||||||
value="image"
|
value="image"
|
||||||
disabled={!enableImgExport}
|
disabled={!enableImgExport}
|
||||||
control={<Radio color="primary" />}
|
control={<Radio color="primary" />}
|
||||||
@ -203,20 +203,20 @@ const ExportDialog = ({
|
|||||||
onChange={handleOnExportFormatChange}
|
onChange={handleOnExportFormatChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={exportFormat}
|
value={exportFormat}
|
||||||
className={classes.select}
|
css={classes.select}
|
||||||
>
|
>
|
||||||
<MenuItem value="svg" className={classes.menu}>
|
<MenuItem value="svg" css={classes.menu}>
|
||||||
Scalable Vector Graphics (SVG)
|
Scalable Vector Graphics (SVG)
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value="png" className={classes.menu}>
|
<MenuItem value="png" css={classes.menu}>
|
||||||
Portable Network Graphics (PNG)
|
Portable Network Graphics (PNG)
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem value="jpg" className={classes.menu}>
|
<MenuItem value="jpg" css={classes.menu}>
|
||||||
JPEG Image (JPEG)
|
JPEG Image (JPEG)
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
className={classes.select}
|
css={classes.select}
|
||||||
control={<Checkbox checked={zoomToFit} onChange={handleOnZoomToFit} />}
|
control={<Checkbox checked={zoomToFit} onChange={handleOnZoomToFit} />}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
id: 'export.img-center',
|
id: 'export.img-center',
|
||||||
@ -229,7 +229,7 @@ const ExportDialog = ({
|
|||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
className={classes.label}
|
css={classes.label}
|
||||||
value="document"
|
value="document"
|
||||||
control={<Radio color="primary" />}
|
control={<Radio color="primary" />}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
@ -244,12 +244,12 @@ const ExportDialog = ({
|
|||||||
onChange={handleOnExportFormatChange}
|
onChange={handleOnExportFormatChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
value={exportFormat}
|
value={exportFormat}
|
||||||
className={classes.select}
|
css={classes.select}
|
||||||
>
|
>
|
||||||
<MenuItem className={classes.select} value="txt">
|
<MenuItem css={classes.select} value="txt">
|
||||||
Plain Text File (TXT)
|
Plain Text File (TXT)
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem className={classes.select} value="md">
|
<MenuItem css={classes.select} value="md">
|
||||||
Markdown (MD)
|
Markdown (MD)
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{/* <MenuItem className={classes.select} value="xls">
|
{/* <MenuItem className={classes.select} value="xls">
|
||||||
@ -261,7 +261,7 @@ const ExportDialog = ({
|
|||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
className={classes.label}
|
css={classes.label}
|
||||||
value="mindmap-tool"
|
value="mindmap-tool"
|
||||||
control={<Radio color="primary" />}
|
control={<Radio color="primary" />}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
@ -275,13 +275,13 @@ const ExportDialog = ({
|
|||||||
<Select
|
<Select
|
||||||
onChange={handleOnExportFormatChange}
|
onChange={handleOnExportFormatChange}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
className={classes.select}
|
css={classes.select}
|
||||||
value={exportFormat}
|
value={exportFormat}
|
||||||
>
|
>
|
||||||
<MenuItem className={classes.select} value="wxml">
|
<MenuItem css={classes.select} value="wxml">
|
||||||
WiseMapping (WXML)
|
WiseMapping (WXML)
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem className={classes.select} value="mm">
|
<MenuItem css={classes.select} value="mm">
|
||||||
Freemind 1.0.1 (MM)
|
Freemind 1.0.1 (MM)
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{/* <MenuItem className={classes.select} value="mmap">
|
{/* <MenuItem className={classes.select} value="mmap">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import createStyles from '@mui/styles/createStyles';
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
import useClasses from '../../../../theme/useStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = () =>
|
||||||
createStyles({
|
useClasses({
|
||||||
select: {
|
select: {
|
||||||
height: '40px',
|
height: '40px',
|
||||||
borderRadius: '9px',
|
borderRadius: '9px',
|
||||||
@ -16,5 +16,4 @@ export const useStyles = makeStyles(() =>
|
|||||||
label: {
|
label: {
|
||||||
margin: '5px 0px',
|
margin: '5px 0px',
|
||||||
},
|
},
|
||||||
}),
|
});
|
||||||
);
|
|
||||||
|
@ -50,9 +50,11 @@ const ActionDispatcher = ({
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case 'open':
|
case 'open':
|
||||||
window.location.href = `/c/maps/${mapsId}/edit`;
|
window.location.href = `/c/maps/${mapsId}/edit`;
|
||||||
|
handleOnClose(true);
|
||||||
break;
|
break;
|
||||||
case 'print':
|
case 'print':
|
||||||
window.open(`/c/maps/${mapsId}/print`, 'print');
|
window.open(`/c/maps/${mapsId}/print`, 'print');
|
||||||
|
handleOnClose(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement =
|
|||||||
>
|
>
|
||||||
<Paper style={{ maxHeight: 200, overflowY: 'scroll' }} variant="outlined" elevation={0}>
|
<Paper style={{ maxHeight: 200, overflowY: 'scroll' }} variant="outlined" elevation={0}>
|
||||||
<Card variant="outlined">
|
<Card variant="outlined">
|
||||||
<List dense={true}>
|
<List dense={true} css={classes.list}>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="body1" style={{ fontWeight: 'bold' }}>
|
<Typography variant="body1" style={{ fontWeight: 'bold' }}>
|
||||||
<FormattedMessage id="info.basic-info" defaultMessage="Basic Info" />
|
<FormattedMessage id="info.basic-info" defaultMessage="Basic Info" />
|
||||||
@ -50,42 +50,42 @@ const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement =
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="caption" color="textPrimary" className={classes.textDesc}>
|
<Typography variant="caption" color="textPrimary" css={classes.textDesc}>
|
||||||
<FormattedMessage id="info.name" defaultMessage="Name" />:
|
<FormattedMessage id="info.name" defaultMessage="Name" />:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">{map?.title}</Typography>
|
<Typography variant="body2">{map?.title}</Typography>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="caption" color="textPrimary" className={classes.textDesc}>
|
<Typography variant="caption" color="textPrimary" css={classes.textDesc}>
|
||||||
<FormattedMessage id="info.description" defaultMessage="Description" />:
|
<FormattedMessage id="info.description" defaultMessage="Description" />:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">{map?.description}</Typography>
|
<Typography variant="body2">{map?.description}</Typography>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="caption" color="textPrimary" className={classes.textDesc}>
|
<Typography variant="caption" color="textPrimary" css={classes.textDesc}>
|
||||||
<FormattedMessage id="info.creator" defaultMessage="Creator" />:
|
<FormattedMessage id="info.creator" defaultMessage="Creator" />:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">{map?.createdBy}</Typography>
|
<Typography variant="body2">{map?.createdBy}</Typography>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="caption" color="textPrimary" className={classes.textDesc}>
|
<Typography variant="caption" color="textPrimary" css={classes.textDesc}>
|
||||||
<FormattedMessage id="info.creation-time" defaultMessage="Creation Date" />:
|
<FormattedMessage id="info.creation-time" defaultMessage="Creation Date" />:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">{dayjs(map?.creationTime).format('LLL')}</Typography>
|
<Typography variant="body2">{dayjs(map?.creationTime).format('LLL')}</Typography>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="caption" color="textPrimary" className={classes.textDesc}>
|
<Typography variant="caption" color="textPrimary" css={classes.textDesc}>
|
||||||
<FormattedMessage id="info.modified-tny" defaultMessage="Last Modified By" />:
|
<FormattedMessage id="info.modified-tny" defaultMessage="Last Modified By" />:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">{map?.lastModificationBy}</Typography>
|
<Typography variant="body2">{map?.lastModificationBy}</Typography>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="caption" color="textPrimary" className={classes.textDesc}>
|
<Typography variant="caption" color="textPrimary" css={classes.textDesc}>
|
||||||
<FormattedMessage id="info.modified-time" defaultMessage="Last Modified Date" />:
|
<FormattedMessage id="info.modified-time" defaultMessage="Last Modified Date" />:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
@ -94,7 +94,7 @@ const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement =
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
|
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="caption" color="textPrimary" className={classes.textDesc}>
|
<Typography variant="caption" color="textPrimary" css={classes.textDesc}>
|
||||||
<FormattedMessage id="info.starred" defaultMessage="Starred" />:
|
<FormattedMessage id="info.starred" defaultMessage="Starred" />:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">{Boolean(map?.starred).toString()}</Typography>
|
<Typography variant="body2">{Boolean(map?.starred).toString()}</Typography>
|
||||||
@ -111,7 +111,7 @@ const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement =
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<Typography variant="caption" color="textPrimary" className={classes.textDesc}>
|
<Typography variant="caption" color="textPrimary" css={classes.textDesc}>
|
||||||
<FormattedMessage id="info.public-visibility" defaultMessage="Publicly Visible" />:
|
<FormattedMessage id="info.public-visibility" defaultMessage="Publicly Visible" />:
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">{Boolean(map?.isPublic).toString()}</Typography>
|
<Typography variant="body2">{Boolean(map?.isPublic).toString()}</Typography>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import createStyles from '@mui/styles/createStyles';
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
|
import useClasses from '../../../../theme/useStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = () =>
|
||||||
createStyles({
|
useClasses({
|
||||||
textarea: {
|
textarea: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '15px 15px',
|
padding: '15px 15px',
|
||||||
@ -11,5 +12,14 @@ export const useStyles = makeStyles(() =>
|
|||||||
textDesc: {
|
textDesc: {
|
||||||
width: '150px',
|
width: '150px',
|
||||||
},
|
},
|
||||||
}),
|
list: {
|
||||||
);
|
'& li': {
|
||||||
|
[useTheme().breakpoints.down('sm')]: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
|
'& p': {
|
||||||
|
marginLeft: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -11,6 +11,7 @@ import Client, { ErrorInfo, Label, MapInfo } from '../../../../classes/client';
|
|||||||
import { LabelSelector } from '../../maps-list/label-selector';
|
import { LabelSelector } from '../../maps-list/label-selector';
|
||||||
import { activeInstance } from '../../../../redux/clientSlice';
|
import { activeInstance } from '../../../../redux/clientSlice';
|
||||||
import { ChangeLabelMutationFunctionParam, getChangeLabelMutationFunction } from '../../maps-list';
|
import { ChangeLabelMutationFunctionParam, getChangeLabelMutationFunction } from '../../maps-list';
|
||||||
|
import { Interpolation, Theme } from '@emotion/react';
|
||||||
|
|
||||||
const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement => {
|
const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@ -62,11 +63,11 @@ const LabelDialog = ({ mapsId, onClose }: MultiDialogProps): React.ReactElement
|
|||||||
id: 'label.description',
|
id: 'label.description',
|
||||||
defaultMessage: 'Use labels to organize your maps.',
|
defaultMessage: 'Use labels to organize your maps.',
|
||||||
})}
|
})}
|
||||||
PaperProps={{ classes: { root: classes.paper } }}
|
paperCss={classes.paper}
|
||||||
error={error}
|
error={error}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
<Typography variant="body2" marginTop="10px">
|
<Typography variant="body2" marginTop="10px" css={classes.title as Interpolation<Theme>}>
|
||||||
<FormattedMessage id="label.add-for" defaultMessage="Editing labels for " />
|
<FormattedMessage id="label.add-for" defaultMessage="Editing labels for " />
|
||||||
{maps.length > 1 ? (
|
{maps.length > 1 ? (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import createStyles from '@mui/styles/createStyles';
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
import useClasses from '../../../../theme/useStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = () =>
|
||||||
createStyles({
|
useClasses({
|
||||||
paper: {
|
paper: {
|
||||||
maxWidth: '420px',
|
maxWidth: '420px',
|
||||||
},
|
},
|
||||||
}),
|
title: {
|
||||||
);
|
maxWidth: '100%',
|
||||||
|
wordBreak: 'break-all',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -122,7 +122,7 @@ const PublishDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElemen
|
|||||||
/>
|
/>
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextareaAutosize
|
<TextareaAutosize
|
||||||
className={classes.textarea}
|
css={classes.textarea}
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
maxRows={6}
|
maxRows={6}
|
||||||
@ -137,7 +137,7 @@ const PublishDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElemen
|
|||||||
/>
|
/>
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextareaAutosize
|
<TextareaAutosize
|
||||||
className={classes.textarea}
|
css={classes.textarea}
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
maxRows={1}
|
maxRows={1}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
import createStyles from '@mui/styles/createStyles';
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
import useClasses from '../../../../theme/useStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = () =>
|
||||||
createStyles({
|
useClasses({
|
||||||
textarea: {
|
textarea: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: '15px 15px',
|
padding: '15px 15px',
|
||||||
marging: '0px 10px',
|
marging: '0px 10px',
|
||||||
},
|
},
|
||||||
}),
|
});
|
||||||
);
|
|
||||||
|
@ -24,6 +24,7 @@ import Typography from '@mui/material/Typography';
|
|||||||
import { useStyles } from './style';
|
import { useStyles } from './style';
|
||||||
import RoleIcon from '../../role-icon';
|
import RoleIcon from '../../role-icon';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
|
import { Interpolation, Theme } from '@emotion/react';
|
||||||
|
|
||||||
type ShareModel = {
|
type ShareModel = {
|
||||||
emails: string;
|
emails: string;
|
||||||
@ -138,15 +139,14 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
defaultMessage:
|
defaultMessage:
|
||||||
'Invite people to collaborate with you in the creation of your mindmap. They will be notified by email. ',
|
'Invite people to collaborate with you in the creation of your mindmap. They will be notified by email. ',
|
||||||
})}
|
})}
|
||||||
PaperProps={{ classes: { root: classes.paper } }}
|
paperCss={classes.paper}
|
||||||
error={error}
|
error={error}
|
||||||
>
|
>
|
||||||
<div className={classes.actionContainer}>
|
<div css={classes.actionContainer as Interpolation<Theme>}>
|
||||||
<TextField
|
<TextField
|
||||||
id="emails"
|
id="emails"
|
||||||
name="emails"
|
name="emails"
|
||||||
required={true}
|
required={true}
|
||||||
style={{ width: '300px' }}
|
|
||||||
size="small"
|
size="small"
|
||||||
type="email"
|
type="email"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@ -154,6 +154,7 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
label="Emails"
|
label="Emails"
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
value={model.emails}
|
value={model.emails}
|
||||||
|
css={[classes.fullWidthInMobile, classes.email]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
@ -161,7 +162,7 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
value={model.role}
|
value={model.role}
|
||||||
name="role"
|
name="role"
|
||||||
style={{ margin: '0px 10px' }}
|
css={[classes.fullWidthInMobile, classes.role]}
|
||||||
>
|
>
|
||||||
<MenuItem value="editor">
|
<MenuItem value="editor">
|
||||||
<FormattedMessage id="share.can-edit" defaultMessage="Can edit" />
|
<FormattedMessage id="share.can-edit" defaultMessage="Can edit" />
|
||||||
@ -202,7 +203,7 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
multiline
|
multiline
|
||||||
rows={3}
|
rows={3}
|
||||||
maxRows={3}
|
maxRows={3}
|
||||||
className={classes.textArea}
|
css={classes.textArea}
|
||||||
variant="filled"
|
variant="filled"
|
||||||
name="message"
|
name="message"
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
@ -216,13 +217,17 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!isLoading && (
|
{!isLoading && (
|
||||||
<Paper elevation={1} className={classes.listPaper} variant="outlined">
|
<Paper elevation={1} css={classes.listPaper as Interpolation<Theme>} variant="outlined">
|
||||||
<List>
|
<List>
|
||||||
{permissions &&
|
{permissions &&
|
||||||
permissions.map((permission) => {
|
permissions.map((permission) => {
|
||||||
return (
|
return (
|
||||||
<ListItem key={permission.email} role={undefined} dense button>
|
<ListItem key={permission.email} role={undefined} dense button>
|
||||||
<ListItemText id={permission.email} primary={formatName(permission)} />
|
<ListItemText
|
||||||
|
css={classes.listItemText as Interpolation<Theme>}
|
||||||
|
id={permission.email}
|
||||||
|
primary={formatName(permission)}
|
||||||
|
/>
|
||||||
|
|
||||||
<RoleIcon role={permission.role} />
|
<RoleIcon role={permission.role} />
|
||||||
<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
|
@ -1,19 +1,38 @@
|
|||||||
import createStyles from '@mui/styles/createStyles';
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
|
import useClasses from '../../../../theme/useStyles';
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = () =>
|
||||||
createStyles({
|
useClasses({
|
||||||
actionContainer: {
|
actionContainer: {
|
||||||
padding: '10px 0px',
|
padding: '10px 0px',
|
||||||
border: '1px solid rgba(0, 0, 0, 0.12)',
|
border: '1px solid rgba(0, 0, 0, 0.12)',
|
||||||
borderRadius: '8px 8px 0px 0px',
|
borderRadius: '8px 8px 0px 0px',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
|
fullWidthInMobile: {
|
||||||
|
[useTheme().breakpoints.down('sm')]: {
|
||||||
|
minWidth: '99%',
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
[useTheme().breakpoints.up('sm')]: {
|
||||||
|
width: '300px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
role: {
|
||||||
|
[useTheme().breakpoints.up('sm')]: {
|
||||||
|
margin: '0px 10px',
|
||||||
|
},
|
||||||
|
},
|
||||||
textArea: {
|
textArea: {
|
||||||
|
[useTheme().breakpoints.up('sm')]: {
|
||||||
width: '730px',
|
width: '730px',
|
||||||
margin: '5px 0px',
|
margin: '5px 0px',
|
||||||
padding: '10px',
|
padding: '10px',
|
||||||
},
|
},
|
||||||
|
},
|
||||||
listPaper: {
|
listPaper: {
|
||||||
maxHeight: 200,
|
maxHeight: 200,
|
||||||
overflowY: 'scroll',
|
overflowY: 'scroll',
|
||||||
@ -21,6 +40,16 @@ export const useStyles = makeStyles(() =>
|
|||||||
paper: {
|
paper: {
|
||||||
width: '850px',
|
width: '850px',
|
||||||
minWidth: '850px',
|
minWidth: '850px',
|
||||||
|
[useTheme().breakpoints.down('sm')]: {
|
||||||
|
minWidth: '100%',
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
);
|
listItemText: {
|
||||||
|
overflow: 'hidden',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
'& span': {
|
||||||
|
display: 'inline',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { ErrorInfo, ReactElement, useEffect } from 'react';
|
import React, { ErrorInfo, ReactElement, useEffect } from 'react';
|
||||||
import clsx from 'clsx';
|
|
||||||
import Drawer from '@mui/material/Drawer';
|
import Drawer from '@mui/material/Drawer';
|
||||||
import AppBar from '@mui/material/AppBar';
|
import AppBar from '@mui/material/AppBar';
|
||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
@ -20,6 +19,9 @@ import LanguageMenu from './language-menu';
|
|||||||
import AppI18n, { Locales } from '../../classes/app-i18n';
|
import AppI18n, { Locales } from '../../classes/app-i18n';
|
||||||
|
|
||||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
|
import MenuIcon from '@mui/icons-material/Menu';
|
||||||
|
import ArrowRight from '@mui/icons-material/NavigateNext';
|
||||||
|
import ArrowLeft from '@mui/icons-material/NavigateBefore';
|
||||||
|
|
||||||
import AddCircleTwoTone from '@mui/icons-material/AddCircleTwoTone';
|
import AddCircleTwoTone from '@mui/icons-material/AddCircleTwoTone';
|
||||||
import CloudUploadTwoTone from '@mui/icons-material/CloudUploadTwoTone';
|
import CloudUploadTwoTone from '@mui/icons-material/CloudUploadTwoTone';
|
||||||
@ -41,7 +43,8 @@ import logoIcon from './logo-small.svg';
|
|||||||
import poweredByIcon from './pwrdby-white.svg';
|
import poweredByIcon from './pwrdby-white.svg';
|
||||||
import LabelDeleteConfirm from './maps-list/label-delete-confirm';
|
import LabelDeleteConfirm from './maps-list/label-delete-confirm';
|
||||||
import ReactGA from 'react-ga4';
|
import ReactGA from 'react-ga4';
|
||||||
import { withStyles } from '@mui/styles';
|
import { CSSObject, Interpolation, Theme } from '@emotion/react';
|
||||||
|
import withEmotionStyles from '../HOCs/withEmotionStyles';
|
||||||
|
|
||||||
export type Filter = GenericFilter | LabelFilter;
|
export type Filter = GenericFilter | LabelFilter;
|
||||||
|
|
||||||
@ -61,12 +64,22 @@ interface ToolbarButtonInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MapsPage = (): ReactElement => {
|
const MapsPage = (): ReactElement => {
|
||||||
const classes = useStyles();
|
|
||||||
const [filter, setFilter] = React.useState<Filter>({ type: 'all' });
|
const [filter, setFilter] = React.useState<Filter>({ type: 'all' });
|
||||||
const client: Client = useSelector(activeInstance);
|
const client: Client = useSelector(activeInstance);
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [activeDialog, setActiveDialog] = React.useState<ActionType | undefined>(undefined);
|
const [activeDialog, setActiveDialog] = React.useState<ActionType | undefined>(undefined);
|
||||||
const [labelToDelete, setLabelToDelete] = React.useState<number | null>(null);
|
const [labelToDelete, setLabelToDelete] = React.useState<number | null>(null);
|
||||||
|
const [mobileOpen, setMobileOpen] = React.useState(false);
|
||||||
|
const [desktopOpen, setDesktopOpen] = React.useState(true);
|
||||||
|
const classes = useStyles(desktopOpen);
|
||||||
|
|
||||||
|
const handleMobileDrawerToggle = () => {
|
||||||
|
setMobileOpen(!mobileOpen);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDesktopDrawerToggle = () => {
|
||||||
|
setDesktopOpen(!desktopOpen);
|
||||||
|
};
|
||||||
// Reload based on user preference ...
|
// Reload based on user preference ...
|
||||||
const userLocale = AppI18n.getUserLocale();
|
const userLocale = AppI18n.getUserLocale();
|
||||||
|
|
||||||
@ -85,6 +98,7 @@ const MapsPage = (): ReactElement => {
|
|||||||
id: 'maps.page-title',
|
id: 'maps.page-title',
|
||||||
defaultMessage: 'My Maps | WiseMapping',
|
defaultMessage: 'My Maps | WiseMapping',
|
||||||
});
|
});
|
||||||
|
window.scrollTo(0, 0);
|
||||||
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: 'Maps List' });
|
ReactGA.send({ hitType: 'pageview', page: window.location.pathname, title: 'Maps List' });
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -101,6 +115,7 @@ const MapsPage = (): ReactElement => {
|
|||||||
const handleMenuClick = (filter: Filter) => {
|
const handleMenuClick = (filter: Filter) => {
|
||||||
queryClient.invalidateQueries('maps');
|
queryClient.invalidateQueries('maps');
|
||||||
setFilter(filter);
|
setFilter(filter);
|
||||||
|
mobileOpen && setMobileOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLabelDelete = (id: number) => {
|
const handleLabelDelete = (id: number) => {
|
||||||
@ -148,22 +163,73 @@ const MapsPage = (): ReactElement => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const drawerItemsList = (
|
||||||
|
<>
|
||||||
|
<div style={{ padding: '20px 0 20px 16px' }} key="logo">
|
||||||
|
<img src={logoIcon} alt="logo" />
|
||||||
|
</div>
|
||||||
|
<List component="nav">
|
||||||
|
{filterButtons.map((buttonInfo) => {
|
||||||
|
return (
|
||||||
|
<StyleListItem
|
||||||
|
icon={buttonInfo.icon}
|
||||||
|
label={buttonInfo.label}
|
||||||
|
filter={buttonInfo.filter}
|
||||||
|
active={filter}
|
||||||
|
onClick={handleMenuClick}
|
||||||
|
onDelete={setLabelToDelete}
|
||||||
|
key={`${buttonInfo.filter.type}:${buttonInfo.label}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</List>
|
||||||
|
<div
|
||||||
|
className="poweredByIcon"
|
||||||
|
style={{ position: 'absolute', bottom: '10px', left: '20px' }}
|
||||||
|
key="power-by"
|
||||||
|
>
|
||||||
|
<Link href="http://www.wisemapping.org/">
|
||||||
|
<img src={poweredByIcon} alt="Powered By WiseMapping" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
const container = document !== undefined ? () => document.body : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IntlProvider
|
<IntlProvider
|
||||||
locale={userLocale.code}
|
locale={userLocale.code}
|
||||||
defaultLocale={Locales.EN.code}
|
defaultLocale={Locales.EN.code}
|
||||||
messages={userLocale.message}
|
messages={userLocale.message}
|
||||||
>
|
>
|
||||||
<div className={classes.root}>
|
<div css={classes.root}>
|
||||||
<AppBar
|
<AppBar
|
||||||
position="fixed"
|
position="fixed"
|
||||||
className={clsx(classes.appBar, {
|
css={[classes.appBar, open && classes.appBarShift]}
|
||||||
[classes.appBarShift]: open,
|
|
||||||
})}
|
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
elevation={0}
|
elevation={0}
|
||||||
>
|
>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
|
<IconButton
|
||||||
|
aria-label="open drawer"
|
||||||
|
edge="start"
|
||||||
|
onClick={handleMobileDrawerToggle}
|
||||||
|
sx={{ mr: 2, display: { sm: 'none' } }}
|
||||||
|
id="open-main-drawer"
|
||||||
|
>
|
||||||
|
<MenuIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
aria-label="open drawer"
|
||||||
|
edge="start"
|
||||||
|
onClick={handleDesktopDrawerToggle}
|
||||||
|
sx={{ p: 0, mr: 2, display: { xs: 'none', sm: 'inherit' } }}
|
||||||
|
id="open-desktop-drawer"
|
||||||
|
>
|
||||||
|
{!desktopOpen && <ArrowRight />}
|
||||||
|
{desktopOpen && <ArrowLeft />}
|
||||||
|
</IconButton>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
arrow={true}
|
arrow={true}
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
@ -179,10 +245,12 @@ const MapsPage = (): ReactElement => {
|
|||||||
type="button"
|
type="button"
|
||||||
disableElevation={true}
|
disableElevation={true}
|
||||||
startIcon={<AddCircleTwoTone />}
|
startIcon={<AddCircleTwoTone />}
|
||||||
className={classes.newMapButton}
|
css={classes.newMapButton}
|
||||||
onClick={() => setActiveDialog('create')}
|
onClick={() => setActiveDialog('create')}
|
||||||
>
|
>
|
||||||
|
<span className="message">
|
||||||
<FormattedMessage id="action.new" defaultMessage="New map" />
|
<FormattedMessage id="action.new" defaultMessage="New map" />
|
||||||
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
@ -200,10 +268,12 @@ const MapsPage = (): ReactElement => {
|
|||||||
type="button"
|
type="button"
|
||||||
disableElevation={true}
|
disableElevation={true}
|
||||||
startIcon={<CloudUploadTwoTone />}
|
startIcon={<CloudUploadTwoTone />}
|
||||||
className={classes.importButton}
|
css={classes.importButton}
|
||||||
onClick={() => setActiveDialog('import')}
|
onClick={() => setActiveDialog('import')}
|
||||||
>
|
>
|
||||||
|
<span className="message">
|
||||||
<FormattedMessage id="action.import" defaultMessage="Import" />
|
<FormattedMessage id="action.import" defaultMessage="Import" />
|
||||||
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<ActionDispatcher
|
<ActionDispatcher
|
||||||
@ -213,7 +283,7 @@ const MapsPage = (): ReactElement => {
|
|||||||
fromEditor
|
fromEditor
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={classes.rightButtonGroup}>
|
<div css={classes.rightButtonGroup as Interpolation<Theme>}>
|
||||||
<LanguageMenu />
|
<LanguageMenu />
|
||||||
<HelpMenu />
|
<HelpMenu />
|
||||||
<AccountMenu />
|
<AccountMenu />
|
||||||
@ -221,44 +291,29 @@ const MapsPage = (): ReactElement => {
|
|||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
<Drawer
|
<Drawer
|
||||||
variant="permanent"
|
container={container}
|
||||||
className={clsx(classes.drawer, {
|
variant={'temporary'}
|
||||||
[classes.drawerOpen]: open,
|
open={mobileOpen}
|
||||||
})}
|
onClose={handleMobileDrawerToggle}
|
||||||
classes={{
|
ModalProps={{
|
||||||
paper: clsx({
|
keepMounted: true,
|
||||||
[classes.drawerOpen]: open,
|
|
||||||
}),
|
|
||||||
}}
|
}}
|
||||||
|
css={[classes.mobileDrawer, { '& .MuiPaper-root': classes.drawerOpen }]}
|
||||||
>
|
>
|
||||||
<div style={{ padding: '20px 0 20px 15px' }} key="logo">
|
{drawerItemsList}
|
||||||
<img src={logoIcon} alt="logo" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<List component="nav">
|
|
||||||
{filterButtons.map((buttonInfo) => {
|
|
||||||
return (
|
|
||||||
<StyleListItem
|
|
||||||
icon={buttonInfo.icon}
|
|
||||||
label={buttonInfo.label}
|
|
||||||
filter={buttonInfo.filter}
|
|
||||||
active={filter}
|
|
||||||
onClick={handleMenuClick}
|
|
||||||
onDelete={setLabelToDelete}
|
|
||||||
key={`${buttonInfo.filter.type}:${buttonInfo.label}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</List>
|
|
||||||
|
|
||||||
<div style={{ position: 'absolute', bottom: '10px', left: '20px' }} key="power-by">
|
|
||||||
<Link href="http://www.wisemapping.org/">
|
|
||||||
<img src={poweredByIcon} alt="Powered By WiseMapping" />
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</Drawer>
|
</Drawer>
|
||||||
<main className={classes.content}>
|
<Drawer
|
||||||
<div className={classes.toolbar} />
|
variant="permanent"
|
||||||
|
css={[
|
||||||
|
classes.drawer as CSSObject,
|
||||||
|
classes.drawerOpen,
|
||||||
|
{ '& .MuiPaper-root': classes.drawerOpen },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{drawerItemsList}
|
||||||
|
</Drawer>
|
||||||
|
<main css={classes.content}>
|
||||||
|
<div css={classes.toolbar} />
|
||||||
<MapsList filter={filter} />
|
<MapsList filter={filter} />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
@ -286,24 +341,21 @@ interface ListItemProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/61486061/how-to-set-selected-and-hover-color-of-listitem-in-mui
|
// https://stackoverflow.com/questions/61486061/how-to-set-selected-and-hover-color-of-listitem-in-mui
|
||||||
const CustomListItem = withStyles({
|
const CustomListItem = withEmotionStyles({
|
||||||
root: {
|
'&.Mui-selected': {
|
||||||
'&$selected': {
|
|
||||||
backgroundColor: 'rgb(210, 140, 5)',
|
backgroundColor: 'rgb(210, 140, 5)',
|
||||||
color: 'white',
|
color: 'white',
|
||||||
'& .MuiListItemIcon-root': {
|
'& .MuiListItemIcon-root': {
|
||||||
color: 'white',
|
color: 'white',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'&$selected:hover': {
|
'&.Mui-selected:hover': {
|
||||||
backgroundColor: 'rgb(210, 140, 5)',
|
backgroundColor: 'rgb(210, 140, 5)',
|
||||||
color: 'white',
|
color: 'white',
|
||||||
'& .MuiListItemIcon-root': {
|
'& .MuiListItemIcon-root': {
|
||||||
color: 'white',
|
color: 'white',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
selected: {},
|
|
||||||
})(ListItemButton);
|
})(ListItemButton);
|
||||||
|
|
||||||
const StyleListItem = (props: ListItemProps) => {
|
const StyleListItem = (props: ListItemProps) => {
|
||||||
@ -336,7 +388,9 @@ const StyleListItem = (props: ListItemProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomListItem selected={isSelected} onClick={(e) => handleOnClick(e, filter)}>
|
<CustomListItem selected={isSelected} onClick={(e) => handleOnClick(e, filter)}>
|
||||||
|
<Tooltip title={label} disableInteractive>
|
||||||
<ListItemIcon>{icon}</ListItemIcon>
|
<ListItemIcon>{icon}</ListItemIcon>
|
||||||
|
</Tooltip>
|
||||||
<ListItemText style={{ color: 'white' }} primary={label} />
|
<ListItemText style={{ color: 'white' }} primary={label} />
|
||||||
{filter.type == 'label' && (
|
{filter.type == 'label' && (
|
||||||
<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
|
@ -16,6 +16,8 @@ import DialogContent from '@mui/material/DialogContent';
|
|||||||
import DialogContentText from '@mui/material/DialogContentText';
|
import DialogContentText from '@mui/material/DialogContentText';
|
||||||
import DialogActions from '@mui/material/DialogActions';
|
import DialogActions from '@mui/material/DialogActions';
|
||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
|
import { useTheme } from '@mui/material/styles';
|
||||||
|
import { mobileAppbarButton } from '../style';
|
||||||
|
|
||||||
const LanguageMenu = (): React.ReactElement => {
|
const LanguageMenu = (): React.ReactElement => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@ -25,6 +27,8 @@ const LanguageMenu = (): React.ReactElement => {
|
|||||||
|
|
||||||
const open = Boolean(anchorEl);
|
const open = Boolean(anchorEl);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const theme = useTheme();
|
||||||
|
const smMediaQuery = theme.breakpoints.down('sm');
|
||||||
|
|
||||||
// Todo: For some reasons, in some situations locale is null. More research needed.
|
// Todo: For some reasons, in some situations locale is null. More research needed.
|
||||||
const mutation = useMutation(
|
const mutation = useMutation(
|
||||||
@ -68,11 +72,14 @@ const LanguageMenu = (): React.ReactElement => {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
disableElevation={true}
|
disableElevation={true}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
css={{
|
||||||
|
[smMediaQuery]: mobileAppbarButton,
|
||||||
|
}}
|
||||||
style={{ borderColor: 'gray', color: 'gray' }}
|
style={{ borderColor: 'gray', color: 'gray' }}
|
||||||
onClick={handleMenu}
|
onClick={handleMenu}
|
||||||
startIcon={<TranslateTwoTone style={{ color: 'inherit' }} />}
|
startIcon={<TranslateTwoTone style={{ color: 'inherit' }} />}
|
||||||
>
|
>
|
||||||
{userLocale.label}
|
<span className="message">{userLocale.label}</span>
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Menu
|
<Menu
|
||||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 3.4 KiB |
@ -29,6 +29,8 @@ import InputBase from '@mui/material/InputBase';
|
|||||||
import Link from '@mui/material/Link';
|
import Link from '@mui/material/Link';
|
||||||
|
|
||||||
import DeleteOutlined from '@mui/icons-material/DeleteOutlined';
|
import DeleteOutlined from '@mui/icons-material/DeleteOutlined';
|
||||||
|
|
||||||
|
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||||
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
||||||
import StarRateRoundedIcon from '@mui/icons-material/StarRateRounded';
|
import StarRateRoundedIcon from '@mui/icons-material/StarRateRounded';
|
||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
@ -38,6 +40,12 @@ import { LabelsCell } from './labels-cell';
|
|||||||
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
||||||
import AppI18n from '../../../classes/app-i18n';
|
import AppI18n from '../../../classes/app-i18n';
|
||||||
import LabelTwoTone from '@mui/icons-material/LabelTwoTone';
|
import LabelTwoTone from '@mui/icons-material/LabelTwoTone';
|
||||||
|
import { CSSObject, Interpolation, Theme } from '@emotion/react';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Card from '@mui/material/Card';
|
||||||
|
import CardContent from '@mui/material/CardContent';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
import CardHeader from '@mui/material/CardHeader';
|
||||||
|
|
||||||
dayjs.extend(LocalizedFormat);
|
dayjs.extend(LocalizedFormat);
|
||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
@ -134,7 +142,7 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
|||||||
padding="checkbox"
|
padding="checkbox"
|
||||||
key="select"
|
key="select"
|
||||||
style={{ width: '20px' }}
|
style={{ width: '20px' }}
|
||||||
className={classes.headerCell}
|
css={classes.headerCell}
|
||||||
>
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
indeterminate={numSelected > 0 && numSelected < rowCount}
|
indeterminate={numSelected > 0 && numSelected < rowCount}
|
||||||
@ -145,7 +153,7 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
|||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell padding="checkbox" key="starred" className={classes.headerCell}></TableCell>
|
<TableCell padding="checkbox" key="starred" css={classes.headerCell}></TableCell>
|
||||||
|
|
||||||
{headCells.map((headCell) => {
|
{headCells.map((headCell) => {
|
||||||
return (
|
return (
|
||||||
@ -153,7 +161,7 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
|||||||
key={headCell.id}
|
key={headCell.id}
|
||||||
sortDirection={orderBy === headCell.id ? order : false}
|
sortDirection={orderBy === headCell.id ? order : false}
|
||||||
style={headCell.style}
|
style={headCell.style}
|
||||||
className={classes.headerCell}
|
css={classes.headerCell}
|
||||||
>
|
>
|
||||||
<TableSortLabel
|
<TableSortLabel
|
||||||
active={orderBy === headCell.id}
|
active={orderBy === headCell.id}
|
||||||
@ -163,7 +171,7 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
|||||||
{headCell.label}
|
{headCell.label}
|
||||||
|
|
||||||
{orderBy === headCell.id && (
|
{orderBy === headCell.id && (
|
||||||
<span className={classes.visuallyHidden}>
|
<span css={classes.visuallyHidden as Interpolation<Theme>}>
|
||||||
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@ -172,7 +180,7 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
<TableCell padding="checkbox" key="action" className={classes.headerCell}></TableCell>
|
<TableCell padding="checkbox" key="action" css={classes.headerCell}></TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
);
|
);
|
||||||
@ -334,7 +342,7 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
mapId: mapId,
|
mapId: mapId,
|
||||||
el: event.currentTarget,
|
el: event.currentTarget,
|
||||||
});
|
});
|
||||||
event.stopPropagation();
|
event.preventDefault();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -364,7 +372,7 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleStarred = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>, id: number) => {
|
const handleStarred = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>, id: number) => {
|
||||||
event.stopPropagation();
|
event.preventDefault();
|
||||||
starredMultation.mutate(id);
|
starredMultation.mutate(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -423,16 +431,16 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
|
|
||||||
const isSelected = (id: number) => selected.indexOf(id) !== -1;
|
const isSelected = (id: number) => selected.indexOf(id) !== -1;
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div css={classes.root}>
|
||||||
<ActionChooser
|
<ActionChooser
|
||||||
anchor={activeRowAction?.el}
|
anchor={activeRowAction?.el}
|
||||||
onClose={handleActionMenuClose}
|
onClose={handleActionMenuClose}
|
||||||
mapId={activeRowAction?.mapId}
|
mapId={activeRowAction?.mapId}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Paper className={classes.paper} elevation={0}>
|
<Paper css={classes.paper} elevation={0}>
|
||||||
<Toolbar className={classes.toolbar} variant="dense">
|
<Toolbar css={classes.toolbar} variant="dense">
|
||||||
<div className={classes.toolbarActions}>
|
<div css={classes.toolbarActions}>
|
||||||
{selected.length > 0 && (
|
{selected.length > 0 && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
arrow={true}
|
arrow={true}
|
||||||
@ -479,9 +487,24 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={classes.toolbarListActions}>
|
<div>
|
||||||
|
<div css={classes.search as Interpolation<Theme>}>
|
||||||
|
<div css={classes.searchIcon as Interpolation<Theme>}>
|
||||||
|
<SearchIcon />
|
||||||
|
</div>
|
||||||
|
<InputBase
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
id: 'maps.search-action',
|
||||||
|
defaultMessage: 'Search ...',
|
||||||
|
})}
|
||||||
|
css={[classes.searchInputRoot, classes.searchInputInput]}
|
||||||
|
inputProps={{ 'aria-label': 'search' }}
|
||||||
|
onChange={handleOnSearchChange}
|
||||||
|
// startAdornment={<SearchIcon />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<TablePagination
|
<TablePagination
|
||||||
style={{ float: 'right', border: '0', paddingBottom: '5px' }}
|
css={classes.tablePagination as Interpolation<Theme>}
|
||||||
count={mapsInfo.length}
|
count={mapsInfo.length}
|
||||||
rowsPerPageOptions={[]}
|
rowsPerPageOptions={[]}
|
||||||
rowsPerPage={rowsPerPage}
|
rowsPerPage={rowsPerPage}
|
||||||
@ -490,29 +513,108 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||||
component="div"
|
component="div"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={classes.search}>
|
|
||||||
<div className={classes.searchIcon}>
|
|
||||||
<SearchIcon />
|
|
||||||
</div>
|
|
||||||
<InputBase
|
|
||||||
placeholder={intl.formatMessage({
|
|
||||||
id: 'maps.search-action',
|
|
||||||
defaultMessage: 'Search ...',
|
|
||||||
})}
|
|
||||||
classes={{
|
|
||||||
root: classes.searchInputRoot,
|
|
||||||
input: classes.searchInputInput,
|
|
||||||
}}
|
|
||||||
inputProps={{ 'aria-label': 'search' }}
|
|
||||||
onChange={handleOnSearchChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<Table className={classes.table} size="small" stickyHeader>
|
<Box css={classes.cards}>
|
||||||
|
{isLoading ? (
|
||||||
|
<Card>
|
||||||
|
<CardContent>Loading ...</CardContent>
|
||||||
|
</Card>
|
||||||
|
) : mapsInfo.length == 0 ? (
|
||||||
|
<Card>
|
||||||
|
<CardContent>
|
||||||
|
<FormattedMessage
|
||||||
|
id="maps.empty-result"
|
||||||
|
defaultMessage="No matching mindmap found with the current filter criteria."
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
) : (
|
||||||
|
stableSort(mapsInfo, getComparator(order, orderBy))
|
||||||
|
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||||
|
.map((row: MapInfo) => {
|
||||||
|
return (
|
||||||
|
<Card key={row.id} css={{ maxWidth: '94vw', margin: '3vw' }}>
|
||||||
|
<Link
|
||||||
|
href={`/c/maps/${row.id}/edit`}
|
||||||
|
underline="none"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<CardHeader
|
||||||
|
css={classes.cardHeader}
|
||||||
|
avatar={
|
||||||
|
<Tooltip
|
||||||
|
arrow={true}
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'maps.tooltip-starred',
|
||||||
|
defaultMessage: 'Starred',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<div className="hola" onClick={(e) => e.stopPropagation()}>
|
||||||
|
<IconButton size="small" onClick={(e) => handleStarred(e, row.id)}>
|
||||||
|
<StarRateRoundedIcon
|
||||||
|
color="action"
|
||||||
|
style={{
|
||||||
|
color: row.starred ? 'yellow' : 'gray',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
action={
|
||||||
|
<Tooltip
|
||||||
|
arrow={true}
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'map.more-actions',
|
||||||
|
defaultMessage: 'More Actions',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<IconButton aria-label="settings" onClick={handleActionClick(row.id)}>
|
||||||
|
<MoreVertIcon color="action" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
title={
|
||||||
|
<Typography sx={{ fontSize: 'large' }} noWrap color="text.secondary">
|
||||||
|
{row.title}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
subheader={
|
||||||
|
<Typography variant="subtitle2">
|
||||||
|
{intl.formatMessage({
|
||||||
|
id: 'map.last-update',
|
||||||
|
defaultMessage: 'Last Update',
|
||||||
|
})}
|
||||||
|
<span>: </span>
|
||||||
|
<Tooltip
|
||||||
|
arrow={true}
|
||||||
|
title={intl.formatMessage(
|
||||||
|
{
|
||||||
|
id: 'maps.modified-by-desc',
|
||||||
|
defaultMessage: 'Modified by {by} on {on}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
by: row.lastModificationBy,
|
||||||
|
on: dayjs(row.lastModificationTime).format('lll'),
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
placement="bottom-start"
|
||||||
|
>
|
||||||
|
<span>{dayjs(row.lastModificationTime).fromNow()}</span>
|
||||||
|
</Tooltip>
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
<Table css={classes.table} size="small" stickyHeader>
|
||||||
<EnhancedTableHead
|
<EnhancedTableHead
|
||||||
classes={classes}
|
classes={classes}
|
||||||
numSelected={selected.length}
|
numSelected={selected.length}
|
||||||
@ -555,7 +657,7 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
selected={isItemSelected}
|
selected={isItemSelected}
|
||||||
style={{ border: '0' }}
|
style={{ border: '0' }}
|
||||||
>
|
>
|
||||||
<TableCell padding="checkbox" className={classes.bodyCell}>
|
<TableCell padding="checkbox" css={classes.bodyCell}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={isItemSelected}
|
checked={isItemSelected}
|
||||||
inputProps={{
|
inputProps={{
|
||||||
@ -565,7 +667,7 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell padding="checkbox" className={classes.bodyCell}>
|
<TableCell padding="checkbox" css={classes.bodyCell}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
arrow={true}
|
arrow={true}
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
@ -584,7 +686,7 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell css={classes.bodyCell}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
arrow={true}
|
arrow={true}
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
@ -604,7 +706,7 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={[classes.bodyCell, classes.labelsCell].join(' ')}>
|
<TableCell css={[classes.bodyCell, classes.labelsCell as CSSObject]}>
|
||||||
<LabelsCell
|
<LabelsCell
|
||||||
labels={row.labels}
|
labels={row.labels}
|
||||||
onDelete={(lbl) => {
|
onDelete={(lbl) => {
|
||||||
@ -613,9 +715,9 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>{row.createdBy}</TableCell>
|
<TableCell css={classes.bodyCell}>{row.createdBy}</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell css={classes.bodyCell}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
arrow={true}
|
arrow={true}
|
||||||
title={intl.formatMessage(
|
title={intl.formatMessage(
|
||||||
@ -634,7 +736,7 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell css={classes.bodyCell}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
arrow={true}
|
arrow={true}
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
|
@ -1,28 +1,37 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import { alpha, useTheme } from '@mui/material/styles';
|
import { alpha, useTheme } from '@mui/material/styles';
|
||||||
|
|
||||||
import createStyles from '@mui/styles/createStyles';
|
import useClasses from '../../../theme/useStyles';
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
export const useStyles = () => {
|
||||||
createStyles({
|
const theme = useTheme();
|
||||||
|
const smMediaQuery = theme.breakpoints.down('sm');
|
||||||
|
|
||||||
|
return useClasses({
|
||||||
root: {
|
root: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
},
|
},
|
||||||
paper: {
|
paper: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
marginBottom: useTheme().spacing(2),
|
marginBottom: theme.spacing(2),
|
||||||
|
},
|
||||||
|
cards: {
|
||||||
|
display: 'none',
|
||||||
|
[smMediaQuery]: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
|
[smMediaQuery]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
minWidth: 750,
|
minWidth: 750,
|
||||||
'& tr:nth-child(even)': {
|
'& tr:nth-of-type(2n)': {
|
||||||
background: 'white',
|
background: 'white',
|
||||||
},
|
},
|
||||||
'& tr:nth-child(odd)': {
|
'& tr:nth-of-type(2n+1)': {
|
||||||
background: 'rgba(221, 221, 221, 0.35)',
|
background: 'rgba(221, 221, 221, 0.35)',
|
||||||
},
|
},
|
||||||
// '&:hover tr': {
|
|
||||||
// backgroundColor: 'rgba(150, 150, 150, 0.7)',
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
headerCell: {
|
headerCell: {
|
||||||
background: 'white',
|
background: 'white',
|
||||||
@ -61,22 +70,31 @@ export const useStyles = makeStyles(() =>
|
|||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
paddingLeft: '23px;',
|
paddingLeft: '23px;',
|
||||||
},
|
},
|
||||||
toolbarListActions: {
|
|
||||||
flexGrow: 1,
|
|
||||||
},
|
|
||||||
search: {
|
search: {
|
||||||
borderRadius: 9,
|
borderRadius: 9,
|
||||||
backgroundColor: alpha(useTheme().palette.common.white, 0.15),
|
backgroundColor: alpha(theme.palette.common.white, 0.15),
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: alpha(useTheme().palette.common.white, 0.25),
|
backgroundColor: alpha(theme.palette.common.white, 0.25),
|
||||||
},
|
},
|
||||||
margin: '10px 0px',
|
margin: '10px 0px',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
[useTheme().breakpoints.up('sm')]: {
|
[theme.breakpoints.up('sm')]: {
|
||||||
marginLeft: useTheme().spacing(1),
|
marginLeft: theme.spacing(1),
|
||||||
width: 'auto',
|
width: 'auto',
|
||||||
},
|
},
|
||||||
|
float: 'left',
|
||||||
|
[smMediaQuery]: {
|
||||||
|
width: '50%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tablePagination: {
|
||||||
float: 'right',
|
float: 'right',
|
||||||
|
border: '0',
|
||||||
|
paddingBottom: '5px',
|
||||||
|
[smMediaQuery]: {
|
||||||
|
width: '50%',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
searchIcon: {
|
searchIcon: {
|
||||||
padding: '6px 0 0 5px',
|
padding: '6px 0 0 5px',
|
||||||
@ -93,19 +111,22 @@ export const useStyles = makeStyles(() =>
|
|||||||
float: 'right',
|
float: 'right',
|
||||||
},
|
},
|
||||||
searchInputInput: {
|
searchInputInput: {
|
||||||
// padding: theme.spacing(1, 1, 1, 0),
|
'& .MuiInputBase-input': {
|
||||||
// vertical padding + font size from searchIcon
|
|
||||||
border: '1px solid #ffa800',
|
border: '1px solid #ffa800',
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
paddingLeft: `calc(1em + ${useTheme().spacing(4)})`,
|
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
|
||||||
transition: useTheme().transitions.create('width'),
|
transition: theme.transitions.create('width'),
|
||||||
width: '100%',
|
width: '100%',
|
||||||
[useTheme().breakpoints.up('sm')]: {
|
[theme.breakpoints.up('sm')]: {
|
||||||
width: '12ch',
|
width: '12ch',
|
||||||
'&:focus': {
|
'&:focus': {
|
||||||
width: '20ch',
|
width: '20ch',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
);
|
cardHeader: {
|
||||||
|
padding: '4px',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -1,10 +1,45 @@
|
|||||||
import createStyles from '@mui/styles/createStyles';
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import makeStyles from '@mui/styles/makeStyles';
|
import { CSSObject } from '@emotion/react';
|
||||||
|
import { Theme, useTheme } from '@mui/material/styles';
|
||||||
|
import useClasses from '../../theme/useStyles';
|
||||||
|
|
||||||
const drawerWidth = 300;
|
const openedMixin = (theme: Theme, drawerWidth): CSSObject => ({
|
||||||
|
width: drawerWidth,
|
||||||
|
transition: theme.transitions.create('width', {
|
||||||
|
easing: theme.transitions.easing.sharp,
|
||||||
|
duration: theme.transitions.duration.enteringScreen,
|
||||||
|
}),
|
||||||
|
overflowX: 'hidden',
|
||||||
|
});
|
||||||
|
|
||||||
export const useStyles = makeStyles(() =>
|
const closedMixin = (theme: Theme): CSSObject => ({
|
||||||
createStyles({
|
transition: theme.transitions.create('width', {
|
||||||
|
easing: theme.transitions.easing.sharp,
|
||||||
|
duration: theme.transitions.duration.leavingScreen,
|
||||||
|
}),
|
||||||
|
overflowX: 'hidden',
|
||||||
|
width: `calc(${theme.spacing(7)} + 1px)`,
|
||||||
|
[theme.breakpoints.up('sm')]: {
|
||||||
|
width: `calc(${theme.spacing(8)} + 1px)`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const mobileAppbarButton = {
|
||||||
|
padding: 0,
|
||||||
|
minWidth: 'unset',
|
||||||
|
'& .message': {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
'& .MuiButton-startIcon': {
|
||||||
|
margin: 0,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export function useStyles(drawerOpen) {
|
||||||
|
const drawerWidth = drawerOpen ? 300 : 66;
|
||||||
|
const theme = useTheme();
|
||||||
|
const smMediaQuery = theme.breakpoints.down('sm');
|
||||||
|
return useClasses({
|
||||||
root: {
|
root: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
},
|
},
|
||||||
@ -14,29 +49,70 @@ export const useStyles = makeStyles(() =>
|
|||||||
appBarShift: {
|
appBarShift: {
|
||||||
marginLeft: drawerWidth,
|
marginLeft: drawerWidth,
|
||||||
width: `calc(100% - ${drawerWidth}px)`,
|
width: `calc(100% - ${drawerWidth}px)`,
|
||||||
|
[smMediaQuery]: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
newMapButton: {
|
newMapButton: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
minWidth: '130px',
|
minWidth: '130px',
|
||||||
|
[smMediaQuery]: mobileAppbarButton,
|
||||||
},
|
},
|
||||||
importButton: {
|
importButton: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
minWidth: '130px',
|
minWidth: '130px',
|
||||||
|
[smMediaQuery]: mobileAppbarButton,
|
||||||
},
|
},
|
||||||
rightButtonGroup: {
|
rightButtonGroup: {
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
flexGrow: 10,
|
flexGrow: 10,
|
||||||
textAlign: 'right',
|
textAlign: 'right',
|
||||||
minWidth: '280px',
|
minWidth: '280px',
|
||||||
|
[smMediaQuery]: {
|
||||||
|
minWidth: 'unset',
|
||||||
|
marginRight: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
drawer: {
|
drawer: {
|
||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
|
[smMediaQuery]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
...(drawerOpen && {
|
||||||
|
...openedMixin(theme, drawerWidth),
|
||||||
|
'& .MuiDrawer-paper': openedMixin(theme, drawerWidth),
|
||||||
|
}),
|
||||||
|
...(!drawerOpen && {
|
||||||
|
...closedMixin(theme),
|
||||||
|
'& .MuiDrawer-paper': closedMixin(theme),
|
||||||
|
}),
|
||||||
|
'& .MuiListItemText-root': {
|
||||||
|
display: 'block',
|
||||||
|
...(!drawerOpen && {
|
||||||
|
color: 'transparent',
|
||||||
|
'& span': { color: 'transparent' },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
'& .MuiListItemSecondaryAction-root, & .poweredByIcon': {
|
||||||
|
display: 'block',
|
||||||
|
...(!drawerOpen && { display: 'none' }),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mobileDrawer: {
|
||||||
|
display: 'none',
|
||||||
|
[smMediaQuery]: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
drawerOpen: {
|
drawerOpen: {
|
||||||
background: '#ffa800',
|
background: '#ffa800',
|
||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
|
[smMediaQuery]: {
|
||||||
|
width: 300,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
toolbar: {
|
toolbar: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -47,5 +123,5 @@ export const useStyles = makeStyles(() =>
|
|||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
padding: '24px 0px',
|
padding: '24px 0px',
|
||||||
},
|
},
|
||||||
}),
|
});
|
||||||
);
|
}
|
||||||
|
20
packages/webapp/src/theme/useStyles.ts
Normal file
20
packages/webapp/src/theme/useStyles.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { css } from '@emotion/react';
|
||||||
|
import { useTheme } from '@emotion/react';
|
||||||
|
|
||||||
|
const getStyle = (value) => {
|
||||||
|
return css(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
function useClasses<T>(stylesElement: T): T {
|
||||||
|
const theme = useTheme();
|
||||||
|
const rawClasses = typeof stylesElement === 'function' ? stylesElement(theme) : stylesElement;
|
||||||
|
const prepared = {};
|
||||||
|
|
||||||
|
Object.entries(rawClasses).forEach(([key, value]) => {
|
||||||
|
prepared[key] = getStyle(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return prepared as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useClasses;
|
Loading…
Reference in New Issue
Block a user