mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-12-22 11:43:48 +01:00
Merged in feat/prettier (pull request #3)
adding back semicolons * adding back semicolons
This commit is contained in:
parent
b63d7ee665
commit
3d538923a9
@ -1,7 +1,7 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"semi": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { StyledCanvas } from './styled'
|
||||
import React from 'react';
|
||||
import { StyledCanvas } from './styled';
|
||||
|
||||
const Canvas = (): React.ReactElement => <StyledCanvas>canvas</StyledCanvas>
|
||||
const Canvas = (): React.ReactElement => <StyledCanvas>canvas</StyledCanvas>;
|
||||
|
||||
export default Canvas
|
||||
export default Canvas;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import styled from 'styled-components'
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const StyledCanvas = styled.div`
|
||||
height: 100%
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
|
||||
`
|
||||
`;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { StyledFooter } from './styled'
|
||||
import React from 'react';
|
||||
import { StyledFooter } from './styled';
|
||||
|
||||
const Footer = (): React.ReactElement => <StyledFooter>footer</StyledFooter>
|
||||
const Footer = (): React.ReactElement => <StyledFooter>footer</StyledFooter>;
|
||||
|
||||
export default Footer
|
||||
export default Footer;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import styled from 'styled-components'
|
||||
import { times } from '../../size'
|
||||
import styled from 'styled-components';
|
||||
import { times } from '../../size';
|
||||
|
||||
export const StyledFooter = styled.div`
|
||||
height: ${times(10)};
|
||||
width: 100%;
|
||||
border: 1px solid black;
|
||||
`
|
||||
`;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from 'react'
|
||||
import Footer from '../footer'
|
||||
import TopBar from '../top-bar'
|
||||
import Canvas from '../canvas'
|
||||
import { StyledFrame } from './styled'
|
||||
import React from 'react';
|
||||
import Footer from '../footer';
|
||||
import TopBar from '../top-bar';
|
||||
import Canvas from '../canvas';
|
||||
import { StyledFrame } from './styled';
|
||||
|
||||
const Frame = (): React.ReactElement => (
|
||||
<StyledFrame>
|
||||
@ -10,6 +10,6 @@ const Frame = (): React.ReactElement => (
|
||||
<Canvas />
|
||||
<Footer />
|
||||
</StyledFrame>
|
||||
)
|
||||
);
|
||||
|
||||
export default Frame
|
||||
export default Frame;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import styled from 'styled-components'
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const StyledFrame = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`
|
||||
`;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { StyledTopBar } from './styled'
|
||||
import React from 'react';
|
||||
import { StyledTopBar } from './styled';
|
||||
|
||||
const TopBar = (): React.ReactElement => <StyledTopBar>top bar</StyledTopBar>
|
||||
const TopBar = (): React.ReactElement => <StyledTopBar>top bar</StyledTopBar>;
|
||||
|
||||
export default TopBar
|
||||
export default TopBar;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import styled from 'styled-components'
|
||||
import { times } from '../../size'
|
||||
import styled from 'styled-components';
|
||||
import { times } from '../../size';
|
||||
|
||||
export const StyledTopBar = styled.div`
|
||||
height: ${times(10)};
|
||||
width: 100%;
|
||||
border: 1px solid black;
|
||||
`
|
||||
`;
|
||||
|
@ -1,3 +1,3 @@
|
||||
import Editor from './components/frame'
|
||||
import Editor from './components/frame';
|
||||
|
||||
export default Editor
|
||||
export default Editor;
|
||||
|
@ -1,9 +1,9 @@
|
||||
const unit = 4 // pixels
|
||||
const unit = 4; // pixels
|
||||
|
||||
export const XS = '4px'
|
||||
export const S = '8px'
|
||||
export const M = '16px'
|
||||
export const L = '24px'
|
||||
export const XL = '24px'
|
||||
export const XS = '4px';
|
||||
export const S = '8px';
|
||||
export const M = '16px';
|
||||
export const L = '24px';
|
||||
export const XL = '24px';
|
||||
|
||||
export const times = (n: number): string => `${unit * n}px`
|
||||
export const times = (n: number): string => `${unit * n}px`;
|
||||
|
@ -1,16 +1,16 @@
|
||||
import MapsPage from '../pageObject/MapsPage'
|
||||
import MapsPage from '../pageObject/MapsPage';
|
||||
|
||||
context('Maps Page', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('http://localhost:3000/c/maps')
|
||||
})
|
||||
cy.visit('http://localhost:3000/c/maps');
|
||||
});
|
||||
|
||||
it('should load the maps page', () => {
|
||||
MapsPage.isLoaded()
|
||||
})
|
||||
MapsPage.isLoaded();
|
||||
});
|
||||
|
||||
it('should open the create dialog', () => {
|
||||
MapsPage.create()
|
||||
MapsPage.isCreateDialogVisible()
|
||||
})
|
||||
})
|
||||
MapsPage.create();
|
||||
MapsPage.isCreateDialogVisible();
|
||||
});
|
||||
});
|
||||
|
@ -1,14 +1,14 @@
|
||||
export default class MapsPage {
|
||||
static isLoaded() {
|
||||
return cy.findByTestId('create')
|
||||
return cy.findByTestId('create');
|
||||
}
|
||||
|
||||
static create() {
|
||||
return cy.findByTestId('create').click()
|
||||
return cy.findByTestId('create').click();
|
||||
}
|
||||
|
||||
static isCreateDialogVisible() {
|
||||
//TODO move to findByText when the double create dialog issue is solved
|
||||
return cy.findAllByText('Create a new mindmap')
|
||||
return cy.findAllByText('Create a new mindmap');
|
||||
}
|
||||
}
|
||||
|
@ -4,4 +4,4 @@
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
};
|
||||
|
@ -1 +1 @@
|
||||
import '@testing-library/cypress/add-commands'
|
||||
import '@testing-library/cypress/add-commands';
|
||||
|
@ -1 +1 @@
|
||||
import './commands'
|
||||
import './commands';
|
||||
|
4
packages/webapp/src/@types/index.d.ts
vendored
4
packages/webapp/src/@types/index.d.ts
vendored
@ -1,2 +1,2 @@
|
||||
declare module '*.png'
|
||||
declare module '*.svg'
|
||||
declare module '*.png';
|
||||
declare module '*.svg';
|
||||
|
24
packages/webapp/src/@types/typings.d.ts
vendored
24
packages/webapp/src/@types/typings.d.ts
vendored
@ -1,19 +1,19 @@
|
||||
declare module '*.jpeg'
|
||||
declare module '*.jpg'
|
||||
declare module '*.jpeg'
|
||||
declare module '*.png'
|
||||
declare module '*.svg'
|
||||
declare module '*.json'
|
||||
declare module '*.jpeg';
|
||||
declare module '*.jpg';
|
||||
declare module '*.jpeg';
|
||||
declare module '*.png';
|
||||
declare module '*.svg';
|
||||
declare module '*.json';
|
||||
|
||||
import { Dayjs } from 'dayjs'
|
||||
type DateType = string | number | Date | Dayjs
|
||||
import { Dayjs } from 'dayjs';
|
||||
type DateType = string | number | Date | Dayjs;
|
||||
|
||||
// @Todo: review if there is a better support for this.
|
||||
declare module 'dayjs' {
|
||||
interface Dayjs {
|
||||
fromNow(withoutSuffix?: boolean): string
|
||||
from(compared: DateType, withoutSuffix?: boolean): string
|
||||
toNow(withoutSuffix?: boolean): string
|
||||
to(compared: DateType, withoutSuffix?: boolean): string
|
||||
fromNow(withoutSuffix?: boolean): string;
|
||||
from(compared: DateType, withoutSuffix?: boolean): string;
|
||||
toNow(withoutSuffix?: boolean): string;
|
||||
to(compared: DateType, withoutSuffix?: boolean): string;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import { IntlProvider } from 'react-intl'
|
||||
import { Route, Switch, Redirect, BrowserRouter as Router } from 'react-router-dom'
|
||||
import React, { ReactElement } from 'react';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { Route, Switch, Redirect, BrowserRouter as Router } from 'react-router-dom';
|
||||
|
||||
import RegistrationSuccessPage from './components/registration-success-page'
|
||||
import ForgotPasswordSuccessPage from './components/forgot-password-success-page'
|
||||
import RegistationPage from './components/registration-page'
|
||||
import LoginPage from './components/login-page'
|
||||
import store from './redux/store'
|
||||
import { ForgotPasswordPage } from './components/forgot-password-page'
|
||||
import { Provider } from 'react-redux'
|
||||
import { QueryClient, QueryClientProvider } from 'react-query'
|
||||
import { theme } from './theme'
|
||||
import AppI18n, { Locales } from './classes/app-i18n'
|
||||
import MapsPage from './components/maps-page'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import { ThemeProvider } from '@material-ui/core/styles'
|
||||
import RegistrationSuccessPage from './components/registration-success-page';
|
||||
import ForgotPasswordSuccessPage from './components/forgot-password-success-page';
|
||||
import RegistationPage from './components/registration-page';
|
||||
import LoginPage from './components/login-page';
|
||||
import store from './redux/store';
|
||||
import { ForgotPasswordPage } from './components/forgot-password-page';
|
||||
import { Provider } from 'react-redux';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { theme } from './theme';
|
||||
import AppI18n, { Locales } from './classes/app-i18n';
|
||||
import MapsPage from './components/maps-page';
|
||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
||||
import { ThemeProvider } from '@material-ui/core/styles';
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
@ -23,11 +23,11 @@ const queryClient = new QueryClient({
|
||||
staleTime: 5 * 1000 * 60, // 10 minutes
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
const App = (): ReactElement => {
|
||||
const appi18n = new AppI18n()
|
||||
const locale = appi18n.getBrowserLocale()
|
||||
const appi18n = new AppI18n();
|
||||
const locale = appi18n.getBrowserLocale();
|
||||
|
||||
return locale.message ? (
|
||||
<Provider store={store}>
|
||||
@ -70,7 +70,7 @@ const App = (): ReactElement => {
|
||||
</Provider>
|
||||
) : (
|
||||
<div>Loading ... </div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default App
|
||||
export default App;
|
||||
|
@ -1,60 +1,60 @@
|
||||
import { fetchAccount } from './../../redux/clientSlice'
|
||||
import 'dayjs/locale/fr'
|
||||
import 'dayjs/locale/en'
|
||||
import 'dayjs/locale/es'
|
||||
import { fetchAccount } from './../../redux/clientSlice';
|
||||
import 'dayjs/locale/fr';
|
||||
import 'dayjs/locale/en';
|
||||
import 'dayjs/locale/es';
|
||||
|
||||
export class Locale {
|
||||
code: LocaleCode
|
||||
label: string
|
||||
message: Record<string, string>
|
||||
code: LocaleCode;
|
||||
label: string;
|
||||
message: Record<string, string>;
|
||||
|
||||
constructor(code: LocaleCode, label: string, message: unknown) {
|
||||
this.code = code
|
||||
this.label = label
|
||||
this.message = message as Record<string, string>
|
||||
this.code = code;
|
||||
this.label = label;
|
||||
this.message = message as Record<string, string>;
|
||||
}
|
||||
}
|
||||
|
||||
export default class AppI18n {
|
||||
public getUserLocale(): Locale {
|
||||
const account = fetchAccount()
|
||||
return account ? account.locale : this.getBrowserLocale()
|
||||
const account = fetchAccount();
|
||||
return account ? account.locale : this.getBrowserLocale();
|
||||
}
|
||||
|
||||
public getBrowserLocale(): Locale {
|
||||
let localeCode = (navigator.languages && navigator.languages[0]) || navigator.language
|
||||
let localeCode = (navigator.languages && navigator.languages[0]) || navigator.language;
|
||||
|
||||
// Just remove the variant ...
|
||||
localeCode = localeCode.split('-')[0]
|
||||
localeCode = localeCode.split('-')[0];
|
||||
|
||||
let result = Locales.EN
|
||||
let result = Locales.EN;
|
||||
try {
|
||||
result = localeFromStr(localeCode)
|
||||
result = localeFromStr(localeCode);
|
||||
} catch {
|
||||
console.warn(`Unsupported languange code ${localeCode}`)
|
||||
console.warn(`Unsupported languange code ${localeCode}`);
|
||||
}
|
||||
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export type LocaleCode = 'en' | 'es' | 'fr' | 'de'
|
||||
export type LocaleCode = 'en' | 'es' | 'fr' | 'de';
|
||||
|
||||
export const Locales = {
|
||||
EN: new Locale('en', 'English', require('./../../compiled-lang/en.json')),
|
||||
ES: new Locale('es', 'Español', require('./../../compiled-lang/es.json')),
|
||||
DE: new Locale('fr', 'Français', require('./../../compiled-lang/fr.json')),
|
||||
FR: new Locale('de', 'Deutsch', require('./../../compiled-lang/de.json')),
|
||||
}
|
||||
};
|
||||
|
||||
export const localeFromStr = (code: string): Locale => {
|
||||
const locales: Locale[] = Object.values(Locales)
|
||||
const locales: Locale[] = Object.values(Locales);
|
||||
|
||||
const result = locales.find((l) => l.code == code)
|
||||
const result = locales.find((l) => l.code == code);
|
||||
|
||||
if (!result) {
|
||||
throw `Language code could not be found in list of default supported: + ${code}`
|
||||
throw `Language code could not be found in list of default supported: + ${code}`;
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { useSelector } from 'react-redux'
|
||||
import React from 'react'
|
||||
import { activeInstanceStatus, ClientStatus } from '../../../redux/clientSlice'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import Alert from '@material-ui/lab/Alert'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import AlertTitle from '@material-ui/lab/AlertTitle'
|
||||
import { useSelector } from 'react-redux';
|
||||
import React from 'react';
|
||||
import { activeInstanceStatus, ClientStatus } from '../../../redux/clientSlice';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import AlertTitle from '@material-ui/lab/AlertTitle';
|
||||
|
||||
const ClientHealthSentinel = (): React.ReactElement => {
|
||||
const status: ClientStatus = useSelector(activeInstanceStatus)
|
||||
const status: ClientStatus = useSelector(activeInstanceStatus);
|
||||
|
||||
const handleOnClose = () => {
|
||||
window.location.href = '/c/login'
|
||||
}
|
||||
window.location.href = '/c/login';
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -50,6 +50,6 @@ const ClientHealthSentinel = (): React.ReactElement => {
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default ClientHealthSentinel
|
||||
);
|
||||
};
|
||||
export default ClientHealthSentinel;
|
||||
|
@ -1,108 +1,108 @@
|
||||
import { Locale, LocaleCode } from '../app-i18n'
|
||||
import { Locale, LocaleCode } from '../app-i18n';
|
||||
|
||||
export type NewUser = {
|
||||
email: string
|
||||
firstname: string
|
||||
lastname: string
|
||||
password: string
|
||||
recaptcha: string | null
|
||||
}
|
||||
email: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
password: string;
|
||||
recaptcha: string | null;
|
||||
};
|
||||
|
||||
export type ImportMapInfo = {
|
||||
title: string
|
||||
description?: string
|
||||
contentType?: string
|
||||
content?: ArrayBuffer | null | string
|
||||
}
|
||||
title: string;
|
||||
description?: string;
|
||||
contentType?: string;
|
||||
content?: ArrayBuffer | null | string;
|
||||
};
|
||||
|
||||
export type Label = {
|
||||
id: number
|
||||
title: string
|
||||
color: string
|
||||
iconName: string
|
||||
}
|
||||
id: number;
|
||||
title: string;
|
||||
color: string;
|
||||
iconName: string;
|
||||
};
|
||||
|
||||
export type Role = 'owner' | 'editor' | 'viewer'
|
||||
export type Role = 'owner' | 'editor' | 'viewer';
|
||||
|
||||
export type MapInfo = {
|
||||
id: number
|
||||
starred: boolean
|
||||
title: string
|
||||
labels: number[]
|
||||
createdBy: string
|
||||
creationTime: string
|
||||
lastModificationBy: string
|
||||
lastModificationTime: string
|
||||
description: string
|
||||
isPublic: boolean
|
||||
role: Role
|
||||
}
|
||||
id: number;
|
||||
starred: boolean;
|
||||
title: string;
|
||||
labels: number[];
|
||||
createdBy: string;
|
||||
creationTime: string;
|
||||
lastModificationBy: string;
|
||||
lastModificationTime: string;
|
||||
description: string;
|
||||
isPublic: boolean;
|
||||
role: Role;
|
||||
};
|
||||
|
||||
export type ChangeHistory = {
|
||||
id: number
|
||||
lastModificationBy: string
|
||||
lastModificationTime: string
|
||||
}
|
||||
id: number;
|
||||
lastModificationBy: string;
|
||||
lastModificationTime: string;
|
||||
};
|
||||
|
||||
export type BasicMapInfo = {
|
||||
title: string
|
||||
description?: string
|
||||
}
|
||||
title: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export type FieldError = {
|
||||
id: string
|
||||
msg: string
|
||||
}
|
||||
id: string;
|
||||
msg: string;
|
||||
};
|
||||
|
||||
export type ErrorInfo = {
|
||||
msg?: string
|
||||
fields?: Map<string, string>
|
||||
}
|
||||
msg?: string;
|
||||
fields?: Map<string, string>;
|
||||
};
|
||||
|
||||
export type AccountInfo = {
|
||||
firstname: string
|
||||
lastname: string
|
||||
email: string
|
||||
locale: Locale
|
||||
}
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
email: string;
|
||||
locale: Locale;
|
||||
};
|
||||
|
||||
export type Permission = {
|
||||
name?: string
|
||||
email: string
|
||||
role: Role
|
||||
}
|
||||
name?: string;
|
||||
email: string;
|
||||
role: Role;
|
||||
};
|
||||
|
||||
interface Client {
|
||||
deleteAccount(): Promise<void>
|
||||
importMap(model: ImportMapInfo): Promise<number>
|
||||
createMap(map: BasicMapInfo): Promise<number>
|
||||
deleteMaps(ids: number[]): Promise<void>
|
||||
deleteMap(id: number): Promise<void>
|
||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>
|
||||
fetchAllMaps(): Promise<MapInfo[]>
|
||||
deleteAccount(): Promise<void>;
|
||||
importMap(model: ImportMapInfo): Promise<number>;
|
||||
createMap(map: BasicMapInfo): Promise<number>;
|
||||
deleteMaps(ids: number[]): Promise<void>;
|
||||
deleteMap(id: number): Promise<void>;
|
||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
|
||||
fetchAllMaps(): Promise<MapInfo[]>;
|
||||
|
||||
fetchMapPermissions(id: number): Promise<Permission[]>
|
||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void>
|
||||
deleteMapPermission(id: number, email: string): Promise<void>
|
||||
fetchMapPermissions(id: number): Promise<Permission[]>;
|
||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void>;
|
||||
deleteMapPermission(id: number, email: string): Promise<void>;
|
||||
|
||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>
|
||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>;
|
||||
|
||||
updateAccountLanguage(locale: LocaleCode): Promise<void>
|
||||
updateAccountPassword(pasword: string): Promise<void>
|
||||
updateAccountInfo(firstname: string, lastname: string): Promise<void>
|
||||
updateAccountLanguage(locale: LocaleCode): Promise<void>;
|
||||
updateAccountPassword(pasword: string): Promise<void>;
|
||||
updateAccountInfo(firstname: string, lastname: string): Promise<void>;
|
||||
|
||||
updateStarred(id: number, starred: boolean): Promise<void>
|
||||
updateMapToPublic(id: number, starred: boolean): Promise<void>
|
||||
updateStarred(id: number, starred: boolean): Promise<void>;
|
||||
updateMapToPublic(id: number, starred: boolean): Promise<void>;
|
||||
|
||||
fetchLabels(): Promise<Label[]>
|
||||
deleteLabel(id: number): Promise<void>
|
||||
fetchAccountInfo(): Promise<AccountInfo>
|
||||
fetchLabels(): Promise<Label[]>;
|
||||
deleteLabel(id: number): Promise<void>;
|
||||
fetchAccountInfo(): Promise<AccountInfo>;
|
||||
|
||||
registerNewUser(user: NewUser): Promise<void>
|
||||
resetPassword(email: string): Promise<void>
|
||||
registerNewUser(user: NewUser): Promise<void>;
|
||||
resetPassword(email: string): Promise<void>;
|
||||
|
||||
fetchHistory(id: number): Promise<ChangeHistory[]>
|
||||
revertHistory(id: number, cid: number): Promise<void>
|
||||
fetchHistory(id: number): Promise<ChangeHistory[]>;
|
||||
revertHistory(id: number, cid: number): Promise<void>;
|
||||
}
|
||||
|
||||
export default Client
|
||||
export default Client;
|
||||
|
@ -7,13 +7,13 @@ import Client, {
|
||||
MapInfo,
|
||||
NewUser,
|
||||
Permission,
|
||||
} from '..'
|
||||
import { LocaleCode, localeFromStr } from '../../app-i18n'
|
||||
} from '..';
|
||||
import { LocaleCode, localeFromStr } from '../../app-i18n';
|
||||
|
||||
class MockClient implements Client {
|
||||
private maps: MapInfo[] = []
|
||||
private labels: Label[] = []
|
||||
private permissionsByMap: Map<number, Permission[]> = new Map()
|
||||
private maps: MapInfo[] = [];
|
||||
private labels: Label[] = [];
|
||||
private permissionsByMap: Map<number, Permission[]> = new Map();
|
||||
|
||||
constructor() {
|
||||
// Remove, just for develop ....
|
||||
@ -42,7 +42,7 @@ class MockClient implements Client {
|
||||
description,
|
||||
isPublic,
|
||||
role,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this.maps = [
|
||||
@ -85,31 +85,31 @@ class MockClient implements Client {
|
||||
false,
|
||||
'editor'
|
||||
),
|
||||
]
|
||||
];
|
||||
|
||||
this.labels = [
|
||||
{ id: 1, title: 'Red Label', iconName: '', color: 'red' },
|
||||
{ id: 2, title: 'Blue Label', iconName: '', color: 'blue' },
|
||||
]
|
||||
];
|
||||
}
|
||||
deleteMapPermission(id: number, email: string): Promise<void> {
|
||||
let perm = this.permissionsByMap.get(id) || []
|
||||
perm = perm.filter((p) => p.email != email)
|
||||
this.permissionsByMap.set(id, perm)
|
||||
return Promise.resolve()
|
||||
let perm = this.permissionsByMap.get(id) || [];
|
||||
perm = perm.filter((p) => p.email != email);
|
||||
this.permissionsByMap.set(id, perm);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
|
||||
let perm = this.permissionsByMap.get(id) || []
|
||||
perm = perm.concat(permissions)
|
||||
this.permissionsByMap.set(id, perm)
|
||||
let perm = this.permissionsByMap.get(id) || [];
|
||||
perm = perm.concat(permissions);
|
||||
this.permissionsByMap.set(id, perm);
|
||||
|
||||
console.log(`Message ${message}`)
|
||||
return Promise.resolve()
|
||||
console.log(`Message ${message}`);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
fetchMapPermissions(id: number): Promise<Permission[]> {
|
||||
let perm = this.permissionsByMap.get(id)
|
||||
let perm = this.permissionsByMap.get(id);
|
||||
if (!perm) {
|
||||
perm = [
|
||||
{
|
||||
@ -127,107 +127,107 @@ class MockClient implements Client {
|
||||
email: 'pepe3@example.com',
|
||||
role: 'viewer',
|
||||
},
|
||||
]
|
||||
this.permissionsByMap.set(id, perm)
|
||||
];
|
||||
this.permissionsByMap.set(id, perm);
|
||||
}
|
||||
return Promise.resolve(perm)
|
||||
return Promise.resolve(perm);
|
||||
}
|
||||
|
||||
deleteAccount(): Promise<void> {
|
||||
return Promise.resolve()
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
updateAccountInfo(firstname: string, lastname: string): Promise<void> {
|
||||
console.log('firstname:' + firstname, +lastname)
|
||||
return Promise.resolve()
|
||||
console.log('firstname:' + firstname, +lastname);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
updateAccountPassword(pasword: string): Promise<void> {
|
||||
console.log('password:' + pasword)
|
||||
return Promise.resolve()
|
||||
console.log('password:' + pasword);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
||||
localStorage.setItem('locale', locale)
|
||||
return Promise.resolve()
|
||||
localStorage.setItem('locale', locale);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
importMap(model: ImportMapInfo): Promise<number> {
|
||||
console.log('model:' + model)
|
||||
return Promise.resolve(10)
|
||||
console.log('model:' + model);
|
||||
return Promise.resolve(10);
|
||||
}
|
||||
|
||||
fetchAccountInfo(): Promise<AccountInfo> {
|
||||
console.log('Fetch account info ...')
|
||||
const locale: LocaleCode | null = localStorage.getItem('locale') as LocaleCode
|
||||
console.log('Fetch account info ...');
|
||||
const locale: LocaleCode | null = localStorage.getItem('locale') as LocaleCode;
|
||||
return Promise.resolve({
|
||||
firstname: 'Costme',
|
||||
lastname: 'Fulanito',
|
||||
email: 'test@example.com',
|
||||
locale: localeFromStr(locale),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
deleteMaps(ids: number[]): Promise<void> {
|
||||
ids.forEach((id) => this.deleteMap(id))
|
||||
return Promise.resolve()
|
||||
ids.forEach((id) => this.deleteMap(id));
|
||||
return Promise.resolve();
|
||||
}
|
||||
revertHistory(id: number, cid: number): Promise<void> {
|
||||
console.log('model:' + id + cid)
|
||||
return Promise.resolve()
|
||||
console.log('model:' + id + cid);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
createMap(map: BasicMapInfo): Promise<number> {
|
||||
throw new Error('Method not implemented.' + map)
|
||||
throw new Error('Method not implemented.' + map);
|
||||
}
|
||||
|
||||
fetchLabels(): Promise<Label[]> {
|
||||
console.log('Fetching labels from server')
|
||||
return Promise.resolve(this.labels)
|
||||
console.log('Fetching labels from server');
|
||||
return Promise.resolve(this.labels);
|
||||
}
|
||||
|
||||
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
||||
const mapInfo = this.maps.find((m) => m.id == id)
|
||||
const mapInfo = this.maps.find((m) => m.id == id);
|
||||
if (mapInfo) {
|
||||
mapInfo.isPublic = isPublic
|
||||
mapInfo.isPublic = isPublic;
|
||||
}
|
||||
return Promise.resolve()
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
updateStarred(id: number, starred: boolean): Promise<void> {
|
||||
const mapInfo = this.maps.find((m) => m.id == id)
|
||||
const mapInfo = this.maps.find((m) => m.id == id);
|
||||
if (!mapInfo) {
|
||||
console.log(`Could not find the map iwth id ${id}`)
|
||||
return Promise.reject()
|
||||
console.log(`Could not find the map iwth id ${id}`);
|
||||
return Promise.reject();
|
||||
}
|
||||
mapInfo.starred = starred
|
||||
return Promise.resolve()
|
||||
mapInfo.starred = starred;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
|
||||
const exists = this.maps.find((m) => m.title == basicInfo.title) != undefined
|
||||
const exists = this.maps.find((m) => m.title == basicInfo.title) != undefined;
|
||||
if (!exists) {
|
||||
this.maps = this.maps.map((m) => {
|
||||
const result = m
|
||||
const result = m;
|
||||
if (m.id == id) {
|
||||
result.description = basicInfo.description ? basicInfo.description : ''
|
||||
result.title = basicInfo.title
|
||||
result.description = basicInfo.description ? basicInfo.description : '';
|
||||
result.title = basicInfo.title;
|
||||
}
|
||||
return result
|
||||
})
|
||||
return Promise.resolve()
|
||||
return result;
|
||||
});
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
const fieldErrors: Map<string, string> = new Map<string, string>()
|
||||
fieldErrors.set('name', 'name already exists ')
|
||||
const fieldErrors: Map<string, string> = new Map<string, string>();
|
||||
fieldErrors.set('name', 'name already exists ');
|
||||
|
||||
return Promise.reject({
|
||||
msg: 'Map already exists ...' + basicInfo.title,
|
||||
fields: fieldErrors,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
fetchHistory(id: number): Promise<ChangeHistory[]> {
|
||||
console.log(`Fetching history for ${id}`)
|
||||
console.log(`Fetching history for ${id}`);
|
||||
const result = [
|
||||
{
|
||||
id: 1,
|
||||
@ -264,12 +264,12 @@ class MockClient implements Client {
|
||||
lastModificationBy: 'Paulo',
|
||||
lastModificationTime: '2008-06-02T00:00:00Z',
|
||||
},
|
||||
]
|
||||
return Promise.resolve(result)
|
||||
];
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
||||
const exists = this.maps.find((m) => m.title == basicInfo.title) != undefined
|
||||
const exists = this.maps.find((m) => m.title == basicInfo.title) != undefined;
|
||||
if (!exists) {
|
||||
const newMap: MapInfo = {
|
||||
id: Math.random() * 1000,
|
||||
@ -283,45 +283,45 @@ class MockClient implements Client {
|
||||
creationTime: '2008-06-02T00:00:00Z',
|
||||
isPublic: false,
|
||||
role: 'owner',
|
||||
}
|
||||
this.maps.push(newMap)
|
||||
return Promise.resolve(newMap.id)
|
||||
};
|
||||
this.maps.push(newMap);
|
||||
return Promise.resolve(newMap.id);
|
||||
} else {
|
||||
const fieldErrors: Map<string, string> = new Map<string, string>()
|
||||
fieldErrors.set('name', 'name already exists ')
|
||||
const fieldErrors: Map<string, string> = new Map<string, string>();
|
||||
fieldErrors.set('name', 'name already exists ');
|
||||
|
||||
return Promise.reject({
|
||||
msg: 'Maps name must be unique:' + basicInfo.title,
|
||||
fields: fieldErrors,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
deleteLabel(id: number): Promise<void> {
|
||||
this.labels = this.labels.filter((l) => l.id != id)
|
||||
console.log('Label delete:' + this.labels)
|
||||
return Promise.resolve()
|
||||
this.labels = this.labels.filter((l) => l.id != id);
|
||||
console.log('Label delete:' + this.labels);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
deleteMap(id: number): Promise<void> {
|
||||
this.maps = this.maps.filter((m) => m.id != id)
|
||||
return Promise.resolve()
|
||||
this.maps = this.maps.filter((m) => m.id != id);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
registerNewUser(user: NewUser): Promise<void> {
|
||||
console.log('user:' + user)
|
||||
return Promise.resolve()
|
||||
console.log('user:' + user);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
fetchAllMaps(): Promise<MapInfo[]> {
|
||||
console.log('Fetching maps from server')
|
||||
return Promise.resolve(this.maps)
|
||||
console.log('Fetching maps from server');
|
||||
return Promise.resolve(this.maps);
|
||||
}
|
||||
|
||||
resetPassword(email: string): Promise<void> {
|
||||
console.log('email:' + email)
|
||||
return Promise.resolve()
|
||||
console.log('email:' + email);
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
export default MockClient
|
||||
export default MockClient;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import axios from 'axios'
|
||||
import axios from 'axios';
|
||||
import Client, {
|
||||
ErrorInfo,
|
||||
MapInfo,
|
||||
@ -9,16 +9,16 @@ import Client, {
|
||||
AccountInfo,
|
||||
ImportMapInfo,
|
||||
Permission,
|
||||
} from '..'
|
||||
import { LocaleCode, localeFromStr, Locales } from '../../app-i18n'
|
||||
} from '..';
|
||||
import { LocaleCode, localeFromStr, Locales } from '../../app-i18n';
|
||||
|
||||
export default class RestClient implements Client {
|
||||
private baseUrl: string
|
||||
private sessionExpired: () => void
|
||||
private baseUrl: string;
|
||||
private sessionExpired: () => void;
|
||||
|
||||
constructor(baseUrl: string, sessionExpired: () => void) {
|
||||
this.baseUrl = baseUrl
|
||||
this.sessionExpired = sessionExpired
|
||||
this.baseUrl = baseUrl;
|
||||
this.sessionExpired = sessionExpired;
|
||||
}
|
||||
|
||||
deleteMapPermission(id: number, email: string): Promise<void> {
|
||||
@ -28,14 +28,14 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
|
||||
@ -51,14 +51,14 @@ export default class RestClient implements Client {
|
||||
)
|
||||
.then(() => {
|
||||
// All was ok, let's sent to success page ...;
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
fetchMapPermissions(id: number): Promise<Permission[]> {
|
||||
@ -71,7 +71,7 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then((response) => {
|
||||
const data = response.data
|
||||
const data = response.data;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const perms: Permission[] = (data.collaborations as any[]).map((p) => {
|
||||
return {
|
||||
@ -79,16 +79,16 @@ export default class RestClient implements Client {
|
||||
email: p.email,
|
||||
name: p.name,
|
||||
role: p.role,
|
||||
}
|
||||
})
|
||||
success(perms)
|
||||
};
|
||||
});
|
||||
success(perms);
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
deleteAccount(): Promise<void> {
|
||||
@ -98,14 +98,14 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
updateAccountInfo(firstname: string, lastname: string): Promise<void> {
|
||||
@ -117,18 +117,18 @@ export default class RestClient implements Client {
|
||||
.then(() => {
|
||||
return axios.put(`${this.baseUrl}/c/restful/account/lastname`, lastname, {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
// All was ok, let's sent to success page ...;
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
updateAccountPassword(pasword: string): Promise<void> {
|
||||
@ -138,14 +138,14 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
updateAccountLanguage(locale: LocaleCode): Promise<void> {
|
||||
@ -156,14 +156,14 @@ export default class RestClient implements Client {
|
||||
})
|
||||
.then(() => {
|
||||
// All was ok, let's sent to success page ...;
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
importMap(model: ImportMapInfo): Promise<number> {
|
||||
@ -177,15 +177,15 @@ export default class RestClient implements Client {
|
||||
{ headers: { 'Content-Type': model.contentType } }
|
||||
)
|
||||
.then((response) => {
|
||||
const mapId = response.headers.resourceid
|
||||
success(mapId)
|
||||
const mapId = response.headers.resourceid;
|
||||
success(mapId);
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
fetchAccountInfo(): Promise<AccountInfo> {
|
||||
@ -198,21 +198,21 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
const account = response.data
|
||||
const locale: LocaleCode | null = account.locale
|
||||
const account = response.data;
|
||||
const locale: LocaleCode | null = account.locale;
|
||||
success({
|
||||
lastname: account.lastname ? account.lastname : '',
|
||||
firstname: account.firstname ? account.firstname : '',
|
||||
email: account.email,
|
||||
locale: locale ? localeFromStr(locale) : Locales.EN,
|
||||
})
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
deleteMaps(ids: number[]): Promise<void> {
|
||||
@ -222,15 +222,15 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const response = error.response
|
||||
const errorInfo = this.parseResponseOnError(response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const response = error.response;
|
||||
const errorInfo = this.parseResponseOnError(response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
||||
@ -241,14 +241,14 @@ export default class RestClient implements Client {
|
||||
})
|
||||
.then(() => {
|
||||
// All was ok, let's sent to success page ...;
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
revertHistory(id: number, hid: number): Promise<void> {
|
||||
@ -258,18 +258,18 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'text/pain' },
|
||||
})
|
||||
.then(() => {
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
fetchHistory(id: number): Promise<ChangeHistory[]> {
|
||||
throw new Error(`Method not implemented. ${id}`)
|
||||
throw new Error(`Method not implemented. ${id}`);
|
||||
}
|
||||
|
||||
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void> {
|
||||
@ -283,19 +283,19 @@ export default class RestClient implements Client {
|
||||
`${this.baseUrl}/c/restful/maps/${id}/description`,
|
||||
basicInfo.description,
|
||||
{ headers: { 'Content-Type': 'text/plain' } }
|
||||
)
|
||||
);
|
||||
})
|
||||
.then(() => {
|
||||
// All was ok, let's sent to success page ...;
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const response = error.response
|
||||
const errorInfo = this.parseResponseOnError(response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const response = error.response;
|
||||
const errorInfo = this.parseResponseOnError(response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
createMap(model: BasicMapInfo): Promise<number> {
|
||||
@ -309,15 +309,15 @@ export default class RestClient implements Client {
|
||||
{ headers: { 'Content-Type': 'application/json' } }
|
||||
)
|
||||
.then((response) => {
|
||||
const mapId = response.headers.resourceid
|
||||
success(mapId)
|
||||
const mapId = response.headers.resourceid;
|
||||
success(mapId);
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
fetchAllMaps(): Promise<MapInfo[]> {
|
||||
@ -330,7 +330,7 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
const data = response.data
|
||||
const data = response.data;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const maps: MapInfo[] = (data.mindmapsInfo as any[]).map((m) => {
|
||||
return {
|
||||
@ -345,20 +345,20 @@ export default class RestClient implements Client {
|
||||
description: m.description,
|
||||
isPublic: m['public'],
|
||||
role: m.role,
|
||||
}
|
||||
})
|
||||
success(maps)
|
||||
};
|
||||
});
|
||||
success(maps);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('Maps List Error=>')
|
||||
console.log(error)
|
||||
console.log('Maps List Error=>');
|
||||
console.log(error);
|
||||
|
||||
const response = error.response
|
||||
const errorInfo = this.parseResponseOnError(response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const response = error.response;
|
||||
const errorInfo = this.parseResponseOnError(response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
registerNewUser(user: NewUser): Promise<void> {
|
||||
@ -369,16 +369,16 @@ export default class RestClient implements Client {
|
||||
})
|
||||
.then(() => {
|
||||
// All was ok, let's sent to success page ...;
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error)
|
||||
const response = error.response
|
||||
const errorInfo = this.parseResponseOnError(response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
console.log(error);
|
||||
const response = error.response;
|
||||
const errorInfo = this.parseResponseOnError(response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
deleteMap(id: number): Promise<void> {
|
||||
@ -388,14 +388,14 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then(() => {
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
resetPassword(email: string): Promise<void> {
|
||||
@ -406,15 +406,15 @@ export default class RestClient implements Client {
|
||||
})
|
||||
.then(() => {
|
||||
// All was ok, let's sent to success page ...;
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const response = error.response
|
||||
const errorInfo = this.parseResponseOnError(response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const response = error.response;
|
||||
const errorInfo = this.parseResponseOnError(response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
||||
@ -424,16 +424,16 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
const mapId = response.headers.resourceid
|
||||
success(mapId)
|
||||
const mapId = response.headers.resourceid;
|
||||
success(mapId);
|
||||
})
|
||||
.catch((error) => {
|
||||
const response = error.response
|
||||
const errorInfo = this.parseResponseOnError(response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const response = error.response;
|
||||
const errorInfo = this.parseResponseOnError(response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
updateStarred(id: number, starred: boolean): Promise<void> {
|
||||
@ -443,15 +443,15 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
})
|
||||
.then(() => {
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const response = error.response
|
||||
const errorInfo = this.parseResponseOnError(response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const response = error.response;
|
||||
const errorInfo = this.parseResponseOnError(response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
fetchLabels(): Promise<Label[]> {
|
||||
@ -464,7 +464,7 @@ export default class RestClient implements Client {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
.then((response) => {
|
||||
const data = response.data
|
||||
const data = response.data;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const maps: Label[] = (data.labels as any[]).map((l) => {
|
||||
return {
|
||||
@ -472,16 +472,16 @@ export default class RestClient implements Client {
|
||||
color: l.color,
|
||||
title: l.title,
|
||||
iconName: l.iconName,
|
||||
}
|
||||
})
|
||||
success(maps)
|
||||
};
|
||||
});
|
||||
success(maps);
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
deleteLabel(id: number): Promise<void> {
|
||||
@ -489,60 +489,60 @@ export default class RestClient implements Client {
|
||||
axios
|
||||
.delete(`${this.baseUrl}/c/restful/label/${id}`)
|
||||
.then(() => {
|
||||
success()
|
||||
success();
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorInfo = this.parseResponseOnError(error.response)
|
||||
reject(errorInfo)
|
||||
})
|
||||
}
|
||||
return new Promise(handler)
|
||||
const errorInfo = this.parseResponseOnError(error.response);
|
||||
reject(errorInfo);
|
||||
});
|
||||
};
|
||||
return new Promise(handler);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private parseResponseOnError = (response: any): ErrorInfo => {
|
||||
let result: ErrorInfo | undefined
|
||||
let result: ErrorInfo | undefined;
|
||||
if (response) {
|
||||
const status: number = response.status
|
||||
const data = response.data
|
||||
console.log(data)
|
||||
const status: number = response.status;
|
||||
const data = response.data;
|
||||
console.log(data);
|
||||
|
||||
switch (status) {
|
||||
case 401:
|
||||
case 302:
|
||||
this.sessionExpired()
|
||||
this.sessionExpired();
|
||||
result = {
|
||||
msg: 'Your current session has expired. Please, sign in and try again.',
|
||||
}
|
||||
break
|
||||
};
|
||||
break;
|
||||
default:
|
||||
if (data) {
|
||||
// Set global errors ...
|
||||
result = {}
|
||||
const globalErrors = data.globalErrors
|
||||
result = {};
|
||||
const globalErrors = data.globalErrors;
|
||||
if (globalErrors && globalErrors.length > 0) {
|
||||
result.msg = globalErrors[0]
|
||||
result.msg = globalErrors[0];
|
||||
}
|
||||
|
||||
// Set field errors ...
|
||||
if (data.fieldErrors && Object.keys(data.fieldErrors).length > 0) {
|
||||
result.fields = data.fieldErrors
|
||||
result.fields = data.fieldErrors;
|
||||
if (!result.msg) {
|
||||
const key = Object.keys(data.fieldErrors)[0]
|
||||
result.msg = data.fieldErrors[key]
|
||||
const key = Object.keys(data.fieldErrors)[0];
|
||||
result.msg = data.fieldErrors[key];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = { msg: response.statusText }
|
||||
result = { msg: response.statusText };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Network related problem ...
|
||||
if (!result) {
|
||||
result = { msg: 'Unexpected error. Please, try latter' }
|
||||
result = { msg: 'Unexpected error. Please, try latter' };
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
@ -1,41 +1,41 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import Client, { ErrorInfo } from '../../classes/client'
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import Client, { ErrorInfo } from '../../classes/client';
|
||||
|
||||
import Header from '../layout/header'
|
||||
import Footer from '../layout/footer'
|
||||
import FormContainer from '../layout/form-container'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { useMutation } from 'react-query'
|
||||
import { activeInstance } from '../../redux/clientSlice'
|
||||
import Input from '../form/input'
|
||||
import GlobalError from '../form/global-error'
|
||||
import SubmitButton from '../form/submit-button'
|
||||
import Header from '../layout/header';
|
||||
import Footer from '../layout/footer';
|
||||
import FormContainer from '../layout/form-container';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useMutation } from 'react-query';
|
||||
import { activeInstance } from '../../redux/clientSlice';
|
||||
import Input from '../form/input';
|
||||
import GlobalError from '../form/global-error';
|
||||
import SubmitButton from '../form/submit-button';
|
||||
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
||||
const ForgotPassword = () => {
|
||||
const [email, setEmail] = useState<string>('')
|
||||
const [error, setError] = useState<ErrorInfo>()
|
||||
const history = useHistory()
|
||||
const intl = useIntl()
|
||||
const [email, setEmail] = useState<string>('');
|
||||
const [error, setError] = useState<ErrorInfo>();
|
||||
const history = useHistory();
|
||||
const intl = useIntl();
|
||||
|
||||
const service: Client = useSelector(activeInstance)
|
||||
const service: Client = useSelector(activeInstance);
|
||||
const mutation = useMutation<void, ErrorInfo, string>(
|
||||
(email: string) => service.resetPassword(email),
|
||||
{
|
||||
onSuccess: () => history.push('/c/forgot-password-success'),
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
mutation.mutate(email)
|
||||
}
|
||||
event.preventDefault();
|
||||
mutation.mutate(email);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormContainer>
|
||||
@ -70,13 +70,13 @@ const ForgotPassword = () => {
|
||||
/>
|
||||
</form>
|
||||
</FormContainer>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const ForgotPasswordPage = (): React.ReactElement => {
|
||||
useEffect(() => {
|
||||
document.title = 'Reset Password | WiseMapping'
|
||||
})
|
||||
document.title = 'Reset Password | WiseMapping';
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -84,7 +84,7 @@ const ForgotPasswordPage = (): React.ReactElement => {
|
||||
<ForgotPassword />
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export { ForgotPasswordPage }
|
||||
export { ForgotPasswordPage };
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import FormContainer from '../layout/form-container'
|
||||
import Header from '../layout/header'
|
||||
import Footer from '../layout/footer'
|
||||
import { Link as RouterLink } from 'react-router-dom'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import FormContainer from '../layout/form-container';
|
||||
import Header from '../layout/header';
|
||||
import Footer from '../layout/footer';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
const ForgotPasswordSuccessPage = (): React.ReactElement => {
|
||||
useEffect(() => {
|
||||
document.title = 'Reset Password | WiseMapping'
|
||||
})
|
||||
document.title = 'Reset Password | WiseMapping';
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -43,7 +43,7 @@ const ForgotPasswordSuccessPage = (): React.ReactElement => {
|
||||
</FormContainer>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ForgotPasswordSuccessPage
|
||||
export default ForgotPasswordSuccessPage;
|
||||
|
@ -1,22 +1,22 @@
|
||||
import React from 'react'
|
||||
import { ErrorInfo } from '../../../classes/client'
|
||||
import StyledAlert from './styled'
|
||||
import React from 'react';
|
||||
import { ErrorInfo } from '../../../classes/client';
|
||||
import StyledAlert from './styled';
|
||||
|
||||
type GlobalErrorProps = {
|
||||
error?: ErrorInfo
|
||||
}
|
||||
error?: ErrorInfo;
|
||||
};
|
||||
|
||||
const GlobalError = (props: GlobalErrorProps): React.ReactElement | null => {
|
||||
const error = props.error
|
||||
const hasError = Boolean(error?.msg)
|
||||
const errorMsg = error?.msg
|
||||
const error = props.error;
|
||||
const hasError = Boolean(error?.msg);
|
||||
const errorMsg = error?.msg;
|
||||
|
||||
return hasError ? (
|
||||
<StyledAlert severity="error" variant="filled" hidden={!hasError}>
|
||||
{' '}
|
||||
{errorMsg}
|
||||
</StyledAlert>
|
||||
) : null
|
||||
}
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default GlobalError
|
||||
export default GlobalError;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import withStyles from '@material-ui/core/styles/withStyles'
|
||||
import Alert from '@material-ui/lab/Alert'
|
||||
import withStyles from '@material-ui/core/styles/withStyles';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
|
||||
export const StyledAlert = withStyles({
|
||||
root: {
|
||||
padding: '10px 15px',
|
||||
margin: '5px 0px ',
|
||||
},
|
||||
})(Alert)
|
||||
})(Alert);
|
||||
|
||||
export default StyledAlert
|
||||
export default StyledAlert;
|
||||
|
@ -1,19 +1,19 @@
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import React, { ChangeEvent } from 'react'
|
||||
import { ErrorInfo } from '../../../classes/client'
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import React, { ChangeEvent } from 'react';
|
||||
import { ErrorInfo } from '../../../classes/client';
|
||||
|
||||
type InputProps = {
|
||||
name: string
|
||||
error?: ErrorInfo
|
||||
onChange?: (event: ChangeEvent<HTMLInputElement>) => void
|
||||
label: string
|
||||
required?: boolean
|
||||
type: string
|
||||
value?: string
|
||||
autoComplete?: string
|
||||
fullWidth?: boolean
|
||||
disabled?: boolean
|
||||
}
|
||||
name: string;
|
||||
error?: ErrorInfo;
|
||||
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
|
||||
label: string;
|
||||
required?: boolean;
|
||||
type: string;
|
||||
value?: string;
|
||||
autoComplete?: string;
|
||||
fullWidth?: boolean;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const Input = ({
|
||||
name,
|
||||
@ -27,7 +27,7 @@ const Input = ({
|
||||
fullWidth = true,
|
||||
disabled = false,
|
||||
}: InputProps): React.ReactElement => {
|
||||
const fieldError = error?.fields?.[name]
|
||||
const fieldError = error?.fields?.[name];
|
||||
return (
|
||||
<TextField
|
||||
name={name}
|
||||
@ -44,6 +44,6 @@ const Input = ({
|
||||
disabled={disabled}
|
||||
autoComplete={autoComplete}
|
||||
/>
|
||||
)
|
||||
}
|
||||
export default Input
|
||||
);
|
||||
};
|
||||
export default Input;
|
||||
|
@ -1,20 +1,20 @@
|
||||
import Button from '@material-ui/core/Button'
|
||||
import React, { useState } from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
import Button from '@material-ui/core/Button';
|
||||
import React, { useState } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
type SubmitButton = {
|
||||
value: string
|
||||
disabled?: boolean
|
||||
}
|
||||
value: string;
|
||||
disabled?: boolean;
|
||||
};
|
||||
const SubmitButton = (props: SubmitButton): React.ReactElement => {
|
||||
const [disabled] = useState(props.disabled ? true : false)
|
||||
const intl = useIntl()
|
||||
const [disabled] = useState(props.disabled ? true : false);
|
||||
const intl = useIntl();
|
||||
|
||||
let valueTxt = props.value
|
||||
let valueTxt = props.value;
|
||||
if (disabled) {
|
||||
valueTxt = intl.formatMessage({ id: 'common.wait', defaultMessage: 'Please wait ...' })
|
||||
valueTxt = intl.formatMessage({ id: 'common.wait', defaultMessage: 'Please wait ...' });
|
||||
}
|
||||
const [value] = useState(valueTxt)
|
||||
const [value] = useState(valueTxt);
|
||||
return (
|
||||
<Button
|
||||
color="primary"
|
||||
@ -33,7 +33,7 @@ const SubmitButton = (props: SubmitButton): React.ReactElement => {
|
||||
>
|
||||
{value}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default SubmitButton
|
||||
export default SubmitButton;
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React from 'react'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { StyledFooter } from './styled'
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { StyledFooter } from './styled';
|
||||
|
||||
// FIXME: use SVG loader
|
||||
// eslint-disable-next-line
|
||||
const poweredByIcon = require('../../../images/pwrdby-white.svg')
|
||||
const poweredByIcon = require('../../../images/pwrdby-white.svg');
|
||||
|
||||
const Footer = (): React.ReactElement => {
|
||||
return (
|
||||
@ -67,7 +67,7 @@ const Footer = (): React.ReactElement => {
|
||||
</div>
|
||||
</div>
|
||||
</StyledFooter>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer
|
||||
export default Footer;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import styled from 'styled-components'
|
||||
import styled from 'styled-components';
|
||||
/* Footer */
|
||||
|
||||
export const StyledFooter = styled.footer`
|
||||
@ -41,4 +41,4 @@ export const StyledFooter = styled.footer`
|
||||
display: inline-block;
|
||||
visibility: visible;
|
||||
}
|
||||
`
|
||||
`;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Container from '@material-ui/core/Container'
|
||||
import withStyles from '@material-ui/core/styles/withStyles'
|
||||
import Container from '@material-ui/core/Container';
|
||||
import withStyles from '@material-ui/core/styles/withStyles';
|
||||
|
||||
const FormContainer = withStyles({
|
||||
root: {
|
||||
@ -7,6 +7,6 @@ const FormContainer = withStyles({
|
||||
maxWidth: '380px',
|
||||
textAlign: 'center',
|
||||
},
|
||||
})(Container)
|
||||
})(Container);
|
||||
|
||||
export default FormContainer
|
||||
export default FormContainer;
|
||||
|
@ -1,20 +1,20 @@
|
||||
import { StyledNav, StyledDiv, Logo } from './styled'
|
||||
import { StyledNav, StyledDiv, Logo } from './styled';
|
||||
|
||||
import React from 'react'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
import logo from '../../../images/logo-small.svg'
|
||||
import logo from '../../../images/logo-small.svg';
|
||||
|
||||
interface HeaderProps {
|
||||
type: 'only-signup' | 'only-signin' | 'none'
|
||||
type: 'only-signup' | 'only-signin' | 'none';
|
||||
}
|
||||
|
||||
export const Header = ({ type }: HeaderProps): React.ReactElement => {
|
||||
let signUpButton
|
||||
let text
|
||||
let signInButton
|
||||
let signUpButton;
|
||||
let text;
|
||||
let signInButton;
|
||||
if (type === 'only-signup') {
|
||||
text = (
|
||||
<span className="header-area-content-span">
|
||||
@ -25,8 +25,8 @@ export const Header = ({ type }: HeaderProps): React.ReactElement => {
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
signUpButton = <SignUpButton className="header-area-right2" />
|
||||
);
|
||||
signUpButton = <SignUpButton className="header-area-right2" />;
|
||||
} else if (type === 'only-signin') {
|
||||
text = (
|
||||
<span className="header-area-content-span">
|
||||
@ -37,14 +37,14 @@ export const Header = ({ type }: HeaderProps): React.ReactElement => {
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
signUpButton = <SignInButton className="header-area-right2" />
|
||||
);
|
||||
signUpButton = <SignInButton className="header-area-right2" />;
|
||||
} else if (type === 'none') {
|
||||
text = ''
|
||||
signUpButton = ''
|
||||
text = '';
|
||||
signUpButton = '';
|
||||
} else {
|
||||
signUpButton = <SignUpButton className="header-area-right2" />
|
||||
signInButton = <SignInButton className="header-area-right2" />
|
||||
signUpButton = <SignUpButton className="header-area-right2" />;
|
||||
signInButton = <SignInButton className="header-area-right2" />;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -60,11 +60,11 @@ export const Header = ({ type }: HeaderProps): React.ReactElement => {
|
||||
{signInButton}
|
||||
</StyledDiv>
|
||||
</StyledNav>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
interface ButtonProps {
|
||||
className?: string
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const SignInButton = (props: ButtonProps): React.ReactElement => {
|
||||
@ -74,8 +74,8 @@ export const SignInButton = (props: ButtonProps): React.ReactElement => {
|
||||
<FormattedMessage id="login.signin" defaultMessage="Sign In" />
|
||||
</Button>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const SignUpButton = (props: ButtonProps): React.ReactElement => {
|
||||
return (
|
||||
@ -90,7 +90,7 @@ const SignUpButton = (props: ButtonProps): React.ReactElement => {
|
||||
<FormattedMessage id="login.signup" defaultMessage="Sign Up" />
|
||||
</Button>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default Header
|
||||
export default Header;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import styled from 'styled-components'
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const StyledNav = styled.nav`
|
||||
height: 90px;
|
||||
@ -50,7 +50,7 @@ export const StyledNav = styled.nav`
|
||||
font-size: 14px;
|
||||
padding: 10px;
|
||||
}
|
||||
`
|
||||
`;
|
||||
|
||||
export const StyledDiv = styled.nav`
|
||||
background: white;
|
||||
@ -64,7 +64,7 @@ export const StyledDiv = styled.nav`
|
||||
display: grid;
|
||||
white-space: nowrap;
|
||||
grid-template-columns: 150px 1fr 130px 160px 50px;
|
||||
`
|
||||
`;
|
||||
|
||||
export const Logo = styled.span`
|
||||
grid-column-start: 1;
|
||||
@ -74,4 +74,4 @@ export const Logo = styled.span`
|
||||
.header-logo a {
|
||||
padding: 0px;
|
||||
}
|
||||
`
|
||||
`;
|
||||
|
@ -1,22 +1,22 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { Link as RouterLink } from 'react-router-dom'
|
||||
import Header from '../layout/header'
|
||||
import Footer from '../layout/footer'
|
||||
import SubmitButton from '../form/submit-button'
|
||||
import Input from '../form/input'
|
||||
import GlobalError from '../form/global-error'
|
||||
import FormContainer from '../layout/form-container'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import Link from '@material-ui/core/Link'
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import Header from '../layout/header';
|
||||
import Footer from '../layout/footer';
|
||||
import SubmitButton from '../form/submit-button';
|
||||
import Input from '../form/input';
|
||||
import GlobalError from '../form/global-error';
|
||||
import FormContainer from '../layout/form-container';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import Link from '@material-ui/core/Link';
|
||||
|
||||
type ConfigStatusProps = {
|
||||
enabled?: boolean
|
||||
}
|
||||
enabled?: boolean;
|
||||
};
|
||||
|
||||
const ConfigStatusMessage = ({ enabled = false }: ConfigStatusProps): React.ReactElement => {
|
||||
let result
|
||||
let result;
|
||||
if (enabled === true) {
|
||||
result = (
|
||||
<div className="db-warn-msg">
|
||||
@ -32,18 +32,18 @@ const ConfigStatusMessage = ({ enabled = false }: ConfigStatusProps): React.Reac
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
return result || null
|
||||
}
|
||||
return result || null;
|
||||
};
|
||||
|
||||
const LoginError = () => {
|
||||
// @Todo: This must be reviewed to be based on navigation state.
|
||||
// Login error example: http://localhost:8080/c/login?login.error=2
|
||||
const errorCode = new URLSearchParams(window.location.search).get('login_error')
|
||||
const intl = useIntl()
|
||||
const errorCode = new URLSearchParams(window.location.search).get('login_error');
|
||||
const intl = useIntl();
|
||||
|
||||
let msg: null | string = null
|
||||
let msg: null | string = null;
|
||||
if (errorCode) {
|
||||
switch (errorCode) {
|
||||
case '3':
|
||||
@ -51,24 +51,24 @@ const LoginError = () => {
|
||||
id: 'login.userinactive',
|
||||
defaultMessage:
|
||||
"Sorry, your account has not been activated yet. You'll receive a notification email when it becomes active. Stay tuned!.",
|
||||
})
|
||||
break
|
||||
});
|
||||
break;
|
||||
default:
|
||||
msg = intl.formatMessage({
|
||||
id: 'login.error',
|
||||
defaultMessage: 'The email address or password you entered is not valid.',
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
return msg ? <GlobalError error={{ msg: msg }} /> : null
|
||||
}
|
||||
return msg ? <GlobalError error={{ msg: msg }} /> : null;
|
||||
};
|
||||
|
||||
const LoginPage = (): React.ReactElement => {
|
||||
const intl = useIntl()
|
||||
const intl = useIntl();
|
||||
|
||||
useEffect(() => {
|
||||
document.title = 'Login | WiseMapping'
|
||||
})
|
||||
document.title = 'Login | WiseMapping';
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -133,7 +133,7 @@ const LoginPage = (): React.ReactElement => {
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage
|
||||
export default LoginPage;
|
||||
|
@ -1,105 +1,105 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useMutation, useQueryClient } from 'react-query'
|
||||
import Client, { ErrorInfo } from '../../../../classes/client'
|
||||
import Input from '../../../form/input'
|
||||
import BaseDialog from '../../action-dispatcher/base-dialog'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { activeInstance, fetchAccount } from '../../../../redux/clientSlice'
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useMutation, useQueryClient } from 'react-query';
|
||||
import Client, { ErrorInfo } from '../../../../classes/client';
|
||||
import Input from '../../../form/input';
|
||||
import BaseDialog from '../../action-dispatcher/base-dialog';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { activeInstance, fetchAccount } from '../../../../redux/clientSlice';
|
||||
|
||||
import Alert from '@material-ui/lab/Alert'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
import FormGroup from '@material-ui/core/FormGroup'
|
||||
import Switch from '@material-ui/core/Switch'
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import FormGroup from '@material-ui/core/FormGroup';
|
||||
import Switch from '@material-ui/core/Switch';
|
||||
|
||||
type AccountInfoDialogProps = {
|
||||
onClose: () => void
|
||||
}
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
type AccountInfoModel = {
|
||||
email: string
|
||||
firstname: string
|
||||
lastname: string
|
||||
}
|
||||
email: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
};
|
||||
|
||||
const defaultModel: AccountInfoModel = { firstname: '', lastname: '', email: '' }
|
||||
const defaultModel: AccountInfoModel = { firstname: '', lastname: '', email: '' };
|
||||
const AccountInfoDialog = ({ onClose }: AccountInfoDialogProps): React.ReactElement => {
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const queryClient = useQueryClient()
|
||||
const [remove, setRemove] = React.useState<boolean>(false)
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const queryClient = useQueryClient();
|
||||
const [remove, setRemove] = React.useState<boolean>(false);
|
||||
|
||||
const [model, setModel] = React.useState<AccountInfoModel>(defaultModel)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const intl = useIntl()
|
||||
const [model, setModel] = React.useState<AccountInfoModel>(defaultModel);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
const intl = useIntl();
|
||||
|
||||
const mutationChangeName = useMutation<void, ErrorInfo, AccountInfoModel>(
|
||||
(model: AccountInfoModel) => {
|
||||
return client.updateAccountInfo(model.firstname, model.lastname)
|
||||
return client.updateAccountInfo(model.firstname, model.lastname);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries('account')
|
||||
onClose()
|
||||
queryClient.invalidateQueries('account');
|
||||
onClose();
|
||||
},
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const mutationRemove = useMutation<void, ErrorInfo, void>(
|
||||
() => {
|
||||
return client.deleteAccount()
|
||||
return client.deleteAccount();
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
window.location.href = '/c/logout'
|
||||
onClose()
|
||||
window.location.href = '/c/logout';
|
||||
onClose();
|
||||
},
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const account = fetchAccount()
|
||||
const account = fetchAccount();
|
||||
useEffect(() => {
|
||||
if (account) {
|
||||
setModel({
|
||||
email: account?.email,
|
||||
lastname: account?.lastname,
|
||||
firstname: account?.firstname,
|
||||
})
|
||||
});
|
||||
}
|
||||
}, [account?.email])
|
||||
}, [account?.email]);
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
setModel(defaultModel)
|
||||
setError(undefined)
|
||||
}
|
||||
onClose();
|
||||
setModel(defaultModel);
|
||||
setError(undefined);
|
||||
};
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
if (remove) {
|
||||
mutationRemove.mutate()
|
||||
mutationRemove.mutate();
|
||||
} else {
|
||||
mutationChangeName.mutate(model)
|
||||
mutationChangeName.mutate(model);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name
|
||||
const value = event.target.value
|
||||
setModel({ ...model, [name as keyof AccountInfoModel]: value })
|
||||
}
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof AccountInfoModel]: value });
|
||||
};
|
||||
|
||||
const handleOnRemoveChange = (event) => {
|
||||
setRemove(event.target.checked)
|
||||
}
|
||||
setRemove(event.target.checked);
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseDialog
|
||||
@ -173,6 +173,6 @@ const AccountInfoDialog = ({ onClose }: AccountInfoDialogProps): React.ReactElem
|
||||
</FormGroup>
|
||||
</FormControl>
|
||||
</BaseDialog>
|
||||
)
|
||||
}
|
||||
export default AccountInfoDialog
|
||||
);
|
||||
};
|
||||
export default AccountInfoDialog;
|
||||
|
@ -1,51 +1,51 @@
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import React from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
import { useMutation } from 'react-query'
|
||||
import Client, { ErrorInfo } from '../../../../classes/client'
|
||||
import Input from '../../../form/input'
|
||||
import BaseDialog from '../../action-dispatcher/base-dialog'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { activeInstance } from '../../../../redux/clientSlice'
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useMutation } from 'react-query';
|
||||
import Client, { ErrorInfo } from '../../../../classes/client';
|
||||
import Input from '../../../form/input';
|
||||
import BaseDialog from '../../action-dispatcher/base-dialog';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { activeInstance } from '../../../../redux/clientSlice';
|
||||
|
||||
type ChangePasswordDialogProps = {
|
||||
onClose: () => void
|
||||
}
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
type ChangePasswordModel = {
|
||||
password: string
|
||||
retryPassword: string
|
||||
}
|
||||
password: string;
|
||||
retryPassword: string;
|
||||
};
|
||||
|
||||
const defaultModel: ChangePasswordModel = { password: '', retryPassword: '' }
|
||||
const defaultModel: ChangePasswordModel = { password: '', retryPassword: '' };
|
||||
const ChangePasswordDialog = ({ onClose }: ChangePasswordDialogProps): React.ReactElement => {
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const [model, setModel] = React.useState<ChangePasswordModel>(defaultModel)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const intl = useIntl()
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const [model, setModel] = React.useState<ChangePasswordModel>(defaultModel);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
const intl = useIntl();
|
||||
|
||||
const mutation = useMutation<void, ErrorInfo, ChangePasswordModel>(
|
||||
(model: ChangePasswordModel) => {
|
||||
return client.updateAccountPassword(model.password)
|
||||
return client.updateAccountPassword(model.password);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
onClose()
|
||||
onClose();
|
||||
},
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
setModel(defaultModel)
|
||||
setError(undefined)
|
||||
}
|
||||
onClose();
|
||||
setModel(defaultModel);
|
||||
setError(undefined);
|
||||
};
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
// Check password are equal ...
|
||||
if (model.password != model.retryPassword) {
|
||||
@ -54,20 +54,20 @@ const ChangePasswordDialog = ({ onClose }: ChangePasswordDialogProps): React.Rea
|
||||
id: 'changepwd.password-match',
|
||||
defaultMessage: 'Password do not match. Please, try again.',
|
||||
}),
|
||||
})
|
||||
return
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
mutation.mutate(model)
|
||||
}
|
||||
mutation.mutate(model);
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name
|
||||
const value = event.target.value
|
||||
setModel({ ...model, [name as keyof ChangePasswordModel]: value })
|
||||
}
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof ChangePasswordModel]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseDialog
|
||||
@ -111,6 +111,6 @@ const ChangePasswordDialog = ({ onClose }: ChangePasswordDialogProps): React.Rea
|
||||
/>
|
||||
</FormControl>
|
||||
</BaseDialog>
|
||||
)
|
||||
}
|
||||
export default ChangePasswordDialog
|
||||
);
|
||||
};
|
||||
export default ChangePasswordDialog;
|
||||
|
@ -1,34 +1,34 @@
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||
import Menu from '@material-ui/core/Menu'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import SettingsApplicationsOutlined from '@material-ui/icons/SettingsApplicationsOutlined'
|
||||
import AccountCircle from '@material-ui/icons/AccountCircle'
|
||||
import React from 'react'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { fetchAccount } from '../../../redux/clientSlice'
|
||||
import AccountInfoDialog from './account-info-dialog'
|
||||
import ChangePasswordDialog from './change-password-dialog'
|
||||
import LockOpenOutlined from '@material-ui/icons/LockOpenOutlined'
|
||||
import Link from '@material-ui/core/Link'
|
||||
import ExitToAppOutlined from '@material-ui/icons/ExitToAppOutlined'
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import SettingsApplicationsOutlined from '@material-ui/icons/SettingsApplicationsOutlined';
|
||||
import AccountCircle from '@material-ui/icons/AccountCircle';
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { fetchAccount } from '../../../redux/clientSlice';
|
||||
import AccountInfoDialog from './account-info-dialog';
|
||||
import ChangePasswordDialog from './change-password-dialog';
|
||||
import LockOpenOutlined from '@material-ui/icons/LockOpenOutlined';
|
||||
import Link from '@material-ui/core/Link';
|
||||
import ExitToAppOutlined from '@material-ui/icons/ExitToAppOutlined';
|
||||
|
||||
type ActionType = 'change-password' | 'account-info' | undefined
|
||||
type ActionType = 'change-password' | 'account-info' | undefined;
|
||||
const AccountMenu = (): React.ReactElement => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
|
||||
const open = Boolean(anchorEl)
|
||||
const [action, setAction] = React.useState<ActionType>(undefined)
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const [action, setAction] = React.useState<ActionType>(undefined);
|
||||
|
||||
const handleMenu = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget)
|
||||
}
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null)
|
||||
}
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const account = fetchAccount()
|
||||
const account = fetchAccount();
|
||||
return (
|
||||
<span>
|
||||
<Tooltip
|
||||
@ -57,7 +57,7 @@ const AccountMenu = (): React.ReactElement => {
|
||||
>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleClose(), setAction('account-info')
|
||||
handleClose(), setAction('account-info');
|
||||
}}
|
||||
>
|
||||
<ListItemIcon>
|
||||
@ -68,7 +68,7 @@ const AccountMenu = (): React.ReactElement => {
|
||||
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleClose(), setAction('change-password')
|
||||
handleClose(), setAction('change-password');
|
||||
}}
|
||||
>
|
||||
<ListItemIcon>
|
||||
@ -91,7 +91,7 @@ const AccountMenu = (): React.ReactElement => {
|
||||
)}
|
||||
{action == 'account-info' && <AccountInfoDialog onClose={() => setAction(undefined)} />}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default AccountMenu
|
||||
export default AccountMenu;
|
||||
|
@ -1,21 +1,21 @@
|
||||
import React from 'react'
|
||||
import DescriptionOutlinedIcon from '@material-ui/icons/DescriptionOutlined'
|
||||
import FileCopyOutlinedIcon from '@material-ui/icons/FileCopyOutlined'
|
||||
import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined'
|
||||
import CloudDownloadOutlinedIcon from '@material-ui/icons/CloudDownloadOutlined'
|
||||
import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'
|
||||
import EditOutlinedIcon from '@material-ui/icons/EditOutlined'
|
||||
import PublicOutlinedIcon from '@material-ui/icons/PublicOutlined'
|
||||
import PrintOutlinedIcon from '@material-ui/icons/PrintOutlined'
|
||||
import ShareOutlinedIcon from '@material-ui/icons/ShareOutlined'
|
||||
import LabelOutlined from '@material-ui/icons/LabelOutlined'
|
||||
import React from 'react';
|
||||
import DescriptionOutlinedIcon from '@material-ui/icons/DescriptionOutlined';
|
||||
import FileCopyOutlinedIcon from '@material-ui/icons/FileCopyOutlined';
|
||||
import DeleteOutlinedIcon from '@material-ui/icons/DeleteOutlined';
|
||||
import CloudDownloadOutlinedIcon from '@material-ui/icons/CloudDownloadOutlined';
|
||||
import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';
|
||||
import EditOutlinedIcon from '@material-ui/icons/EditOutlined';
|
||||
import PublicOutlinedIcon from '@material-ui/icons/PublicOutlined';
|
||||
import PrintOutlinedIcon from '@material-ui/icons/PrintOutlined';
|
||||
import ShareOutlinedIcon from '@material-ui/icons/ShareOutlined';
|
||||
import LabelOutlined from '@material-ui/icons/LabelOutlined';
|
||||
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { fetchMapById } from '../../../redux/clientSlice'
|
||||
import Menu from '@material-ui/core/Menu'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||
import Divider from '@material-ui/core/Divider'
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { fetchMapById } from '../../../redux/clientSlice';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
export type ActionType =
|
||||
| 'open'
|
||||
| 'share'
|
||||
@ -31,27 +31,27 @@ export type ActionType =
|
||||
| 'info'
|
||||
| 'publish'
|
||||
| 'history'
|
||||
| undefined
|
||||
| undefined;
|
||||
|
||||
interface ActionProps {
|
||||
onClose: (action: ActionType) => void
|
||||
anchor?: HTMLElement
|
||||
mapId?: number
|
||||
onClose: (action: ActionType) => void;
|
||||
anchor?: HTMLElement;
|
||||
mapId?: number;
|
||||
}
|
||||
|
||||
const ActionChooser = (props: ActionProps): React.ReactElement => {
|
||||
const { anchor, onClose, mapId } = props
|
||||
const { anchor, onClose, mapId } = props;
|
||||
|
||||
const handleOnClose = (
|
||||
action: ActionType
|
||||
): ((event: React.MouseEvent<HTMLLIElement>) => void) => {
|
||||
return (event): void => {
|
||||
event.stopPropagation()
|
||||
onClose(action)
|
||||
}
|
||||
}
|
||||
event.stopPropagation();
|
||||
onClose(action);
|
||||
};
|
||||
};
|
||||
|
||||
const role = mapId ? fetchMapById(mapId)?.map?.role : undefined
|
||||
const role = mapId ? fetchMapById(mapId)?.map?.role : undefined;
|
||||
return (
|
||||
<Menu
|
||||
anchorEl={anchor}
|
||||
@ -149,7 +149,7 @@ const ActionChooser = (props: ActionProps): React.ReactElement => {
|
||||
</MenuItem>
|
||||
)}
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ActionChooser
|
||||
export default ActionChooser;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import withStyles from '@material-ui/core/styles/withStyles'
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import withStyles from '@material-ui/core/styles/withStyles';
|
||||
|
||||
export const StyledMenuItem = withStyles({
|
||||
root: {
|
||||
width: '300px',
|
||||
},
|
||||
})(MenuItem)
|
||||
})(MenuItem);
|
||||
|
@ -1,40 +1,40 @@
|
||||
import React from 'react'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { ErrorInfo } from '../../../../classes/client'
|
||||
import { StyledDialog, StyledDialogActions, StyledDialogContent, StyledDialogTitle } from './style'
|
||||
import GlobalError from '../../../form/global-error'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { PaperProps } from '@material-ui/core/Paper'
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { ErrorInfo } from '../../../../classes/client';
|
||||
import { StyledDialog, StyledDialogActions, StyledDialogContent, StyledDialogTitle } from './style';
|
||||
import GlobalError from '../../../form/global-error';
|
||||
import DialogContentText from '@material-ui/core/DialogContentText';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import { PaperProps } from '@material-ui/core/Paper';
|
||||
|
||||
export type DialogProps = {
|
||||
onClose: () => void
|
||||
onSubmit?: (event: React.FormEvent<HTMLFormElement>) => void
|
||||
children: unknown
|
||||
error?: ErrorInfo
|
||||
onClose: () => void;
|
||||
onSubmit?: (event: React.FormEvent<HTMLFormElement>) => void;
|
||||
children: unknown;
|
||||
error?: ErrorInfo;
|
||||
|
||||
title: string
|
||||
description?: string
|
||||
title: string;
|
||||
description?: string;
|
||||
|
||||
submitButton?: string
|
||||
actionUrl?: string
|
||||
maxWidth?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false
|
||||
PaperProps?: Partial<PaperProps>
|
||||
}
|
||||
submitButton?: string;
|
||||
actionUrl?: string;
|
||||
maxWidth?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false;
|
||||
PaperProps?: Partial<PaperProps>;
|
||||
};
|
||||
|
||||
const BaseDialog = (props: DialogProps): React.ReactElement => {
|
||||
const { onClose, onSubmit, maxWidth = 'sm', PaperProps } = props
|
||||
const { onClose, onSubmit, maxWidth = 'sm', PaperProps } = props;
|
||||
|
||||
const handleOnSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault()
|
||||
e.preventDefault();
|
||||
if (onSubmit) {
|
||||
onSubmit(e)
|
||||
onSubmit(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const description = props.description ? (
|
||||
<DialogContentText>{props.description}</DialogContentText>
|
||||
) : null
|
||||
) : null;
|
||||
return (
|
||||
<div>
|
||||
<StyledDialog
|
||||
@ -79,7 +79,7 @@ const BaseDialog = (props: DialogProps): React.ReactElement => {
|
||||
</form>
|
||||
</StyledDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default BaseDialog
|
||||
export default BaseDialog;
|
||||
|
@ -1,29 +1,29 @@
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import withStyles from '@material-ui/core/styles/withStyles'
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import withStyles from '@material-ui/core/styles/withStyles';
|
||||
|
||||
export const StyledDialogContent = withStyles({
|
||||
root: {
|
||||
padding: '0px 39px',
|
||||
},
|
||||
})(DialogContent)
|
||||
})(DialogContent);
|
||||
|
||||
export const StyledDialogTitle = withStyles({
|
||||
root: {
|
||||
padding: '39px 39px 10px 39px',
|
||||
},
|
||||
})(DialogTitle)
|
||||
})(DialogTitle);
|
||||
|
||||
export const StyledDialogActions = withStyles({
|
||||
root: {
|
||||
padding: '39px 39px 39px 39px',
|
||||
},
|
||||
})(DialogActions)
|
||||
})(DialogActions);
|
||||
|
||||
export const StyledDialog = withStyles({
|
||||
root: {
|
||||
borderRadius: '9px',
|
||||
},
|
||||
})(Dialog)
|
||||
})(Dialog);
|
||||
|
@ -1,62 +1,62 @@
|
||||
import React from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
import { useMutation } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useMutation } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
|
||||
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client'
|
||||
import { activeInstance } from '../../../../redux/clientSlice'
|
||||
import Input from '../../../form/input'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
|
||||
import { activeInstance } from '../../../../redux/clientSlice';
|
||||
import Input from '../../../form/input';
|
||||
import BaseDialog from '../base-dialog';
|
||||
|
||||
export type CreateModel = {
|
||||
title: string
|
||||
description?: string
|
||||
}
|
||||
title: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export type CreateProps = {
|
||||
onClose: () => void
|
||||
}
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const defaultModel: CreateModel = { title: '', description: '' }
|
||||
const defaultModel: CreateModel = { title: '', description: '' };
|
||||
const CreateDialog = ({ onClose }: CreateProps): React.ReactElement => {
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const [model, setModel] = React.useState<CreateModel>(defaultModel)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const intl = useIntl()
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const [model, setModel] = React.useState<CreateModel>(defaultModel);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
const intl = useIntl();
|
||||
|
||||
const mutation = useMutation<number, ErrorInfo, CreateModel>(
|
||||
(model: CreateModel) => {
|
||||
return client.createMap(model)
|
||||
return client.createMap(model);
|
||||
},
|
||||
{
|
||||
onSuccess: (mapId: number) => {
|
||||
window.location.href = `/c/maps/${mapId}/edit`
|
||||
window.location.href = `/c/maps/${mapId}/edit`;
|
||||
},
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
setModel(defaultModel)
|
||||
setError(undefined)
|
||||
}
|
||||
onClose();
|
||||
setModel(defaultModel);
|
||||
setError(undefined);
|
||||
};
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
event.preventDefault()
|
||||
mutation.mutate(model)
|
||||
}
|
||||
event.preventDefault();
|
||||
mutation.mutate(model);
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name
|
||||
const value = event.target.value
|
||||
setModel({ ...model, [name as keyof BasicMapInfo]: value })
|
||||
}
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -103,7 +103,7 @@ const CreateDialog = ({ onClose }: CreateProps): React.ReactElement => {
|
||||
</FormControl>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateDialog
|
||||
export default CreateDialog;
|
||||
|
@ -1,38 +1,38 @@
|
||||
import React from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useMutation, useQueryClient } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Client, { ErrorInfo } from '../../../../classes/client'
|
||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice'
|
||||
import { SimpleDialogProps, handleOnMutationSuccess } from '..'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import Alert from '@material-ui/lab/Alert'
|
||||
import AlertTitle from '@material-ui/lab/AlertTitle'
|
||||
import React from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useMutation, useQueryClient } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client, { ErrorInfo } from '../../../../classes/client';
|
||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice';
|
||||
import { SimpleDialogProps, handleOnMutationSuccess } from '..';
|
||||
import BaseDialog from '../base-dialog';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import AlertTitle from '@material-ui/lab/AlertTitle';
|
||||
|
||||
const DeleteDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const intl = useIntl()
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const queryClient = useQueryClient()
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const intl = useIntl();
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const queryClient = useQueryClient();
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
|
||||
const mutation = useMutation((id: number) => client.deleteMap(id), {
|
||||
onSuccess: () => handleOnMutationSuccess(onClose, queryClient),
|
||||
onError: (error: ErrorInfo) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleOnSubmit = (): void => {
|
||||
mutation.mutate(mapId)
|
||||
}
|
||||
mutation.mutate(mapId);
|
||||
};
|
||||
|
||||
// Fetch map model to be rendered ...
|
||||
const { map } = fetchMapById(mapId)
|
||||
const alertTitle = `Delete ${map?.title}`
|
||||
const { map } = fetchMapById(mapId);
|
||||
const alertTitle = `Delete ${map?.title}`;
|
||||
return (
|
||||
<div>
|
||||
<BaseDialog
|
||||
@ -54,7 +54,7 @@ const DeleteDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
||||
</Alert>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteDialog
|
||||
export default DeleteDialog;
|
||||
|
@ -1,41 +1,41 @@
|
||||
import React from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useMutation, useQueryClient } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Client from '../../../../classes/client'
|
||||
import { activeInstance } from '../../../../redux/clientSlice'
|
||||
import { handleOnMutationSuccess } from '..'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import Alert from '@material-ui/lab/Alert'
|
||||
import AlertTitle from '@material-ui/lab/AlertTitle'
|
||||
import React from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useMutation, useQueryClient } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client from '../../../../classes/client';
|
||||
import { activeInstance } from '../../../../redux/clientSlice';
|
||||
import { handleOnMutationSuccess } from '..';
|
||||
import BaseDialog from '../base-dialog';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import AlertTitle from '@material-ui/lab/AlertTitle';
|
||||
|
||||
export type DeleteMultiselectDialogProps = {
|
||||
mapsId: number[]
|
||||
onClose: () => void
|
||||
}
|
||||
mapsId: number[];
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const DeleteMultiselectDialog = ({
|
||||
onClose,
|
||||
mapsId,
|
||||
}: DeleteMultiselectDialogProps): React.ReactElement => {
|
||||
const intl = useIntl()
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const queryClient = useQueryClient()
|
||||
const intl = useIntl();
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const mutation = useMutation((ids: number[]) => client.deleteMaps(ids), {
|
||||
onSuccess: () => handleOnMutationSuccess(onClose, queryClient),
|
||||
onError: (error) => {
|
||||
console.error(`Unexpected error ${error}`)
|
||||
console.error(`Unexpected error ${error}`);
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleOnSubmit = (): void => {
|
||||
mutation.mutate(mapsId)
|
||||
}
|
||||
mutation.mutate(mapsId);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -62,7 +62,7 @@ const DeleteMultiselectDialog = ({
|
||||
</Alert>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default DeleteMultiselectDialog
|
||||
export default DeleteMultiselectDialog;
|
||||
|
@ -1,70 +1,70 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
import { useMutation } from 'react-query'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import { useSelector } from 'react-redux'
|
||||
import React, { useEffect } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useMutation } from 'react-query';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client'
|
||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice'
|
||||
import Input from '../../../form/input'
|
||||
import { SimpleDialogProps } from '..'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
|
||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice';
|
||||
import Input from '../../../form/input';
|
||||
import { SimpleDialogProps } from '..';
|
||||
import BaseDialog from '../base-dialog';
|
||||
|
||||
export type DuplicateModel = {
|
||||
id: number
|
||||
title: string
|
||||
description?: string
|
||||
}
|
||||
id: number;
|
||||
title: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
const defaultModel: DuplicateModel = { title: '', description: '', id: -1 }
|
||||
const defaultModel: DuplicateModel = { title: '', description: '', id: -1 };
|
||||
const DuplicateDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const service: Client = useSelector(activeInstance)
|
||||
const [model, setModel] = React.useState<DuplicateModel>(defaultModel)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const service: Client = useSelector(activeInstance);
|
||||
const [model, setModel] = React.useState<DuplicateModel>(defaultModel);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
|
||||
const intl = useIntl()
|
||||
const intl = useIntl();
|
||||
|
||||
const mutation = useMutation<number, ErrorInfo, DuplicateModel>(
|
||||
(model: DuplicateModel) => {
|
||||
const { id, ...rest } = model
|
||||
return service.duplicateMap(id, rest)
|
||||
const { id, ...rest } = model;
|
||||
return service.duplicateMap(id, rest);
|
||||
},
|
||||
{
|
||||
onSuccess: (mapId) => {
|
||||
window.location.href = `/c/maps/${mapId}/edit`
|
||||
window.location.href = `/c/maps/${mapId}/edit`;
|
||||
},
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
event.preventDefault()
|
||||
mutation.mutate(model)
|
||||
}
|
||||
event.preventDefault();
|
||||
mutation.mutate(model);
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name
|
||||
const value = event.target.value
|
||||
setModel({ ...model, [name as keyof BasicMapInfo]: value })
|
||||
}
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
||||
};
|
||||
|
||||
const { map } = fetchMapById(mapId)
|
||||
const { map } = fetchMapById(mapId);
|
||||
useEffect(() => {
|
||||
if (open && map) {
|
||||
setModel(map)
|
||||
setModel(map);
|
||||
} else {
|
||||
setModel(defaultModel)
|
||||
setError(undefined)
|
||||
setModel(defaultModel);
|
||||
setError(undefined);
|
||||
}
|
||||
}, [mapId])
|
||||
}, [mapId]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -111,7 +111,7 @@ const DuplicateDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElem
|
||||
</FormControl>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default DuplicateDialog
|
||||
export default DuplicateDialog;
|
||||
|
@ -1,25 +1,25 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import { useStyles } from './style'
|
||||
import Alert from '@material-ui/lab/Alert'
|
||||
import { fetchMapById } from '../../../../redux/clientSlice'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import RadioGroup from '@material-ui/core/RadioGroup'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
import Radio from '@material-ui/core/Radio'
|
||||
import Select from '@material-ui/core/Select'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import BaseDialog from '../base-dialog';
|
||||
import { useStyles } from './style';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import { fetchMapById } from '../../../../redux/clientSlice';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import RadioGroup from '@material-ui/core/RadioGroup';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import Radio from '@material-ui/core/Radio';
|
||||
import Select from '@material-ui/core/Select';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
|
||||
type ExportFormat = 'pdf' | 'svg' | 'jpg' | 'png' | 'txt' | 'mm' | 'wxml' | 'xls' | 'txt'
|
||||
type ExportGroup = 'image' | 'document' | 'mindmap-tool'
|
||||
type ExportFormat = 'pdf' | 'svg' | 'jpg' | 'png' | 'txt' | 'mm' | 'wxml' | 'xls' | 'txt';
|
||||
type ExportGroup = 'image' | 'document' | 'mindmap-tool';
|
||||
|
||||
type ExportDialogProps = {
|
||||
mapId: number
|
||||
enableImgExport: boolean
|
||||
svgXml?: string
|
||||
onClose: () => void
|
||||
}
|
||||
mapId: number;
|
||||
enableImgExport: boolean;
|
||||
svgXml?: string;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ExportDialog = ({
|
||||
mapId,
|
||||
@ -27,50 +27,50 @@ const ExportDialog = ({
|
||||
enableImgExport,
|
||||
svgXml,
|
||||
}: ExportDialogProps): React.ReactElement => {
|
||||
const intl = useIntl()
|
||||
const [submit, setSubmit] = React.useState<boolean>(false)
|
||||
const intl = useIntl();
|
||||
const [submit, setSubmit] = React.useState<boolean>(false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [formExportRef, setExportFormRef] = React.useState<any>()
|
||||
const [formExportRef, setExportFormRef] = React.useState<any>();
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const [formTransformtRef, setTransformFormRef] = React.useState<any>()
|
||||
const [formTransformtRef, setTransformFormRef] = React.useState<any>();
|
||||
const [exportGroup, setExportGroup] = React.useState<ExportGroup>(
|
||||
enableImgExport ? 'image' : 'document'
|
||||
)
|
||||
);
|
||||
const [exportFormat, setExportFormat] = React.useState<ExportFormat>(
|
||||
enableImgExport ? 'svg' : 'xls'
|
||||
)
|
||||
const classes = useStyles()
|
||||
);
|
||||
const classes = useStyles();
|
||||
|
||||
const handleOnExportFormatChange = (event) => {
|
||||
setExportFormat(event.target.value)
|
||||
}
|
||||
setExportFormat(event.target.value);
|
||||
};
|
||||
|
||||
const handleOnGroupChange = (event) => {
|
||||
const value: ExportGroup = event.target.value
|
||||
setExportGroup(value)
|
||||
const value: ExportGroup = event.target.value;
|
||||
setExportGroup(value);
|
||||
|
||||
let defaultFormat: ExportFormat
|
||||
let defaultFormat: ExportFormat;
|
||||
switch (value) {
|
||||
case 'document':
|
||||
defaultFormat = 'pdf'
|
||||
break
|
||||
defaultFormat = 'pdf';
|
||||
break;
|
||||
case 'image':
|
||||
defaultFormat = 'svg'
|
||||
break
|
||||
defaultFormat = 'svg';
|
||||
break;
|
||||
case 'mindmap-tool':
|
||||
defaultFormat = 'wxml'
|
||||
break
|
||||
defaultFormat = 'wxml';
|
||||
break;
|
||||
}
|
||||
setExportFormat(defaultFormat)
|
||||
}
|
||||
setExportFormat(defaultFormat);
|
||||
};
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleOnSubmit = (): void => {
|
||||
setSubmit(true)
|
||||
}
|
||||
setSubmit(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (submit) {
|
||||
@ -81,15 +81,15 @@ const ExportDialog = ({
|
||||
exportFormat == 'jpg' ||
|
||||
exportFormat == 'png'
|
||||
) {
|
||||
formTransformtRef?.submit()
|
||||
formTransformtRef?.submit();
|
||||
} else {
|
||||
formExportRef?.submit()
|
||||
formExportRef?.submit();
|
||||
}
|
||||
onClose()
|
||||
onClose();
|
||||
}
|
||||
}, [submit])
|
||||
}, [submit]);
|
||||
|
||||
const { map } = fetchMapById(mapId)
|
||||
const { map } = fetchMapById(mapId);
|
||||
return (
|
||||
<div>
|
||||
<BaseDialog
|
||||
@ -231,7 +231,7 @@ const ExportDialog = ({
|
||||
<input name="svgXml" id="svgXml" value={svgXml} type="hidden" />
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ExportDialog
|
||||
export default ExportDialog;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import createStyles from '@material-ui/core/styles/createStyles'
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles'
|
||||
import createStyles from '@material-ui/core/styles/createStyles';
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles';
|
||||
|
||||
export const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
@ -17,4 +17,4 @@ export const useStyles = makeStyles(() =>
|
||||
margin: '5px 0px',
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1,42 +1,42 @@
|
||||
import React, { ErrorInfo } from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useQuery } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Client, { ChangeHistory } from '../../../../classes/client'
|
||||
import { activeInstance } from '../../../../redux/clientSlice'
|
||||
import { SimpleDialogProps } from '..'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import dayjs from 'dayjs'
|
||||
import React, { ErrorInfo } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useQuery } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client, { ChangeHistory } from '../../../../classes/client';
|
||||
import { activeInstance } from '../../../../redux/clientSlice';
|
||||
import { SimpleDialogProps } from '..';
|
||||
import BaseDialog from '../base-dialog';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import Table from '@material-ui/core/Table'
|
||||
import TableRow from '@material-ui/core/TableRow'
|
||||
import TableCell from '@material-ui/core/TableCell'
|
||||
import TableHead from '@material-ui/core/TableHead'
|
||||
import TableBody from '@material-ui/core/TableBody'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import Link from '@material-ui/core/Link'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import TableContainer from '@material-ui/core/TableContainer';
|
||||
import Table from '@material-ui/core/Table';
|
||||
import TableRow from '@material-ui/core/TableRow';
|
||||
import TableCell from '@material-ui/core/TableCell';
|
||||
import TableHead from '@material-ui/core/TableHead';
|
||||
import TableBody from '@material-ui/core/TableBody';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import Link from '@material-ui/core/Link';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
|
||||
const HistoryDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const intl = useIntl()
|
||||
const intl = useIntl();
|
||||
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const { data } = useQuery<unknown, ErrorInfo, ChangeHistory[]>('history', () => {
|
||||
return client.fetchHistory(mapId)
|
||||
})
|
||||
const changeHistory: ChangeHistory[] = data ? data : []
|
||||
return client.fetchHistory(mapId);
|
||||
});
|
||||
const changeHistory: ChangeHistory[] = data ? data : [];
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleOnClick = (event, vid): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
client.revertHistory(mapId, vid).then(() => {
|
||||
handleOnClose()
|
||||
})
|
||||
}
|
||||
handleOnClose();
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -127,7 +127,7 @@ const HistoryDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElemen
|
||||
</TableContainer>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default HistoryDialog
|
||||
export default HistoryDialog;
|
||||
|
@ -1,96 +1,96 @@
|
||||
import Button from '@material-ui/core/Button'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import React from 'react'
|
||||
import Button from '@material-ui/core/Button';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import React from 'react';
|
||||
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useMutation } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Client, { ErrorInfo } from '../../../../classes/client'
|
||||
import { activeInstance } from '../../../../redux/clientSlice'
|
||||
import Input from '../../../form/input'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useMutation } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client, { ErrorInfo } from '../../../../classes/client';
|
||||
import { activeInstance } from '../../../../redux/clientSlice';
|
||||
import Input from '../../../form/input';
|
||||
import BaseDialog from '../base-dialog';
|
||||
|
||||
export type ImportModel = {
|
||||
title: string
|
||||
description?: string
|
||||
contentType?: string
|
||||
content?: ArrayBuffer | null | string
|
||||
}
|
||||
title: string;
|
||||
description?: string;
|
||||
contentType?: string;
|
||||
content?: ArrayBuffer | null | string;
|
||||
};
|
||||
|
||||
export type CreateProps = {
|
||||
onClose: () => void
|
||||
}
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const defaultModel: ImportModel = { title: '' }
|
||||
const defaultModel: ImportModel = { title: '' };
|
||||
const ImportDialog = ({ onClose }: CreateProps): React.ReactElement => {
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const [model, setModel] = React.useState<ImportModel>(defaultModel)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const intl = useIntl()
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const [model, setModel] = React.useState<ImportModel>(defaultModel);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
const intl = useIntl();
|
||||
|
||||
const mutation = useMutation<number, ErrorInfo, ImportModel>(
|
||||
(model: ImportModel) => {
|
||||
return client.importMap(model)
|
||||
return client.importMap(model);
|
||||
},
|
||||
{
|
||||
onSuccess: (mapId: number) => {
|
||||
window.location.href = `/c/maps/${mapId}/edit`
|
||||
window.location.href = `/c/maps/${mapId}/edit`;
|
||||
},
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
setModel(defaultModel)
|
||||
setError(undefined)
|
||||
}
|
||||
onClose();
|
||||
setModel(defaultModel);
|
||||
setError(undefined);
|
||||
};
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
event.preventDefault()
|
||||
mutation.mutate(model)
|
||||
}
|
||||
event.preventDefault();
|
||||
mutation.mutate(model);
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name
|
||||
const value = event.target.value
|
||||
setModel({ ...model, [name as keyof ImportModel]: value })
|
||||
}
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof ImportModel]: value });
|
||||
};
|
||||
|
||||
const handleOnFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const files = event?.target?.files
|
||||
const reader = new FileReader()
|
||||
const files = event?.target?.files;
|
||||
const reader = new FileReader();
|
||||
|
||||
if (files) {
|
||||
const file = files[0]
|
||||
const file = files[0];
|
||||
// Closure to capture the file information.
|
||||
reader.onload = (event) => {
|
||||
const fileContent = event?.target?.result
|
||||
model.content = fileContent
|
||||
const fileContent = event?.target?.result;
|
||||
model.content = fileContent;
|
||||
|
||||
// Suggest file name ...
|
||||
const fileName = file.name
|
||||
const fileName = file.name;
|
||||
if (fileName) {
|
||||
const title = fileName.split('.')[0]
|
||||
const title = fileName.split('.')[0];
|
||||
if (!model.title || 0 === model.title.length) {
|
||||
model.title = title
|
||||
model.title = title;
|
||||
}
|
||||
}
|
||||
model.contentType =
|
||||
file.name.lastIndexOf('.wxml') != -1
|
||||
? 'application/xml'
|
||||
: 'application/freemind'
|
||||
setModel({ ...model })
|
||||
}
|
||||
: 'application/freemind';
|
||||
setModel({ ...model });
|
||||
};
|
||||
|
||||
// Read in the image file as a data URL.
|
||||
reader.readAsText(file)
|
||||
reader.readAsText(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -161,7 +161,7 @@ const ImportDialog = ({ onClose }: CreateProps): React.ReactElement => {
|
||||
</FormControl>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ImportDialog
|
||||
export default ImportDialog;
|
||||
|
@ -1,41 +1,41 @@
|
||||
import React from 'react'
|
||||
import RenameDialog from './rename-dialog'
|
||||
import DeleteDialog from './delete-dialog'
|
||||
import { ActionType } from '../action-chooser'
|
||||
import { QueryClient } from 'react-query'
|
||||
import DuplicateDialog from './duplicate-dialog'
|
||||
import CreateDialog from './create-dialog'
|
||||
import HistoryDialog from './history-dialog'
|
||||
import ImportDialog from './import-dialog'
|
||||
import PublishDialog from './publish-dialog'
|
||||
import InfoDialog from './info-dialog'
|
||||
import DeleteMultiselectDialog from './delete-multiselect-dialog'
|
||||
import ExportDialog from './export-dialog'
|
||||
import ShareDialog from './share-dialog'
|
||||
import React from 'react';
|
||||
import RenameDialog from './rename-dialog';
|
||||
import DeleteDialog from './delete-dialog';
|
||||
import { ActionType } from '../action-chooser';
|
||||
import { QueryClient } from 'react-query';
|
||||
import DuplicateDialog from './duplicate-dialog';
|
||||
import CreateDialog from './create-dialog';
|
||||
import HistoryDialog from './history-dialog';
|
||||
import ImportDialog from './import-dialog';
|
||||
import PublishDialog from './publish-dialog';
|
||||
import InfoDialog from './info-dialog';
|
||||
import DeleteMultiselectDialog from './delete-multiselect-dialog';
|
||||
import ExportDialog from './export-dialog';
|
||||
import ShareDialog from './share-dialog';
|
||||
|
||||
export type BasicMapInfo = {
|
||||
name: string
|
||||
description: string | undefined
|
||||
}
|
||||
name: string;
|
||||
description: string | undefined;
|
||||
};
|
||||
|
||||
type ActionDialogProps = {
|
||||
action?: ActionType
|
||||
mapsId: number[]
|
||||
onClose: () => void
|
||||
}
|
||||
action?: ActionType;
|
||||
mapsId: number[];
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const ActionDispatcher = ({ mapsId, action, onClose }: ActionDialogProps): React.ReactElement => {
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
switch (action) {
|
||||
case 'open':
|
||||
window.location.href = `/c/maps/${mapsId}/edit`
|
||||
break
|
||||
window.location.href = `/c/maps/${mapsId}/edit`;
|
||||
break;
|
||||
case 'print':
|
||||
window.open(`/c/maps/${mapsId}/print`, 'print')
|
||||
break
|
||||
window.open(`/c/maps/${mapsId}/print`, 'print');
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -61,16 +61,16 @@ const ActionDispatcher = ({ mapsId, action, onClose }: ActionDialogProps): React
|
||||
)}
|
||||
{action === 'share' && <ShareDialog onClose={handleOnClose} mapId={mapsId[0]} />}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
export const handleOnMutationSuccess = (onClose: () => void, queryClient: QueryClient): void => {
|
||||
queryClient.invalidateQueries('maps')
|
||||
onClose()
|
||||
}
|
||||
queryClient.invalidateQueries('maps');
|
||||
onClose();
|
||||
};
|
||||
|
||||
export type SimpleDialogProps = {
|
||||
mapId: number
|
||||
onClose: () => void
|
||||
}
|
||||
mapId: number;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
export default ActionDispatcher
|
||||
export default ActionDispatcher;
|
||||
|
@ -1,29 +1,29 @@
|
||||
import React from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import React from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import { ErrorInfo } from '../../../../classes/client'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import { SimpleDialogProps } from '..'
|
||||
import { useStyles } from './style'
|
||||
import dayjs from 'dayjs'
|
||||
import { fetchMapById } from '../../../../redux/clientSlice'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Card from '@material-ui/core/Card'
|
||||
import ListItem from '@material-ui/core/ListItem'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import List from '@material-ui/core/List'
|
||||
import { ErrorInfo } from '../../../../classes/client';
|
||||
import BaseDialog from '../base-dialog';
|
||||
import { SimpleDialogProps } from '..';
|
||||
import { useStyles } from './style';
|
||||
import dayjs from 'dayjs';
|
||||
import { fetchMapById } from '../../../../redux/clientSlice';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import List from '@material-ui/core/List';
|
||||
|
||||
const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const { map } = fetchMapById(mapId)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const { map } = fetchMapById(mapId);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
|
||||
const intl = useIntl()
|
||||
const classes = useStyles()
|
||||
const intl = useIntl();
|
||||
const classes = useStyles();
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
setError(undefined)
|
||||
}
|
||||
onClose();
|
||||
setError(undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<BaseDialog
|
||||
@ -175,7 +175,7 @@ const InfoDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement =
|
||||
</Card>
|
||||
</Paper>
|
||||
</BaseDialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default InfoDialog
|
||||
export default InfoDialog;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import createStyles from '@material-ui/core/styles/createStyles'
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles'
|
||||
import createStyles from '@material-ui/core/styles/createStyles';
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles';
|
||||
|
||||
export const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
@ -12,4 +12,4 @@ export const useStyles = makeStyles(() =>
|
||||
width: '150px',
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1,68 +1,68 @@
|
||||
import React from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useMutation, useQueryClient } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Client, { ErrorInfo } from '../../../../classes/client'
|
||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import { handleOnMutationSuccess, SimpleDialogProps } from '..'
|
||||
import { useStyles } from './style'
|
||||
import React from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useMutation, useQueryClient } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client, { ErrorInfo } from '../../../../classes/client';
|
||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice';
|
||||
import BaseDialog from '../base-dialog';
|
||||
import { handleOnMutationSuccess, SimpleDialogProps } from '..';
|
||||
import { useStyles } from './style';
|
||||
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
import Checkbox from '@material-ui/core/Checkbox'
|
||||
import TabContext from '@material-ui/lab/TabContext'
|
||||
import AppBar from '@material-ui/core/AppBar'
|
||||
import TabList from '@material-ui/lab/TabList'
|
||||
import Tab from '@material-ui/core/Tab'
|
||||
import TabPanel from '@material-ui/lab/TabPanel'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import TextareaAutosize from '@material-ui/core/TextareaAutosize'
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import Checkbox from '@material-ui/core/Checkbox';
|
||||
import TabContext from '@material-ui/lab/TabContext';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import TabList from '@material-ui/lab/TabList';
|
||||
import Tab from '@material-ui/core/Tab';
|
||||
import TabPanel from '@material-ui/lab/TabPanel';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import TextareaAutosize from '@material-ui/core/TextareaAutosize';
|
||||
|
||||
const PublishDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const { map } = fetchMapById(mapId)
|
||||
const { map } = fetchMapById(mapId);
|
||||
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const [model, setModel] = React.useState<boolean>(map ? map.isPublic : false)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const [activeTab, setActiveTab] = React.useState('1')
|
||||
const queryClient = useQueryClient()
|
||||
const intl = useIntl()
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const [model, setModel] = React.useState<boolean>(map ? map.isPublic : false);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
const [activeTab, setActiveTab] = React.useState('1');
|
||||
const queryClient = useQueryClient();
|
||||
const intl = useIntl();
|
||||
|
||||
const classes = useStyles()
|
||||
const classes = useStyles();
|
||||
const mutation = useMutation<void, ErrorInfo, boolean>(
|
||||
(model: boolean) => {
|
||||
return client.updateMapToPublic(mapId, model)
|
||||
return client.updateMapToPublic(mapId, model);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
setModel(model)
|
||||
handleOnMutationSuccess(onClose, queryClient)
|
||||
setModel(model);
|
||||
handleOnMutationSuccess(onClose, queryClient);
|
||||
},
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
setError(undefined)
|
||||
}
|
||||
onClose();
|
||||
setError(undefined);
|
||||
};
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
event.preventDefault()
|
||||
mutation.mutate(model)
|
||||
}
|
||||
event.preventDefault();
|
||||
mutation.mutate(model);
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>, checked: boolean): void => {
|
||||
event.preventDefault()
|
||||
setModel(checked)
|
||||
}
|
||||
event.preventDefault();
|
||||
setModel(checked);
|
||||
};
|
||||
|
||||
const handleTabChange = (event, newValue) => {
|
||||
setActiveTab(newValue)
|
||||
}
|
||||
setActiveTab(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -152,7 +152,7 @@ const PublishDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElemen
|
||||
</div>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default PublishDialog
|
||||
export default PublishDialog;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import createStyles from '@material-ui/core/styles/createStyles'
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles'
|
||||
import createStyles from '@material-ui/core/styles/createStyles';
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles';
|
||||
|
||||
export const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
@ -9,4 +9,4 @@ export const useStyles = makeStyles(() =>
|
||||
marging: '0px 10px',
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1,72 +1,72 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
import { useMutation, useQueryClient } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client'
|
||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice'
|
||||
import { SimpleDialogProps, handleOnMutationSuccess } from '..'
|
||||
import Input from '../../../form/input'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import React, { useEffect } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useMutation, useQueryClient } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client, { BasicMapInfo, ErrorInfo } from '../../../../classes/client';
|
||||
import { activeInstance, fetchMapById } from '../../../../redux/clientSlice';
|
||||
import { SimpleDialogProps, handleOnMutationSuccess } from '..';
|
||||
import Input from '../../../form/input';
|
||||
import BaseDialog from '../base-dialog';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
|
||||
export type RenameModel = {
|
||||
id: number
|
||||
title: string
|
||||
description?: string
|
||||
}
|
||||
id: number;
|
||||
title: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
const defaultModel: RenameModel = { title: '', description: '', id: -1 }
|
||||
const defaultModel: RenameModel = { title: '', description: '', id: -1 };
|
||||
const RenameDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const service: Client = useSelector(activeInstance)
|
||||
const [model, setModel] = React.useState<RenameModel>(defaultModel)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const service: Client = useSelector(activeInstance);
|
||||
const [model, setModel] = React.useState<RenameModel>(defaultModel);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
|
||||
const intl = useIntl()
|
||||
const queryClient = useQueryClient()
|
||||
const intl = useIntl();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const mutation = useMutation<RenameModel, ErrorInfo, RenameModel>(
|
||||
(model: RenameModel) => {
|
||||
const { id, ...rest } = model
|
||||
return service.renameMap(id, rest).then(() => model)
|
||||
const { id, ...rest } = model;
|
||||
return service.renameMap(id, rest).then(() => model);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
handleOnMutationSuccess(onClose, queryClient)
|
||||
handleOnMutationSuccess(onClose, queryClient);
|
||||
},
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
setModel(defaultModel)
|
||||
setError(undefined)
|
||||
}
|
||||
onClose();
|
||||
setModel(defaultModel);
|
||||
setError(undefined);
|
||||
};
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
event.preventDefault()
|
||||
mutation.mutate(model)
|
||||
}
|
||||
event.preventDefault();
|
||||
mutation.mutate(model);
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name
|
||||
const value = event.target.value
|
||||
setModel({ ...model, [name as keyof BasicMapInfo]: value })
|
||||
}
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
||||
};
|
||||
|
||||
const { map } = fetchMapById(mapId)
|
||||
const { map } = fetchMapById(mapId);
|
||||
useEffect(() => {
|
||||
if (open && map) {
|
||||
setModel(map)
|
||||
setModel(map);
|
||||
} else {
|
||||
setModel(defaultModel)
|
||||
setError(undefined)
|
||||
setModel(defaultModel);
|
||||
setError(undefined);
|
||||
}
|
||||
}, [mapId])
|
||||
}, [mapId]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -110,7 +110,7 @@ const RenameDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
||||
</FormControl>
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default RenameDialog
|
||||
export default RenameDialog;
|
||||
|
@ -1,115 +1,115 @@
|
||||
import React from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useMutation, useQuery, useQueryClient } from 'react-query'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Client, { ErrorInfo, Permission } from '../../../../classes/client'
|
||||
import { activeInstance } from '../../../../redux/clientSlice'
|
||||
import { SimpleDialogProps } from '..'
|
||||
import BaseDialog from '../base-dialog'
|
||||
import List from '@material-ui/core/List'
|
||||
import ListItem from '@material-ui/core/ListItem'
|
||||
import ListItemText from '@material-ui/core/ListItemText'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import React from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client, { ErrorInfo, Permission } from '../../../../classes/client';
|
||||
import { activeInstance } from '../../../../redux/clientSlice';
|
||||
import { SimpleDialogProps } from '..';
|
||||
import BaseDialog from '../base-dialog';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
|
||||
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'
|
||||
import DeleteIcon from '@material-ui/icons/Delete'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Select from '@material-ui/core/Select'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import TextField from '@material-ui/core/TextField'
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel'
|
||||
import Checkbox from '@material-ui/core/Checkbox'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import { useStyles } from './style'
|
||||
import RoleIcon from '../../role-icon'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
|
||||
import DeleteIcon from '@material-ui/icons/Delete';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Select from '@material-ui/core/Select';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import Checkbox from '@material-ui/core/Checkbox';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { useStyles } from './style';
|
||||
import RoleIcon from '../../role-icon';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
|
||||
type ShareModel = {
|
||||
emails: string
|
||||
role: 'editor' | 'viewer'
|
||||
message: string
|
||||
}
|
||||
emails: string;
|
||||
role: 'editor' | 'viewer';
|
||||
message: string;
|
||||
};
|
||||
|
||||
const defaultModel: ShareModel = { emails: '', role: 'editor', message: '' }
|
||||
const defaultModel: ShareModel = { emails: '', role: 'editor', message: '' };
|
||||
const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement => {
|
||||
const intl = useIntl()
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const queryClient = useQueryClient()
|
||||
const classes = useStyles()
|
||||
const [showMessage, setShowMessage] = React.useState<boolean>(false)
|
||||
const [model, setModel] = React.useState<ShareModel>(defaultModel)
|
||||
const [error, setError] = React.useState<ErrorInfo>()
|
||||
const intl = useIntl();
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const queryClient = useQueryClient();
|
||||
const classes = useStyles();
|
||||
const [showMessage, setShowMessage] = React.useState<boolean>(false);
|
||||
const [model, setModel] = React.useState<ShareModel>(defaultModel);
|
||||
const [error, setError] = React.useState<ErrorInfo>();
|
||||
|
||||
const deleteMutation = useMutation(
|
||||
(email: string) => {
|
||||
return client.deleteMapPermission(mapId, email)
|
||||
return client.deleteMapPermission(mapId, email);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(`perm-${mapId}`)
|
||||
setModel(defaultModel)
|
||||
queryClient.invalidateQueries(`perm-${mapId}`);
|
||||
setModel(defaultModel);
|
||||
},
|
||||
onError: (error: ErrorInfo) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const addMutation = useMutation(
|
||||
(model: ShareModel) => {
|
||||
const emails = model.emails.split("'")
|
||||
const emails = model.emails.split("'");
|
||||
const permissions = emails.map((email) => {
|
||||
return { email: email, role: model.role }
|
||||
})
|
||||
return client.addMapPermissions(mapId, model.message, permissions)
|
||||
return { email: email, role: model.role };
|
||||
});
|
||||
return client.addMapPermissions(mapId, model.message, permissions);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(`perm-${mapId}`)
|
||||
setModel(defaultModel)
|
||||
queryClient.invalidateQueries(`perm-${mapId}`);
|
||||
setModel(defaultModel);
|
||||
},
|
||||
onError: (error: ErrorInfo) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnClose = (): void => {
|
||||
onClose()
|
||||
}
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name
|
||||
const value = event.target.value
|
||||
setModel({ ...model, [name as keyof ShareModel]: value })
|
||||
}
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof ShareModel]: value });
|
||||
};
|
||||
|
||||
const handleOnAddClick = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void => {
|
||||
event.stopPropagation()
|
||||
addMutation.mutate(model)
|
||||
}
|
||||
event.stopPropagation();
|
||||
addMutation.mutate(model);
|
||||
};
|
||||
|
||||
const handleOnDeleteClick = (
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
|
||||
email: string
|
||||
): void => {
|
||||
event.stopPropagation()
|
||||
deleteMutation.mutate(email)
|
||||
}
|
||||
event.stopPropagation();
|
||||
deleteMutation.mutate(email);
|
||||
};
|
||||
|
||||
const { isLoading, data: permissions = [] } = useQuery<unknown, ErrorInfo, Permission[]>(
|
||||
`perm-${mapId}`,
|
||||
() => {
|
||||
return client.fetchMapPermissions(mapId)
|
||||
return client.fetchMapPermissions(mapId);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const formatName = (perm: Permission): string => {
|
||||
return perm.name ? `${perm.name}<${perm.email}>` : perm.email
|
||||
}
|
||||
return perm.name ? `${perm.name}<${perm.email}>` : perm.email;
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -160,7 +160,7 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
||||
<FormControlLabel
|
||||
value="start"
|
||||
onChange={(event, value) => {
|
||||
setShowMessage(value)
|
||||
setShowMessage(value);
|
||||
}}
|
||||
style={{ fontSize: '5px' }}
|
||||
control={<Checkbox color="primary" />}
|
||||
@ -242,14 +242,14 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</Paper>
|
||||
)}
|
||||
</BaseDialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default ShareDialog
|
||||
export default ShareDialog;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import createStyles from '@material-ui/core/styles/createStyles'
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles'
|
||||
import createStyles from '@material-ui/core/styles/createStyles';
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles';
|
||||
|
||||
export const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
@ -23,4 +23,4 @@ export const useStyles = makeStyles(() =>
|
||||
minWidth: '850px',
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1,30 +1,30 @@
|
||||
import React from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import React from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import Help from '@material-ui/icons/Help'
|
||||
import PolicyOutlined from '@material-ui/icons/PolicyOutlined'
|
||||
import FeedbackOutlined from '@material-ui/icons/FeedbackOutlined'
|
||||
import EmojiPeopleOutlined from '@material-ui/icons/EmailOutlined'
|
||||
import EmailOutlined from '@material-ui/icons/EmailOutlined'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import Menu from '@material-ui/core/Menu'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import Link from '@material-ui/core/Link'
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import Help from '@material-ui/icons/Help';
|
||||
import PolicyOutlined from '@material-ui/icons/PolicyOutlined';
|
||||
import FeedbackOutlined from '@material-ui/icons/FeedbackOutlined';
|
||||
import EmojiPeopleOutlined from '@material-ui/icons/EmailOutlined';
|
||||
import EmailOutlined from '@material-ui/icons/EmailOutlined';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import Link from '@material-ui/core/Link';
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
|
||||
const HelpMenu = (): React.ReactElement => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
|
||||
const open = Boolean(anchorEl)
|
||||
const intl = useIntl()
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const intl = useIntl();
|
||||
|
||||
const handleMenu = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget)
|
||||
}
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null)
|
||||
}
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<span>
|
||||
@ -100,7 +100,7 @@ const HelpMenu = (): React.ReactElement => {
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default HelpMenu
|
||||
export default HelpMenu;
|
||||
|
@ -1,96 +1,96 @@
|
||||
import React, { ErrorInfo, ReactElement, useEffect } from 'react'
|
||||
import clsx from 'clsx'
|
||||
import Drawer from '@material-ui/core/Drawer'
|
||||
import AppBar from '@material-ui/core/AppBar'
|
||||
import Toolbar from '@material-ui/core/Toolbar'
|
||||
import List from '@material-ui/core/List'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import { useStyles } from './style'
|
||||
import { MapsList } from './maps-list'
|
||||
import { FormattedMessage, IntlProvider, useIntl } from 'react-intl'
|
||||
import { useQuery, useMutation, useQueryClient } from 'react-query'
|
||||
import { activeInstance } from '../../redux/clientSlice'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Client, { Label } from '../../classes/client'
|
||||
import ActionDispatcher from './action-dispatcher'
|
||||
import { ActionType } from './action-chooser'
|
||||
import AccountMenu from './account-menu'
|
||||
import ClientHealthSentinel from '../../classes/client/client-health-sentinel'
|
||||
import HelpMenu from './help-menu'
|
||||
import LanguageMenu from './language-menu'
|
||||
import AppI18n, { Locales } from '../../classes/app-i18n'
|
||||
import React, { ErrorInfo, ReactElement, useEffect } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Drawer from '@material-ui/core/Drawer';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import List from '@material-ui/core/List';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import { useStyles } from './style';
|
||||
import { MapsList } from './maps-list';
|
||||
import { FormattedMessage, IntlProvider, useIntl } from 'react-intl';
|
||||
import { useQuery, useMutation, useQueryClient } from 'react-query';
|
||||
import { activeInstance } from '../../redux/clientSlice';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Client, { Label } from '../../classes/client';
|
||||
import ActionDispatcher from './action-dispatcher';
|
||||
import { ActionType } from './action-chooser';
|
||||
import AccountMenu from './account-menu';
|
||||
import ClientHealthSentinel from '../../classes/client/client-health-sentinel';
|
||||
import HelpMenu from './help-menu';
|
||||
import LanguageMenu from './language-menu';
|
||||
import AppI18n, { Locales } from '../../classes/app-i18n';
|
||||
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||
import ListItem from '@material-ui/core/ListItem'
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
|
||||
import AddCircleTwoTone from '@material-ui/icons/AddCircleTwoTone'
|
||||
import CloudUploadTwoTone from '@material-ui/icons/CloudUploadTwoTone'
|
||||
import DeleteOutlineTwoTone from '@material-ui/icons/DeleteOutlineTwoTone'
|
||||
import LabelTwoTone from '@material-ui/icons/LabelTwoTone'
|
||||
import PersonOutlineTwoTone from '@material-ui/icons/PersonOutlineTwoTone'
|
||||
import PublicTwoTone from '@material-ui/icons/PublicTwoTone'
|
||||
import ScatterPlotTwoTone from '@material-ui/icons/ScatterPlotTwoTone'
|
||||
import ShareTwoTone from '@material-ui/icons/ShareTwoTone'
|
||||
import StarTwoTone from '@material-ui/icons/StarTwoTone'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Link from '@material-ui/core/Link'
|
||||
import ListItemText from '@material-ui/core/ListItemText'
|
||||
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'
|
||||
import AddCircleTwoTone from '@material-ui/icons/AddCircleTwoTone';
|
||||
import CloudUploadTwoTone from '@material-ui/icons/CloudUploadTwoTone';
|
||||
import DeleteOutlineTwoTone from '@material-ui/icons/DeleteOutlineTwoTone';
|
||||
import LabelTwoTone from '@material-ui/icons/LabelTwoTone';
|
||||
import PersonOutlineTwoTone from '@material-ui/icons/PersonOutlineTwoTone';
|
||||
import PublicTwoTone from '@material-ui/icons/PublicTwoTone';
|
||||
import ScatterPlotTwoTone from '@material-ui/icons/ScatterPlotTwoTone';
|
||||
import ShareTwoTone from '@material-ui/icons/ShareTwoTone';
|
||||
import StarTwoTone from '@material-ui/icons/StarTwoTone';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Link from '@material-ui/core/Link';
|
||||
import ListItemText from '@material-ui/core/ListItemText';
|
||||
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
|
||||
|
||||
import logoIcon from '../../images/logo-small.svg'
|
||||
import poweredByIcon from '../../images/pwrdby-white.svg'
|
||||
import logoIcon from '../../images/logo-small.svg';
|
||||
import poweredByIcon from '../../images/pwrdby-white.svg';
|
||||
|
||||
export type Filter = GenericFilter | LabelFilter
|
||||
export type Filter = GenericFilter | LabelFilter;
|
||||
|
||||
export interface GenericFilter {
|
||||
type: 'public' | 'all' | 'starred' | 'shared' | 'label' | 'owned'
|
||||
type: 'public' | 'all' | 'starred' | 'shared' | 'label' | 'owned';
|
||||
}
|
||||
|
||||
export interface LabelFilter {
|
||||
type: 'label'
|
||||
label: Label
|
||||
type: 'label';
|
||||
label: Label;
|
||||
}
|
||||
|
||||
interface ToolbarButtonInfo {
|
||||
filter: GenericFilter | LabelFilter
|
||||
label: string
|
||||
icon: React.ReactElement
|
||||
filter: GenericFilter | LabelFilter;
|
||||
label: string;
|
||||
icon: React.ReactElement;
|
||||
}
|
||||
|
||||
const MapsPage = (): ReactElement => {
|
||||
const classes = useStyles()
|
||||
const [filter, setFilter] = React.useState<Filter>({ type: 'all' })
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const queryClient = useQueryClient()
|
||||
const [activeDialog, setActiveDialog] = React.useState<ActionType | undefined>(undefined)
|
||||
const intl = useIntl()
|
||||
const classes = useStyles();
|
||||
const [filter, setFilter] = React.useState<Filter>({ type: 'all' });
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const queryClient = useQueryClient();
|
||||
const [activeDialog, setActiveDialog] = React.useState<ActionType | undefined>(undefined);
|
||||
const intl = useIntl();
|
||||
|
||||
useEffect(() => {
|
||||
document.title = 'Maps | WiseMapping'
|
||||
}, [])
|
||||
document.title = 'Maps | WiseMapping';
|
||||
}, []);
|
||||
|
||||
const mutation = useMutation((id: number) => client.deleteLabel(id), {
|
||||
onSuccess: () => queryClient.invalidateQueries('labels'),
|
||||
onError: (error) => {
|
||||
console.error(`Unexpected error ${error}`)
|
||||
console.error(`Unexpected error ${error}`);
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
const handleMenuClick = (filter: Filter) => {
|
||||
queryClient.invalidateQueries('maps')
|
||||
setFilter(filter)
|
||||
}
|
||||
queryClient.invalidateQueries('maps');
|
||||
setFilter(filter);
|
||||
};
|
||||
|
||||
const handleLabelDelete = (id: number) => {
|
||||
mutation.mutate(id)
|
||||
}
|
||||
mutation.mutate(id);
|
||||
};
|
||||
|
||||
const { data } = useQuery<unknown, ErrorInfo, Label[]>('labels', () => {
|
||||
return client.fetchLabels()
|
||||
})
|
||||
return client.fetchLabels();
|
||||
});
|
||||
|
||||
const labels: Label[] = data ? data : []
|
||||
const labels: Label[] = data ? data : [];
|
||||
const filterButtons: ToolbarButtonInfo[] = [
|
||||
{
|
||||
filter: { type: 'all' },
|
||||
@ -117,7 +117,7 @@ const MapsPage = (): ReactElement => {
|
||||
label: 'Public',
|
||||
icon: <PublicTwoTone color="secondary" />,
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
labels.forEach((l) =>
|
||||
filterButtons.push({
|
||||
@ -125,11 +125,11 @@ const MapsPage = (): ReactElement => {
|
||||
label: l.title,
|
||||
icon: <LabelTwoTone style={{ color: l.color ? l.color : 'inherit' }} />,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
// Configure using user settings ...
|
||||
const appi18n = new AppI18n()
|
||||
const userLocale = appi18n.getUserLocale()
|
||||
const appi18n = new AppI18n();
|
||||
const userLocale = appi18n.getUserLocale();
|
||||
|
||||
return (
|
||||
<IntlProvider
|
||||
@ -232,7 +232,7 @@ const MapsPage = (): ReactElement => {
|
||||
(buttonInfo.filter as LabelFilter).label
|
||||
}`}
|
||||
/>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
|
||||
@ -251,46 +251,46 @@ const MapsPage = (): ReactElement => {
|
||||
</main>
|
||||
</div>
|
||||
</IntlProvider>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
interface ListItemProps {
|
||||
icon: React.ReactElement
|
||||
label: string
|
||||
filter: Filter
|
||||
active?: Filter
|
||||
onClick: (filter: Filter) => void
|
||||
onDelete?: (id: number) => void
|
||||
icon: React.ReactElement;
|
||||
label: string;
|
||||
filter: Filter;
|
||||
active?: Filter;
|
||||
onClick: (filter: Filter) => void;
|
||||
onDelete?: (id: number) => void;
|
||||
}
|
||||
|
||||
const StyleListItem = (props: ListItemProps) => {
|
||||
const icon = props.icon
|
||||
const label = props.label
|
||||
const filter = props.filter
|
||||
const activeFilter = props.active
|
||||
const onClick = props.onClick
|
||||
const onDeleteLabel = props.onDelete
|
||||
const icon = props.icon;
|
||||
const label = props.label;
|
||||
const filter = props.filter;
|
||||
const activeFilter = props.active;
|
||||
const onClick = props.onClick;
|
||||
const onDeleteLabel = props.onDelete;
|
||||
const isSelected =
|
||||
activeFilter &&
|
||||
activeFilter.type == filter.type &&
|
||||
(activeFilter.type != 'label' ||
|
||||
(activeFilter as LabelFilter).label == (filter as LabelFilter).label)
|
||||
(activeFilter as LabelFilter).label == (filter as LabelFilter).label);
|
||||
|
||||
const handleOnClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>, filter: Filter) => {
|
||||
event.stopPropagation()
|
||||
onClick(filter)
|
||||
}
|
||||
event.stopPropagation();
|
||||
onClick(filter);
|
||||
};
|
||||
|
||||
const handleOnDelete = (
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
|
||||
filter: Filter
|
||||
) => {
|
||||
event.stopPropagation()
|
||||
event.stopPropagation();
|
||||
if (!onDeleteLabel) {
|
||||
throw 'Illegal state exeption'
|
||||
throw 'Illegal state exeption';
|
||||
}
|
||||
onDeleteLabel((filter as LabelFilter).label.id)
|
||||
}
|
||||
onDeleteLabel((filter as LabelFilter).label.id);
|
||||
};
|
||||
|
||||
return (
|
||||
<ListItem button selected={isSelected} onClick={(e) => handleOnClick(e, filter)}>
|
||||
@ -308,7 +308,7 @@ const StyleListItem = (props: ListItemProps) => {
|
||||
</ListItemSecondaryAction>
|
||||
)}
|
||||
</ListItem>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default MapsPage
|
||||
export default MapsPage;
|
||||
|
@ -1,55 +1,55 @@
|
||||
import TranslateTwoTone from '@material-ui/icons/TranslateTwoTone'
|
||||
import React from 'react'
|
||||
import { useMutation, useQueryClient } from 'react-query'
|
||||
import Client from '../../../classes/client'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { activeInstance, fetchAccount } from '../../../redux/clientSlice'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { LocaleCode, Locales } from '../../../classes/app-i18n'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import Menu from '@material-ui/core/Menu'
|
||||
import MenuItem from '@material-ui/core/MenuItem'
|
||||
import Dialog from '@material-ui/core/Dialog'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import DialogContentText from '@material-ui/core/DialogContentText'
|
||||
import DialogActions from '@material-ui/core/DialogActions'
|
||||
import Divider from '@material-ui/core/Divider'
|
||||
import TranslateTwoTone from '@material-ui/icons/TranslateTwoTone';
|
||||
import React from 'react';
|
||||
import { useMutation, useQueryClient } from 'react-query';
|
||||
import Client from '../../../classes/client';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { activeInstance, fetchAccount } from '../../../redux/clientSlice';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { LocaleCode, Locales } from '../../../classes/app-i18n';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
import Dialog from '@material-ui/core/Dialog';
|
||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
import DialogContent from '@material-ui/core/DialogContent';
|
||||
import DialogContentText from '@material-ui/core/DialogContentText';
|
||||
import DialogActions from '@material-ui/core/DialogActions';
|
||||
import Divider from '@material-ui/core/Divider';
|
||||
|
||||
const LanguageMenu = (): React.ReactElement => {
|
||||
const queryClient = useQueryClient()
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
|
||||
const [openHelpDialog, setHelpDialogOpen] = React.useState<boolean>(false)
|
||||
const queryClient = useQueryClient();
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [openHelpDialog, setHelpDialogOpen] = React.useState<boolean>(false);
|
||||
|
||||
const open = Boolean(anchorEl)
|
||||
const intl = useIntl()
|
||||
const open = Boolean(anchorEl);
|
||||
const intl = useIntl();
|
||||
|
||||
const mutation = useMutation((locale: LocaleCode) => client.updateAccountLanguage(locale), {
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries('account')
|
||||
handleClose()
|
||||
queryClient.invalidateQueries('account');
|
||||
handleClose();
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error(`Unexpected error ${error}`)
|
||||
console.error(`Unexpected error ${error}`);
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
const handleMenu = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget)
|
||||
}
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null)
|
||||
}
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleOnClick = (event: React.MouseEvent<HTMLElement>) => {
|
||||
const localeCode = event.target['id']
|
||||
mutation.mutate(localeCode)
|
||||
}
|
||||
const localeCode = event.target['id'];
|
||||
mutation.mutate(localeCode);
|
||||
};
|
||||
|
||||
const accountInfo = fetchAccount()
|
||||
const accountInfo = fetchAccount();
|
||||
return (
|
||||
<span>
|
||||
<Tooltip
|
||||
@ -106,8 +106,8 @@ const LanguageMenu = (): React.ReactElement => {
|
||||
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
handleClose()
|
||||
setHelpDialogOpen(true)
|
||||
handleClose();
|
||||
setHelpDialogOpen(true);
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="language.help" defaultMessage="Help to Translate" />
|
||||
@ -115,12 +115,12 @@ const LanguageMenu = (): React.ReactElement => {
|
||||
</Menu>
|
||||
{openHelpDialog && <HelpUsToTranslateDialog onClose={() => setHelpDialogOpen(false)} />}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
type HelpUsToTranslateDialogProp = {
|
||||
onClose: () => void
|
||||
}
|
||||
onClose: () => void;
|
||||
};
|
||||
const HelpUsToTranslateDialog = ({ onClose }: HelpUsToTranslateDialogProp) => {
|
||||
return (
|
||||
<Dialog open={true} onClose={onClose}>
|
||||
@ -137,7 +137,7 @@ const HelpUsToTranslateDialog = ({ onClose }: HelpUsToTranslateDialogProp) => {
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default LanguageMenu
|
||||
export default LanguageMenu;
|
||||
|
@ -1,54 +1,54 @@
|
||||
import React, { useEffect, CSSProperties } from 'react'
|
||||
import React, { useEffect, CSSProperties } from 'react';
|
||||
|
||||
import { useStyles } from './styled'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { activeInstance, fetchAccount } from '../../../redux/clientSlice'
|
||||
import { useMutation, useQuery, useQueryClient } from 'react-query'
|
||||
import Client, { ErrorInfo, MapInfo } from '../../../classes/client'
|
||||
import ActionChooser, { ActionType } from '../action-chooser'
|
||||
import ActionDispatcher from '../action-dispatcher'
|
||||
import dayjs from 'dayjs'
|
||||
import { Filter, LabelFilter } from '..'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import { useStyles } from './styled';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { activeInstance, fetchAccount } from '../../../redux/clientSlice';
|
||||
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
||||
import Client, { ErrorInfo, MapInfo } from '../../../classes/client';
|
||||
import ActionChooser, { ActionType } from '../action-chooser';
|
||||
import ActionDispatcher from '../action-dispatcher';
|
||||
import dayjs from 'dayjs';
|
||||
import { Filter, LabelFilter } from '..';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import Table from '@material-ui/core/Table'
|
||||
import TableBody from '@material-ui/core/TableBody'
|
||||
import TableCell from '@material-ui/core/TableCell'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import TableHead from '@material-ui/core/TableHead'
|
||||
import TablePagination from '@material-ui/core/TablePagination'
|
||||
import TableRow from '@material-ui/core/TableRow'
|
||||
import TableSortLabel from '@material-ui/core/TableSortLabel'
|
||||
import Toolbar from '@material-ui/core/Toolbar'
|
||||
import Paper from '@material-ui/core/Paper'
|
||||
import Checkbox from '@material-ui/core/Checkbox'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import InputBase from '@material-ui/core/InputBase'
|
||||
import Link from '@material-ui/core/Link'
|
||||
import Table from '@material-ui/core/Table';
|
||||
import TableBody from '@material-ui/core/TableBody';
|
||||
import TableCell from '@material-ui/core/TableCell';
|
||||
import TableContainer from '@material-ui/core/TableContainer';
|
||||
import TableHead from '@material-ui/core/TableHead';
|
||||
import TablePagination from '@material-ui/core/TablePagination';
|
||||
import TableRow from '@material-ui/core/TableRow';
|
||||
import TableSortLabel from '@material-ui/core/TableSortLabel';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import Paper from '@material-ui/core/Paper';
|
||||
import Checkbox from '@material-ui/core/Checkbox';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import InputBase from '@material-ui/core/InputBase';
|
||||
import Link from '@material-ui/core/Link';
|
||||
|
||||
import LabelTwoTone from '@material-ui/icons/LabelTwoTone'
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined'
|
||||
import MoreHorizIcon from '@material-ui/icons/MoreHoriz'
|
||||
import StarRateRoundedIcon from '@material-ui/icons/StarRateRounded'
|
||||
import SearchIcon from '@material-ui/icons/Search'
|
||||
import LabelTwoTone from '@material-ui/icons/LabelTwoTone';
|
||||
import DeleteOutlined from '@material-ui/icons/DeleteOutlined';
|
||||
import MoreHorizIcon from '@material-ui/icons/MoreHoriz';
|
||||
import StarRateRoundedIcon from '@material-ui/icons/StarRateRounded';
|
||||
import SearchIcon from '@material-ui/icons/Search';
|
||||
|
||||
// Load fromNow pluggin
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
dayjs.extend(relativeTime)
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
|
||||
if (b[orderBy] < a[orderBy]) {
|
||||
return -1
|
||||
return -1;
|
||||
}
|
||||
if (b[orderBy] > a[orderBy]) {
|
||||
return 1
|
||||
return 1;
|
||||
}
|
||||
return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
type Order = 'asc' | 'desc'
|
||||
type Order = 'asc' | 'desc';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function getComparator<Key extends keyof any>(
|
||||
@ -60,38 +60,38 @@ function getComparator<Key extends keyof any>(
|
||||
) => number {
|
||||
return order === 'desc'
|
||||
? (a, b) => descendingComparator(a, b, orderBy)
|
||||
: (a, b) => -descendingComparator(a, b, orderBy)
|
||||
: (a, b) => -descendingComparator(a, b, orderBy);
|
||||
}
|
||||
|
||||
function stableSort<T>(array: T[], comparator: (a: T, b: T) => number) {
|
||||
const stabilizedThis = array.map((el, index) => [el, index] as [T, number])
|
||||
const stabilizedThis = array.map((el, index) => [el, index] as [T, number]);
|
||||
stabilizedThis.sort((a, b) => {
|
||||
const order = comparator(a[0], b[0])
|
||||
if (order !== 0) return order
|
||||
return a[1] - b[1]
|
||||
})
|
||||
return stabilizedThis.map((el) => el[0])
|
||||
const order = comparator(a[0], b[0]);
|
||||
if (order !== 0) return order;
|
||||
return a[1] - b[1];
|
||||
});
|
||||
return stabilizedThis.map((el) => el[0]);
|
||||
}
|
||||
|
||||
interface HeadCell {
|
||||
id: keyof MapInfo
|
||||
label?: string
|
||||
numeric: boolean
|
||||
style?: CSSProperties
|
||||
id: keyof MapInfo;
|
||||
label?: string;
|
||||
numeric: boolean;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
interface EnhancedTableProps {
|
||||
classes: ReturnType<typeof useStyles>
|
||||
numSelected: number
|
||||
onRequestSort: (event: React.MouseEvent<unknown>, property: keyof MapInfo) => void
|
||||
onSelectAllClick: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||
order: Order
|
||||
orderBy: string
|
||||
rowCount: number
|
||||
classes: ReturnType<typeof useStyles>;
|
||||
numSelected: number;
|
||||
onRequestSort: (event: React.MouseEvent<unknown>, property: keyof MapInfo) => void;
|
||||
onSelectAllClick: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
order: Order;
|
||||
orderBy: string;
|
||||
rowCount: number;
|
||||
}
|
||||
|
||||
function EnhancedTableHead(props: EnhancedTableProps) {
|
||||
const intl = useIntl()
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
classes,
|
||||
@ -101,11 +101,11 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
||||
numSelected,
|
||||
rowCount,
|
||||
onRequestSort,
|
||||
} = props
|
||||
} = props;
|
||||
|
||||
const createSortHandler = (property: keyof MapInfo) => (event: React.MouseEvent<unknown>) => {
|
||||
onRequestSort(event, property)
|
||||
}
|
||||
onRequestSort(event, property);
|
||||
};
|
||||
|
||||
const headCells: HeadCell[] = [
|
||||
{
|
||||
@ -126,7 +126,7 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
||||
label: intl.formatMessage({ id: 'map.last-update', defaultMessage: 'Last Update' }),
|
||||
style: { width: '70px', whiteSpace: 'nowrap' },
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
return (
|
||||
<TableHead>
|
||||
@ -176,7 +176,7 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
||||
)}
|
||||
</TableSortLabel>
|
||||
</TableCell>
|
||||
)
|
||||
);
|
||||
})}
|
||||
|
||||
<TableCell
|
||||
@ -186,195 +186,195 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
||||
></TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
type ActionPanelState = {
|
||||
el: HTMLElement | undefined
|
||||
mapId: number
|
||||
}
|
||||
el: HTMLElement | undefined;
|
||||
mapId: number;
|
||||
};
|
||||
|
||||
interface MapsListProps {
|
||||
filter: Filter
|
||||
filter: Filter;
|
||||
}
|
||||
|
||||
const mapsFilter = (filter: Filter, search: string): ((mapInfo: MapInfo) => boolean) => {
|
||||
return (mapInfo: MapInfo) => {
|
||||
// Check for filter condition
|
||||
let result = false
|
||||
let result = false;
|
||||
switch (filter.type) {
|
||||
case 'all':
|
||||
result = true
|
||||
break
|
||||
result = true;
|
||||
break;
|
||||
case 'starred':
|
||||
result = mapInfo.starred
|
||||
break
|
||||
result = mapInfo.starred;
|
||||
break;
|
||||
case 'owned':
|
||||
result = mapInfo.role == 'owner'
|
||||
break
|
||||
result = mapInfo.role == 'owner';
|
||||
break;
|
||||
case 'shared':
|
||||
result = mapInfo.role != 'owner'
|
||||
break
|
||||
result = mapInfo.role != 'owner';
|
||||
break;
|
||||
case 'label':
|
||||
result =
|
||||
!mapInfo.labels || mapInfo.labels.includes((filter as LabelFilter).label.id)
|
||||
break
|
||||
!mapInfo.labels || mapInfo.labels.includes((filter as LabelFilter).label.id);
|
||||
break;
|
||||
case 'public':
|
||||
result = mapInfo.isPublic
|
||||
break
|
||||
result = mapInfo.isPublic;
|
||||
break;
|
||||
default:
|
||||
result = false
|
||||
result = false;
|
||||
}
|
||||
|
||||
// Does it match search filter criteria...
|
||||
if (search && result) {
|
||||
result = mapInfo.title.toLowerCase().indexOf(search.toLowerCase()) != -1
|
||||
result = mapInfo.title.toLowerCase().indexOf(search.toLowerCase()) != -1;
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
export const MapsList = (props: MapsListProps): React.ReactElement => {
|
||||
const classes = useStyles()
|
||||
const [order, setOrder] = React.useState<Order>('asc')
|
||||
const [filter, setFilter] = React.useState<Filter>({ type: 'all' })
|
||||
const classes = useStyles();
|
||||
const [order, setOrder] = React.useState<Order>('asc');
|
||||
const [filter, setFilter] = React.useState<Filter>({ type: 'all' });
|
||||
|
||||
const [orderBy, setOrderBy] = React.useState<keyof MapInfo>('lastModificationTime')
|
||||
const [selected, setSelected] = React.useState<number[]>([])
|
||||
const [searchCondition, setSearchCondition] = React.useState<string>('')
|
||||
const [orderBy, setOrderBy] = React.useState<keyof MapInfo>('lastModificationTime');
|
||||
const [selected, setSelected] = React.useState<number[]>([]);
|
||||
const [searchCondition, setSearchCondition] = React.useState<string>('');
|
||||
|
||||
const [page, setPage] = React.useState(0)
|
||||
const [rowsPerPage, setRowsPerPage] = React.useState(10)
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const intl = useIntl()
|
||||
const [page, setPage] = React.useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = React.useState(10);
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const intl = useIntl();
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// Configure locale ...
|
||||
const account = fetchAccount()
|
||||
const account = fetchAccount();
|
||||
if (account) {
|
||||
dayjs.locale(account.locale.code)
|
||||
dayjs.locale(account.locale.code);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setSelected([])
|
||||
setPage(0)
|
||||
setFilter(props.filter)
|
||||
}, [props.filter.type, (props.filter as LabelFilter).label])
|
||||
setSelected([]);
|
||||
setPage(0);
|
||||
setFilter(props.filter);
|
||||
}, [props.filter.type, (props.filter as LabelFilter).label]);
|
||||
|
||||
const { isLoading, data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', () => {
|
||||
return client.fetchAllMaps()
|
||||
})
|
||||
const mapsInfo: MapInfo[] = data ? data.filter(mapsFilter(filter, searchCondition)) : []
|
||||
return client.fetchAllMaps();
|
||||
});
|
||||
const mapsInfo: MapInfo[] = data ? data.filter(mapsFilter(filter, searchCondition)) : [];
|
||||
|
||||
const [activeRowAction, setActiveRowAction] = React.useState<ActionPanelState | undefined>(
|
||||
undefined
|
||||
)
|
||||
);
|
||||
type ActiveDialog = {
|
||||
actionType: ActionType
|
||||
mapsId: number[]
|
||||
}
|
||||
actionType: ActionType;
|
||||
mapsId: number[];
|
||||
};
|
||||
|
||||
const [activeDialog, setActiveDialog] = React.useState<ActiveDialog | undefined>(undefined)
|
||||
const [activeDialog, setActiveDialog] = React.useState<ActiveDialog | undefined>(undefined);
|
||||
const handleRequestSort = (event: React.MouseEvent<unknown>, property: keyof MapInfo) => {
|
||||
const isAsc = orderBy === property && order === 'asc'
|
||||
setOrder(isAsc ? 'desc' : 'asc')
|
||||
setOrderBy(property)
|
||||
}
|
||||
const isAsc = orderBy === property && order === 'asc';
|
||||
setOrder(isAsc ? 'desc' : 'asc');
|
||||
setOrderBy(property);
|
||||
};
|
||||
|
||||
const handleSelectAllClick = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
if (event.target.checked) {
|
||||
const newSelecteds = mapsInfo.map((n) => n.id)
|
||||
setSelected(newSelecteds)
|
||||
return
|
||||
const newSelecteds = mapsInfo.map((n) => n.id);
|
||||
setSelected(newSelecteds);
|
||||
return;
|
||||
}
|
||||
setSelected([])
|
||||
}
|
||||
setSelected([]);
|
||||
};
|
||||
|
||||
const handleRowClick = (event: React.MouseEvent<unknown>, id: number): void => {
|
||||
const selectedIndex = selected.indexOf(id)
|
||||
let newSelected: number[] = []
|
||||
const selectedIndex = selected.indexOf(id);
|
||||
let newSelected: number[] = [];
|
||||
|
||||
if (selectedIndex === -1) {
|
||||
newSelected = newSelected.concat(selected, id)
|
||||
newSelected = newSelected.concat(selected, id);
|
||||
} else if (selectedIndex === 0) {
|
||||
newSelected = newSelected.concat(selected.slice(1))
|
||||
newSelected = newSelected.concat(selected.slice(1));
|
||||
} else if (selectedIndex === selected.length - 1) {
|
||||
newSelected = newSelected.concat(selected.slice(0, -1))
|
||||
newSelected = newSelected.concat(selected.slice(0, -1));
|
||||
} else if (selectedIndex > 0) {
|
||||
newSelected = newSelected.concat(
|
||||
selected.slice(0, selectedIndex),
|
||||
selected.slice(selectedIndex + 1)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
setSelected(newSelected)
|
||||
}
|
||||
setSelected(newSelected);
|
||||
};
|
||||
|
||||
const handleChangePage = (event: unknown, newPage: number) => {
|
||||
setPage(newPage)
|
||||
}
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setRowsPerPage(parseInt(event.target.value, 10))
|
||||
setPage(0)
|
||||
}
|
||||
setRowsPerPage(parseInt(event.target.value, 10));
|
||||
setPage(0);
|
||||
};
|
||||
|
||||
const handleActionClick = (mapId: number): ((event) => void) => {
|
||||
return (event): void => {
|
||||
setActiveRowAction({
|
||||
mapId: mapId,
|
||||
el: event.currentTarget,
|
||||
})
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
});
|
||||
event.stopPropagation();
|
||||
};
|
||||
};
|
||||
|
||||
const starredMultation = useMutation<void, ErrorInfo, number>(
|
||||
(id: number) => {
|
||||
const map = mapsInfo.find((m) => m.id == id)
|
||||
return client.updateStarred(id, !map?.starred)
|
||||
const map = mapsInfo.find((m) => m.id == id);
|
||||
return client.updateStarred(id, !map?.starred);
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries('maps')
|
||||
queryClient.invalidateQueries('maps');
|
||||
},
|
||||
onError: () => {
|
||||
// setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleStarred = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>, id: number) => {
|
||||
event.stopPropagation()
|
||||
starredMultation.mutate(id)
|
||||
}
|
||||
event.stopPropagation();
|
||||
starredMultation.mutate(id);
|
||||
};
|
||||
|
||||
const handleActionMenuClose = (action: ActionType): void => {
|
||||
if (action) {
|
||||
const mapId = activeRowAction?.mapId
|
||||
const mapId = activeRowAction?.mapId;
|
||||
|
||||
setActiveDialog({
|
||||
actionType: action as ActionType,
|
||||
mapsId: [mapId] as number[],
|
||||
})
|
||||
});
|
||||
}
|
||||
setActiveRowAction(undefined)
|
||||
}
|
||||
setActiveRowAction(undefined);
|
||||
};
|
||||
|
||||
const handleOnSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchCondition(e.target.value)
|
||||
}
|
||||
setSearchCondition(e.target.value);
|
||||
};
|
||||
|
||||
const handleDeleteClick = () => {
|
||||
setActiveDialog({
|
||||
actionType: 'delete',
|
||||
mapsId: selected,
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const isSelected = (id: number) => selected.indexOf(id) !== -1
|
||||
const isSelected = (id: number) => selected.indexOf(id) !== -1;
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<ActionChooser
|
||||
@ -480,8 +480,8 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
||||
stableSort(mapsInfo, getComparator(order, orderBy))
|
||||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||
.map((row: MapInfo) => {
|
||||
const isItemSelected = isSelected(row.id)
|
||||
const labelId = row.id
|
||||
const isItemSelected = isSelected(row.id);
|
||||
const labelId = row.id;
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
@ -592,7 +592,7 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
||||
</Tooltip>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
);
|
||||
})
|
||||
)}
|
||||
</TableBody>
|
||||
@ -606,5 +606,5 @@ export const MapsList = (props: MapsListProps): React.ReactElement => {
|
||||
mapsId={activeDialog ? activeDialog.mapsId : []}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { fade } from '@material-ui/core/styles'
|
||||
import { Theme } from '@material-ui/core/styles/createMuiTheme'
|
||||
import createStyles from '@material-ui/core/styles/createStyles'
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles'
|
||||
import { fade } from '@material-ui/core/styles';
|
||||
import { Theme } from '@material-ui/core/styles/createMuiTheme';
|
||||
import createStyles from '@material-ui/core/styles/createStyles';
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles';
|
||||
|
||||
export const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@ -100,4 +100,4 @@ export const useStyles = makeStyles((theme: Theme) =>
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React from 'react'
|
||||
import React from 'react';
|
||||
|
||||
import Tooltip from '@material-ui/core/Tooltip'
|
||||
import PersonSharpIcon from '@material-ui/icons/PersonSharp'
|
||||
import EditSharpIcon from '@material-ui/icons/EditSharp'
|
||||
import VisibilitySharpIcon from '@material-ui/icons/VisibilitySharp'
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import PersonSharpIcon from '@material-ui/icons/PersonSharp';
|
||||
import EditSharpIcon from '@material-ui/icons/EditSharp';
|
||||
import VisibilitySharpIcon from '@material-ui/icons/VisibilitySharp';
|
||||
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { Role } from '../../../classes/client'
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Role } from '../../../classes/client';
|
||||
|
||||
type RoleIconProps = {
|
||||
role: Role
|
||||
}
|
||||
role: Role;
|
||||
};
|
||||
|
||||
const RoleIcon = ({ role }: RoleIconProps): React.ReactElement => {
|
||||
return (
|
||||
@ -42,7 +42,7 @@ const RoleIcon = ({ role }: RoleIconProps): React.ReactElement => {
|
||||
</Tooltip>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default RoleIcon
|
||||
export default RoleIcon;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Theme } from '@material-ui/core/styles/createMuiTheme'
|
||||
import createStyles from '@material-ui/core/styles/createStyles'
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles'
|
||||
import { Theme } from '@material-ui/core/styles/createMuiTheme';
|
||||
import createStyles from '@material-ui/core/styles/createStyles';
|
||||
import makeStyles from '@material-ui/core/styles/makeStyles';
|
||||
|
||||
const drawerWidth = 300
|
||||
const drawerWidth = 300;
|
||||
|
||||
export const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@ -60,4 +60,4 @@ export const useStyles = makeStyles((theme: Theme) =>
|
||||
padding: theme.spacing(3),
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1,60 +1,60 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
import ReCAPTCHA from 'react-google-recaptcha'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import Client, { ErrorInfo } from '../../classes/client'
|
||||
import FormContainer from '../layout/form-container'
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import ReCAPTCHA from 'react-google-recaptcha';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import Client, { ErrorInfo } from '../../classes/client';
|
||||
import FormContainer from '../layout/form-container';
|
||||
|
||||
import Header from '../layout/header'
|
||||
import Footer from '../layout/footer'
|
||||
import Header from '../layout/header';
|
||||
import Footer from '../layout/footer';
|
||||
|
||||
import { useSelector } from 'react-redux'
|
||||
import { useMutation } from 'react-query'
|
||||
import { activeInstance } from '../../redux/clientSlice'
|
||||
import Input from '../form/input'
|
||||
import GlobalError from '../form/global-error'
|
||||
import SubmitButton from '../form/submit-button'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import FormControl from '@material-ui/core/FormControl'
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useMutation } from 'react-query';
|
||||
import { activeInstance } from '../../redux/clientSlice';
|
||||
import Input from '../form/input';
|
||||
import GlobalError from '../form/global-error';
|
||||
import SubmitButton from '../form/submit-button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
|
||||
export type Model = {
|
||||
email: string
|
||||
lastname: string
|
||||
firstname: string
|
||||
password: string
|
||||
recaptcha: string
|
||||
}
|
||||
email: string;
|
||||
lastname: string;
|
||||
firstname: string;
|
||||
password: string;
|
||||
recaptcha: string;
|
||||
};
|
||||
|
||||
const defaultModel: Model = { email: '', lastname: '', firstname: '', password: '', recaptcha: '' }
|
||||
const defaultModel: Model = { email: '', lastname: '', firstname: '', password: '', recaptcha: '' };
|
||||
const RegistrationForm = () => {
|
||||
const [model, setModel] = useState<Model>(defaultModel)
|
||||
const [error, setError] = useState<ErrorInfo>()
|
||||
const history = useHistory()
|
||||
const intl = useIntl()
|
||||
const [model, setModel] = useState<Model>(defaultModel);
|
||||
const [error, setError] = useState<ErrorInfo>();
|
||||
const history = useHistory();
|
||||
const intl = useIntl();
|
||||
|
||||
const Client: Client = useSelector(activeInstance)
|
||||
const Client: Client = useSelector(activeInstance);
|
||||
const mutation = useMutation<void, ErrorInfo, Model>(
|
||||
(model: Model) => Client.registerNewUser({ ...model }),
|
||||
{
|
||||
onSuccess: () => history.push('/c/registration-success'),
|
||||
onError: (error) => {
|
||||
setError(error)
|
||||
setError(error);
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||
event.preventDefault()
|
||||
mutation.mutate(model)
|
||||
}
|
||||
event.preventDefault();
|
||||
mutation.mutate(model);
|
||||
};
|
||||
|
||||
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
event.preventDefault()
|
||||
event.preventDefault();
|
||||
|
||||
const name = event.target.name
|
||||
const value = event.target.value
|
||||
setModel({ ...model, [name as keyof Model]: value })
|
||||
}
|
||||
const name = event.target.name;
|
||||
const value = event.target.value;
|
||||
setModel({ ...model, [name as keyof Model]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<FormContainer>
|
||||
@ -125,8 +125,8 @@ const RegistrationForm = () => {
|
||||
<ReCAPTCHA
|
||||
sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
|
||||
onChange={(value: string) => {
|
||||
model.recaptcha = value
|
||||
setModel(model)
|
||||
model.recaptcha = value;
|
||||
setModel(model);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -147,13 +147,13 @@ const RegistrationForm = () => {
|
||||
</form>
|
||||
</FormControl>
|
||||
</FormContainer>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const RegistationPage = (): React.ReactElement => {
|
||||
useEffect(() => {
|
||||
document.title = 'Registration | WiseMapping'
|
||||
})
|
||||
document.title = 'Registration | WiseMapping';
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -161,7 +161,7 @@ const RegistationPage = (): React.ReactElement => {
|
||||
<RegistrationForm />
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default RegistationPage
|
||||
export default RegistationPage;
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import FormContainer from '../layout/form-container'
|
||||
import Header from '../layout/header'
|
||||
import Footer from '../layout/footer'
|
||||
import { Link as RouterLink } from 'react-router-dom'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import React, { useEffect } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import FormContainer from '../layout/form-container';
|
||||
import Header from '../layout/header';
|
||||
import Footer from '../layout/footer';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Button from '@material-ui/core/Button';
|
||||
|
||||
const RegistrationSuccessPage = (): React.ReactElement => {
|
||||
useEffect(() => {
|
||||
document.title = 'Reset Password | WiseMapping'
|
||||
})
|
||||
document.title = 'Reset Password | WiseMapping';
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -43,7 +43,7 @@ const RegistrationSuccessPage = (): React.ReactElement => {
|
||||
</FormContainer>
|
||||
<Footer />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default RegistrationSuccessPage
|
||||
export default RegistrationSuccessPage;
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import App from './app'
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './app';
|
||||
|
||||
async function bootstrapApplication() {
|
||||
ReactDOM.render(<App />, document.getElementById('root') as HTMLElement)
|
||||
ReactDOM.render(<App />, document.getElementById('root') as HTMLElement);
|
||||
}
|
||||
|
||||
bootstrapApplication()
|
||||
bootstrapApplication();
|
||||
|
@ -1,53 +1,53 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
import { useQuery } from 'react-query'
|
||||
import Client, { AccountInfo, ErrorInfo, MapInfo } from '../classes/client'
|
||||
import MockClient from '../classes/client/mock-client'
|
||||
import RestClient from '../classes/client/rest-client'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { useQuery } from 'react-query';
|
||||
import Client, { AccountInfo, ErrorInfo, MapInfo } from '../classes/client';
|
||||
import MockClient from '../classes/client/mock-client';
|
||||
import RestClient from '../classes/client/rest-client';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
interface ConfigInfo {
|
||||
apiBaseUrl: string
|
||||
apiBaseUrl: string;
|
||||
}
|
||||
|
||||
class RutimeConfig {
|
||||
private config: ConfigInfo
|
||||
private config: ConfigInfo;
|
||||
load() {
|
||||
// Config can be inserted in the html page to define the global properties ...
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this.config = (window as any).serverconfig
|
||||
return this
|
||||
this.config = (window as any).serverconfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
buildClient(): Client {
|
||||
let result: Client
|
||||
let result: Client;
|
||||
if (this.config) {
|
||||
result = new RestClient(this.config.apiBaseUrl, () => {
|
||||
sessionExpired()
|
||||
})
|
||||
console.log('Service using rest client. ' + JSON.stringify(this.config))
|
||||
sessionExpired();
|
||||
});
|
||||
console.log('Service using rest client. ' + JSON.stringify(this.config));
|
||||
} else {
|
||||
console.log('Warning:Service using mockservice client')
|
||||
result = new MockClient()
|
||||
console.log('Warning:Service using mockservice client');
|
||||
result = new MockClient();
|
||||
}
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ClientStatus {
|
||||
state: 'healthy' | 'session-expired'
|
||||
msg?: string
|
||||
state: 'healthy' | 'session-expired';
|
||||
msg?: string;
|
||||
}
|
||||
|
||||
export interface ClientState {
|
||||
instance: Client
|
||||
status: ClientStatus
|
||||
instance: Client;
|
||||
status: ClientStatus;
|
||||
}
|
||||
|
||||
const initialState: ClientState = {
|
||||
instance: new RutimeConfig().load().buildClient(),
|
||||
status: { state: 'healthy' },
|
||||
}
|
||||
};
|
||||
|
||||
export const clientSlice = createSlice({
|
||||
name: 'client',
|
||||
@ -57,45 +57,45 @@ export const clientSlice = createSlice({
|
||||
state.status = {
|
||||
state: 'session-expired',
|
||||
msg: 'Sessions has expired. You need to login again',
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
type MapLoadResult = {
|
||||
isLoading: boolean
|
||||
error: ErrorInfo | null
|
||||
map: MapInfo | null
|
||||
}
|
||||
isLoading: boolean;
|
||||
error: ErrorInfo | null;
|
||||
map: MapInfo | null;
|
||||
};
|
||||
|
||||
export const fetchMapById = (id: number): MapLoadResult => {
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, MapInfo[]>('maps', () => {
|
||||
return client.fetchAllMaps()
|
||||
})
|
||||
return client.fetchAllMaps();
|
||||
});
|
||||
|
||||
const result = data?.find((m) => m.id == id)
|
||||
const map = result || null
|
||||
return { isLoading: isLoading, error: error, map: map }
|
||||
}
|
||||
const result = data?.find((m) => m.id == id);
|
||||
const map = result || null;
|
||||
return { isLoading: isLoading, error: error, map: map };
|
||||
};
|
||||
|
||||
export const fetchAccount = (): AccountInfo | undefined => {
|
||||
const client: Client = useSelector(activeInstance)
|
||||
const client: Client = useSelector(activeInstance);
|
||||
const { data } = useQuery<unknown, ErrorInfo, AccountInfo>('account', () => {
|
||||
return client.fetchAccountInfo()
|
||||
})
|
||||
return data
|
||||
}
|
||||
return client.fetchAccountInfo();
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const activeInstance = (state: any): Client => {
|
||||
return state.client.instance
|
||||
}
|
||||
return state.client.instance;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const activeInstanceStatus = (state: any): ClientStatus => {
|
||||
return state.client.status
|
||||
}
|
||||
return state.client.status;
|
||||
};
|
||||
|
||||
export const { sessionExpired } = clientSlice.actions
|
||||
export default clientSlice.reducer
|
||||
export const { sessionExpired } = clientSlice.actions;
|
||||
export default clientSlice.reducer;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { configureStore } from '@reduxjs/toolkit'
|
||||
import clientReducer from './clientSlice'
|
||||
import { configureStore } from '@reduxjs/toolkit';
|
||||
import clientReducer from './clientSlice';
|
||||
|
||||
// Create Service object...
|
||||
const store = configureStore({
|
||||
reducer: {
|
||||
client: clientReducer,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
export default store
|
||||
export default store;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import createMuiTheme from '@material-ui/core/styles/createMuiTheme'
|
||||
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
|
||||
|
||||
const theme = createMuiTheme({
|
||||
overrides: {
|
||||
@ -71,6 +71,6 @@ const theme = createMuiTheme({
|
||||
contrastText: '#FFFFFF',
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
export { theme }
|
||||
export { theme };
|
||||
|
Loading…
Reference in New Issue
Block a user