Merged in feat/prettier (pull request #3)

adding back semicolons

* adding back semicolons
This commit is contained in:
Juan Allo 2021-02-23 07:02:15 +00:00
parent b63d7ee665
commit 3d538923a9
72 changed files with 1792 additions and 1792 deletions

View File

@ -1,7 +1,7 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": false,
"semi": true,
"singleQuote": true,
"printWidth": 100
}

View File

@ -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;

View File

@ -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;
`
`;

View File

@ -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;

View File

@ -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;
`
`;

View File

@ -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;

View File

@ -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;
`
`;

View File

@ -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;

View File

@ -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;
`
`;

View File

@ -1,3 +1,3 @@
import Editor from './components/frame'
import Editor from './components/frame';
export default Editor
export default Editor;

View File

@ -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`;

View File

@ -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();
});
});

View File

@ -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');
}
}

View File

@ -4,4 +4,4 @@
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}
};

View File

@ -1 +1 @@
import '@testing-library/cypress/add-commands'
import '@testing-library/cypress/add-commands';

View File

@ -1 +1 @@
import './commands'
import './commands';

View File

@ -1,2 +1,2 @@
declare module '*.png'
declare module '*.svg'
declare module '*.png';
declare module '*.svg';

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
};
}

View File

@ -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 };

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
`
`;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
`
`;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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',
},
})
)
);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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',
},
})
)
);

View File

@ -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;

View File

@ -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',
},
})
)
);

View File

@ -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;

View File

@ -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;

View File

@ -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',
},
})
)
);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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>
)
}
);
};

View File

@ -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) =>
},
},
})
)
);

View File

@ -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;

View File

@ -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),
},
})
)
);

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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 };