mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-25 23:54:55 +01:00
Complete history channel
This commit is contained in:
parent
87a12c25b1
commit
85d44786c7
@ -23,15 +23,18 @@
|
|||||||
"action.history": {
|
"action.history": {
|
||||||
"defaultMessage": "History"
|
"defaultMessage": "History"
|
||||||
},
|
},
|
||||||
|
"action.history-description": {
|
||||||
|
"defaultMessage": "List of changes introduced in the last 90 days."
|
||||||
|
},
|
||||||
|
"action.history-title": {
|
||||||
|
"defaultMessage": "Version history"
|
||||||
|
},
|
||||||
"action.import": {
|
"action.import": {
|
||||||
"defaultMessage": "Import"
|
"defaultMessage": "Import"
|
||||||
},
|
},
|
||||||
"action.info": {
|
"action.info": {
|
||||||
"defaultMessage": "Info"
|
"defaultMessage": "Info"
|
||||||
},
|
},
|
||||||
"action.info-title": {
|
|
||||||
"defaultMessage": "Info"
|
|
||||||
},
|
|
||||||
"action.label": {
|
"action.label": {
|
||||||
"defaultMessage": "Add Label"
|
"defaultMessage": "Add Label"
|
||||||
},
|
},
|
||||||
@ -50,6 +53,12 @@
|
|||||||
"action.rename": {
|
"action.rename": {
|
||||||
"defaultMessage": "Rename"
|
"defaultMessage": "Rename"
|
||||||
},
|
},
|
||||||
|
"action.rename-description-placeholder": {
|
||||||
|
"defaultMessage": "Description"
|
||||||
|
},
|
||||||
|
"action.rename-name-placeholder": {
|
||||||
|
"defaultMessage": "Name"
|
||||||
|
},
|
||||||
"action.share": {
|
"action.share": {
|
||||||
"defaultMessage": "Share"
|
"defaultMessage": "Share"
|
||||||
},
|
},
|
||||||
@ -68,6 +77,12 @@
|
|||||||
"duplicate.title": {
|
"duplicate.title": {
|
||||||
"defaultMessage": "Duplicate"
|
"defaultMessage": "Duplicate"
|
||||||
},
|
},
|
||||||
|
"expired.description": {
|
||||||
|
"defaultMessage": "Your current session has expired. Please, sign in and try again."
|
||||||
|
},
|
||||||
|
"expired.title": {
|
||||||
|
"defaultMessage": "Your session has expired"
|
||||||
|
},
|
||||||
"footer.aboutus": {
|
"footer.aboutus": {
|
||||||
"defaultMessage": "About Us"
|
"defaultMessage": "About Us"
|
||||||
},
|
},
|
||||||
@ -116,6 +131,9 @@
|
|||||||
"login.desc": {
|
"login.desc": {
|
||||||
"defaultMessage": "Log into your account"
|
"defaultMessage": "Log into your account"
|
||||||
},
|
},
|
||||||
|
"login.email": {
|
||||||
|
"defaultMessage": "Email"
|
||||||
|
},
|
||||||
"login.error": {
|
"login.error": {
|
||||||
"defaultMessage": "The email address or password you entered is not valid."
|
"defaultMessage": "The email address or password you entered is not valid."
|
||||||
},
|
},
|
||||||
@ -126,6 +144,9 @@
|
|||||||
"defaultMessage": "Although HSQLDB is bundled with WiseMapping by default during the installation, we do not recommend this database for production use. Please consider using MySQL 5.7 instead. You can find more information how to configure MySQL",
|
"defaultMessage": "Although HSQLDB is bundled with WiseMapping by default during the installation, we do not recommend this database for production use. Please consider using MySQL 5.7 instead. You can find more information how to configure MySQL",
|
||||||
"description": "Missing production database configured"
|
"description": "Missing production database configured"
|
||||||
},
|
},
|
||||||
|
"login.password": {
|
||||||
|
"defaultMessage": "Password"
|
||||||
|
},
|
||||||
"login.remberme": {
|
"login.remberme": {
|
||||||
"defaultMessage": "Remember me"
|
"defaultMessage": "Remember me"
|
||||||
},
|
},
|
||||||
@ -141,6 +162,33 @@
|
|||||||
"login.userinactive": {
|
"login.userinactive": {
|
||||||
"defaultMessage": "Sorry, your account has not been activated yet. You'll receive a notification email when it becomes active. Stay tuned!."
|
"defaultMessage": "Sorry, your account has not been activated yet. You'll receive a notification email when it becomes active. Stay tuned!."
|
||||||
},
|
},
|
||||||
|
"map.creator": {
|
||||||
|
"defaultMessage": "Creator"
|
||||||
|
},
|
||||||
|
"map.last-update": {
|
||||||
|
"defaultMessage": "Last Update"
|
||||||
|
},
|
||||||
|
"map.more-actions": {
|
||||||
|
"defaultMessage": "More Actions"
|
||||||
|
},
|
||||||
|
"map.name": {
|
||||||
|
"defaultMessage": "Name"
|
||||||
|
},
|
||||||
|
"maps.empty-result": {
|
||||||
|
"defaultMessage": "No matching record found with the current filter criteria."
|
||||||
|
},
|
||||||
|
"maps.modified": {
|
||||||
|
"defaultMessage": "Modified"
|
||||||
|
},
|
||||||
|
"maps.modified-by": {
|
||||||
|
"defaultMessage": "Modified By"
|
||||||
|
},
|
||||||
|
"maps.revert": {
|
||||||
|
"defaultMessage": "Revert"
|
||||||
|
},
|
||||||
|
"maps.view": {
|
||||||
|
"defaultMessage": "View"
|
||||||
|
},
|
||||||
"menu.account": {
|
"menu.account": {
|
||||||
"defaultMessage": "Account"
|
"defaultMessage": "Account"
|
||||||
},
|
},
|
||||||
|
@ -25,7 +25,7 @@ export type MapInfo = {
|
|||||||
role: 'owner' | 'editor' | 'viewer'
|
role: 'owner' | 'editor' | 'viewer'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HistoryChange = {
|
export type ChangeHistory = {
|
||||||
id: number;
|
id: number;
|
||||||
creator: string;
|
creator: string;
|
||||||
modified: string;
|
modified: string;
|
||||||
@ -62,6 +62,9 @@ interface Client {
|
|||||||
|
|
||||||
registerNewUser(user: NewUser): Promise<void>;
|
registerNewUser(user: NewUser): Promise<void>;
|
||||||
resetPassword(email: string): Promise<void>;
|
resetPassword(email: string): Promise<void>;
|
||||||
|
|
||||||
|
fetchHistory(id:number):Promise<ChangeHistory[]>;
|
||||||
|
revertHistory(id:number,cid:number): Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Client, { BasicMapInfo, Label, MapInfo, NewUser } from '..';
|
import Client, { BasicMapInfo, ChangeHistory, Label, MapInfo, NewUser } from '..';
|
||||||
|
|
||||||
class MockClient implements Client {
|
class MockClient implements Client {
|
||||||
private maps: MapInfo[] = [];
|
private maps: MapInfo[] = [];
|
||||||
@ -41,6 +41,9 @@ class MockClient implements Client {
|
|||||||
];
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
revertHistory(id: number, cid: number): Promise<void> {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
createMap(map: BasicMapInfo): Promise<number> {
|
createMap(map: BasicMapInfo): Promise<number> {
|
||||||
throw new Error("Method not implemented.");
|
throw new Error("Method not implemented.");
|
||||||
@ -91,6 +94,46 @@ class MockClient implements Client {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
fetchHistory(id: number): Promise<ChangeHistory[]> {
|
||||||
|
const result = [{
|
||||||
|
id: 1,
|
||||||
|
creator: 'Paulo',
|
||||||
|
modified: '2008-06-02T00:00:00Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
creator: 'Paulo',
|
||||||
|
modified: '2008-06-02T00:00:00Z'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
creator: 'Paulo',
|
||||||
|
modified: '2008-06-02T00:00:00Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
creator: 'Paulo',
|
||||||
|
modified: '2008-06-02T00:00:00Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
creator: 'Paulo',
|
||||||
|
modified: '2008-06-02T00:00:00Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
creator: 'Paulo',
|
||||||
|
modified: '2008-06-02T00:00:00Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
creator: 'Paulo',
|
||||||
|
modified: '2008-06-02T00:00:00Z'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return Promise.resolve(result);
|
||||||
|
}
|
||||||
|
|
||||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number> {
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import Client, { ErrorInfo, MapInfo, BasicMapInfo, NewUser, Label } from '..';
|
import Client, { ErrorInfo, MapInfo, BasicMapInfo, NewUser, Label, ChangeHistory } from '..';
|
||||||
|
|
||||||
export default class RestClient implements Client {
|
export default class RestClient implements Client {
|
||||||
private baseUrl: string;
|
private baseUrl: string;
|
||||||
@ -11,6 +11,14 @@ export default class RestClient implements Client {
|
|||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
this.sessionExpired = sessionExpired;
|
this.sessionExpired = sessionExpired;
|
||||||
}
|
}
|
||||||
|
revertHistory(id: number, cid: number): Promise<void> {
|
||||||
|
// '/c/restful/maps/${mindmapId}/history'
|
||||||
|
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
fetchHistory(id: number): Promise<ChangeHistory[]> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
fetchMapInfo(id: number): Promise<BasicMapInfo> {
|
fetchMapInfo(id: number): Promise<BasicMapInfo> {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
@ -29,7 +37,7 @@ export default class RestClient implements Client {
|
|||||||
case 401:
|
case 401:
|
||||||
case 302:
|
case 302:
|
||||||
this.sessionExpired();
|
this.sessionExpired();
|
||||||
result = { msg: intl.formatMessage({ id: "expired.title", defaultMessage: "Your current session has expired. Please, sign in and try again." })}
|
result = { msg: intl.formatMessage({ id: "expired.description", defaultMessage: "Your current session has expired. Please, sign in and try again." })}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -47,6 +47,18 @@
|
|||||||
"value": "History"
|
"value": "History"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"action.history-description": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "List of changes introduced in the last 90 days."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"action.history-title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Version history"
|
||||||
|
}
|
||||||
|
],
|
||||||
"action.import": [
|
"action.import": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
@ -59,12 +71,6 @@
|
|||||||
"value": "Info"
|
"value": "Info"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"action.info-title": [
|
|
||||||
{
|
|
||||||
"type": 0,
|
|
||||||
"value": "Info"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"action.label": [
|
"action.label": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
@ -101,6 +107,18 @@
|
|||||||
"value": "Rename"
|
"value": "Rename"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"action.rename-description-placeholder": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Description"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"action.rename-name-placeholder": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Name"
|
||||||
|
}
|
||||||
|
],
|
||||||
"action.share": [
|
"action.share": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
@ -137,6 +155,18 @@
|
|||||||
"value": "Duplicate"
|
"value": "Duplicate"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"expired.description": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Your current session has expired. Please, sign in and try again."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"expired.title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Your session has expired"
|
||||||
|
}
|
||||||
|
],
|
||||||
"footer.aboutus": [
|
"footer.aboutus": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
@ -233,6 +263,12 @@
|
|||||||
"value": "Log into your account"
|
"value": "Log into your account"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"login.email": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Email"
|
||||||
|
}
|
||||||
|
],
|
||||||
"login.error": [
|
"login.error": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
@ -251,6 +287,12 @@
|
|||||||
"value": "Although HSQLDB is bundled with WiseMapping by default during the installation, we do not recommend this database for production use. Please consider using MySQL 5.7 instead. You can find more information how to configure MySQL"
|
"value": "Although HSQLDB is bundled with WiseMapping by default during the installation, we do not recommend this database for production use. Please consider using MySQL 5.7 instead. You can find more information how to configure MySQL"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"login.password": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Password"
|
||||||
|
}
|
||||||
|
],
|
||||||
"login.remberme": [
|
"login.remberme": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
@ -281,6 +323,60 @@
|
|||||||
"value": "Sorry, your account has not been activated yet. You'll receive a notification email when it becomes active. Stay tuned!."
|
"value": "Sorry, your account has not been activated yet. You'll receive a notification email when it becomes active. Stay tuned!."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"map.creator": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Creator"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"map.last-update": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Last Update"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"map.more-actions": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "More Actions"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"map.name": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Name"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maps.empty-result": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "No matching record found with the current filter criteria."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maps.modified": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Modified"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maps.modified-by": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Modified By"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maps.revert": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Revert"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maps.view": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "View"
|
||||||
|
}
|
||||||
|
],
|
||||||
"menu.account": [
|
"menu.account": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
|
@ -49,7 +49,7 @@ const ForgotPassword = () => {
|
|||||||
<GlobalError error={error} />
|
<GlobalError error={error} />
|
||||||
|
|
||||||
<form onSubmit={handleOnSubmit}>
|
<form onSubmit={handleOnSubmit}>
|
||||||
<Input type="email" name="email" label={{ id: "forgot.email", defaultMessage: "Email" }}
|
<Input type="email" name="email" label={intl.formatMessage({ id: "forgot.email", defaultMessage: "Email" })}
|
||||||
autoComplete="email" onChange={e => setEmail(e.target.value)} error={error}/>
|
autoComplete="email" onChange={e => setEmail(e.target.value)} error={error}/>
|
||||||
|
|
||||||
<SubmitButton value={intl.formatMessage({ id: "forgot.register", defaultMessage: "Send recovery link" })} />
|
<SubmitButton value={intl.formatMessage({ id: "forgot.register", defaultMessage: "Send recovery link" })} />
|
||||||
|
@ -7,7 +7,7 @@ type InputProps = {
|
|||||||
name: string;
|
name: string;
|
||||||
error?: ErrorInfo;
|
error?: ErrorInfo;
|
||||||
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
|
onChange?: (event: ChangeEvent<HTMLInputElement>) => void;
|
||||||
label: MessageDescriptor;
|
label: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
type: string;
|
type: string;
|
||||||
value?: string
|
value?: string
|
||||||
@ -27,7 +27,7 @@ const Input = (props: InputProps) => {
|
|||||||
const fullWidth = props.fullWidth != undefined ? props.required : true;
|
const fullWidth = props.fullWidth != undefined ? props.required : true;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextField name={name} type={props.type} label={intl.formatMessage(props.label)}
|
<TextField name={name} type={props.type} label={props.label}
|
||||||
value={value} onChange={onChange}
|
value={value} onChange={onChange}
|
||||||
error={Boolean(fieldError)} helperText={fieldError}
|
error={Boolean(fieldError)} helperText={fieldError}
|
||||||
variant="outlined" required={required} fullWidth={fullWidth} margin="dense"/>
|
variant="outlined" required={required} fullWidth={fullWidth} margin="dense"/>
|
||||||
|
@ -67,8 +67,8 @@ const LoginPage = () => {
|
|||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<form action="/c/perform-login" method="POST" >
|
<form action="/c/perform-login" method="POST" >
|
||||||
<Input name="username" type="email" label={{ id: "login.email", defaultMessage: "Email" }} required autoComplete="email" />
|
<Input name="username" type="email" label={intl.formatMessage({ id: "login.email", defaultMessage: "Email" })} required autoComplete="email" />
|
||||||
<Input name="password" type="password" label={{ id: "login.password", defaultMessage: "Password" }} required autoComplete="current-password" />
|
<Input name="password" type="password" label={intl.formatMessage({ id: "login.password", defaultMessage: "Password" })} required autoComplete="current-password" />
|
||||||
<div>
|
<div>
|
||||||
<input name="_spring_security_login.remberme" id="staySignIn" type="checkbox" />
|
<input name="_spring_security_login.remberme" id="staySignIn" type="checkbox" />
|
||||||
<label htmlFor="staySignIn"><FormattedMessage id="login.remberme" defaultMessage="Remember me" /></label>
|
<label htmlFor="staySignIn"><FormattedMessage id="login.remberme" defaultMessage="Remember me" /></label>
|
||||||
|
@ -68,10 +68,10 @@ const CreateDialog = (props: CreateProps) => {
|
|||||||
submitButton={intl.formatMessage({ id: 'create.button', defaultMessage: 'Create' })}>
|
submitButton={intl.formatMessage({ id: 'create.button', defaultMessage: 'Create' })}>
|
||||||
|
|
||||||
<FormControl fullWidth={true}>
|
<FormControl fullWidth={true}>
|
||||||
<Input name="title" type="text" label={{ id: "action.rename-name-placeholder", defaultMessage: "Name" }}
|
<Input name="title" type="text" label={intl.formatMessage({ id: "action.rename-name-placeholder", defaultMessage: "Name" })}
|
||||||
value={model.title} onChange={handleOnChange} error={error} fullWidth={true} />
|
value={model.title} onChange={handleOnChange} error={error} fullWidth={true} />
|
||||||
|
|
||||||
<Input name="description" type="text" label={{ id: "action.rename-description-placeholder", defaultMessage: "Description" }}
|
<Input name="description" type="text" label={intl.formatMessage({ id: "action.rename-description-placeholder", defaultMessage: "Description" })}
|
||||||
value={model.description} onChange={handleOnChange} required={false} fullWidth={true} />
|
value={model.description} onChange={handleOnChange} required={false} fullWidth={true} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
|
@ -77,10 +77,10 @@ const DuplicateDialog = (props: DialogProps) => {
|
|||||||
submitButton={intl.formatMessage({ id: 'duplicate.title', defaultMessage: 'Duplicate' })}>
|
submitButton={intl.formatMessage({ id: 'duplicate.title', defaultMessage: 'Duplicate' })}>
|
||||||
|
|
||||||
<FormControl fullWidth={true}>
|
<FormControl fullWidth={true}>
|
||||||
<Input name="title" type="text" label={{ id: "action.rename-name-placeholder", defaultMessage: "Name" }}
|
<Input name="title" type="text" label={intl.formatMessage({ id: "action.rename-name-placeholder", defaultMessage: "Name" })}
|
||||||
value={model.title} onChange={handleOnChange} error={error} fullWidth={true} />
|
value={model.title} onChange={handleOnChange} error={error} fullWidth={true} />
|
||||||
|
|
||||||
<Input name="description" type="text" label={{ id: "action.rename-description-placeholder", defaultMessage: "Description" }}
|
<Input name="description" type="text" label={intl.formatMessage({ id: "action.rename-description-placeholder", defaultMessage: "Description" })}
|
||||||
value={model.description} onChange={handleOnChange} required={false} fullWidth={true} />
|
value={model.description} onChange={handleOnChange} required={false} fullWidth={true} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
import React, { ErrorInfo } from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import Client, { ChangeHistory } from "../../../../client";
|
||||||
|
import { activeInstance } from '../../../../redux/clientSlice';
|
||||||
|
import { DialogProps, fetchMapById, handleOnMutationSuccess } from "..";
|
||||||
|
import BaseDialog from "../base-dialog";
|
||||||
|
import { Link, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Tooltip } from "@material-ui/core";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
|
||||||
|
const HistoryDialog = (props: DialogProps) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const mapId = props.mapId;
|
||||||
|
|
||||||
|
const client: Client = useSelector(activeInstance);
|
||||||
|
const { isLoading, error, data } = useQuery<unknown, ErrorInfo, ChangeHistory[]>('history', () => {
|
||||||
|
return client.fetchHistory(mapId);
|
||||||
|
});
|
||||||
|
const changeHistory: ChangeHistory[] = data ? data : [];
|
||||||
|
|
||||||
|
const handleOnClose = (): void => {
|
||||||
|
props.onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnClick = (event,vid): void => {
|
||||||
|
event.preventDefault();
|
||||||
|
client.revertHistory(mapId,vid)
|
||||||
|
.then((mapId)=>{
|
||||||
|
handleOnClose();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<BaseDialog
|
||||||
|
open={props.open} onClose={handleOnClose}
|
||||||
|
title={intl.formatMessage({ id: "action.history-title", defaultMessage: "Version history" })}
|
||||||
|
description={intl.formatMessage({ id: "action.history-description", defaultMessage: "List of changes introduced in the last 90 days." })} >
|
||||||
|
<TableContainer component={Paper} style={{ maxHeight: '200px' }}>
|
||||||
|
<Table size="small" stickyHeader>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell align="left"><FormattedMessage id="maps.modified-by" defaultMessage="Modified By" /></TableCell>
|
||||||
|
<TableCell align="left"><FormattedMessage id="maps.modified" defaultMessage="Modified" /></TableCell>
|
||||||
|
<TableCell align="left"></TableCell>
|
||||||
|
<TableCell align="left"></TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{changeHistory.map((row) => (
|
||||||
|
<TableRow key={row.id}>
|
||||||
|
<TableCell align="left">{row.creator}</TableCell>
|
||||||
|
<TableCell align="left">
|
||||||
|
<Tooltip title={moment(row.modified).format("lll")} placement="bottom-start">
|
||||||
|
<span>{moment(row.modified).fromNow()}</span>
|
||||||
|
</Tooltip>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align="left"><Link href={`c/maps/${mapId}/${row.id}/view`} target="history"><FormattedMessage id="maps.view" defaultMessage="View" /></Link></TableCell>
|
||||||
|
<TableCell align="left"><Link href="#" onClick={(e)=>handleOnClick(e,row.id)}><FormattedMessage id="maps.revert" defaultMessage="Revert" /></Link></TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
|
||||||
|
</BaseDialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HistoryDialog;
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import RenameDialog from './rename';
|
import RenameDialog from './rename-dialog';
|
||||||
import DeleteDialog from './delete-dialog';
|
import DeleteDialog from './delete-dialog';
|
||||||
import { ActionType } from '../action-chooser';
|
import { ActionType } from '../action-chooser';
|
||||||
import { ErrorInfo, MapInfo } from '../../../client';
|
import { ErrorInfo, MapInfo } from '../../../client';
|
||||||
@ -10,6 +10,7 @@ import { activeInstance } from '../../../redux/clientSlice';
|
|||||||
import DuplicateDialog from './duplicate-dialog';
|
import DuplicateDialog from './duplicate-dialog';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import CreateDialog from './create-dialog';
|
import CreateDialog from './create-dialog';
|
||||||
|
import HistoryDialog from './history-dialog';
|
||||||
|
|
||||||
export type BasicMapInfo = {
|
export type BasicMapInfo = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -46,6 +47,7 @@ const ActionDispatcher = (props: ActionDialogProps) => {
|
|||||||
<DeleteDialog open={action === 'delete'} onClose={handleOnClose} mapId={mapId} />
|
<DeleteDialog open={action === 'delete'} onClose={handleOnClose} mapId={mapId} />
|
||||||
<RenameDialog open={action === 'rename'} onClose={handleOnClose} mapId={mapId} />
|
<RenameDialog open={action === 'rename'} onClose={handleOnClose} mapId={mapId} />
|
||||||
<DuplicateDialog open={action === 'duplicate'} onClose={handleOnClose} mapId={mapId} />
|
<DuplicateDialog open={action === 'duplicate'} onClose={handleOnClose} mapId={mapId} />
|
||||||
|
<HistoryDialog open={action === 'history'} onClose={handleOnClose} mapId={mapId} />
|
||||||
</span >
|
</span >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -76,10 +76,10 @@ const RenameDialog = (props: DialogProps) => {
|
|||||||
submitButton={intl.formatMessage({ id: 'rename.title', defaultMessage: 'Rename' })}>
|
submitButton={intl.formatMessage({ id: 'rename.title', defaultMessage: 'Rename' })}>
|
||||||
|
|
||||||
<FormControl fullWidth={true}>
|
<FormControl fullWidth={true}>
|
||||||
<Input name="title" type="text" label={{ id: "action.rename-name-placeholder", defaultMessage: "Name" }}
|
<Input name="title" type="text" label={intl.formatMessage({ id: "action.rename-name-placeholder", defaultMessage: "Name" })}
|
||||||
value={model.title} onChange={handleOnChange} error={error} fullWidth={true} />
|
value={model.title} onChange={handleOnChange} error={error} fullWidth={true} />
|
||||||
|
|
||||||
<Input name="description" type="text" label={{ id: "action.rename-description-placeholder", defaultMessage: "Description" }}
|
<Input name="description" type="text" label={intl.formatMessage({ id: "action.rename-description-placeholder", defaultMessage: "Description" })}
|
||||||
value={model.description} onChange={handleOnChange} required={false} fullWidth={true} />
|
value={model.description} onChange={handleOnChange} required={false} fullWidth={true} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
@ -259,7 +259,7 @@ const HandleClientStatus = () => {
|
|||||||
|
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Alert severity="error">
|
<Alert severity="error">
|
||||||
<AlertTitle><FormattedMessage id="expired.title" defaultMessage="Your current session has expired. Please, sign in and try again." /></AlertTitle>
|
<AlertTitle><FormattedMessage id="expired.description" defaultMessage="Your current session has expired. Please, sign in and try again." /></AlertTitle>
|
||||||
</Alert>
|
</Alert>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import { Button, InputBase, Link } from '@material-ui/core';
|
|||||||
import SearchIcon from '@material-ui/icons/Search';
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { Filter, LabelFilter } from '..';
|
import { Filter, LabelFilter } from '..';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage, useIntl } from 'react-intl';
|
||||||
import { DeleteOutlined, LabelTwoTone } from '@material-ui/icons';
|
import { DeleteOutlined, LabelTwoTone } from '@material-ui/icons';
|
||||||
import Alert from '@material-ui/lab/Alert';
|
import Alert from '@material-ui/lab/Alert';
|
||||||
|
|
||||||
@ -71,12 +71,6 @@ interface HeadCell {
|
|||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
const headCells: HeadCell[] = [
|
|
||||||
{ id: 'title', numeric: false, label: 'Name' },
|
|
||||||
{ id: 'labels', numeric: false },
|
|
||||||
{ id: 'creator', numeric: false, label: 'Creator', style: { width: '60px' } },
|
|
||||||
{ id: 'modified', numeric: true, label: 'Last Update', style: { width: '30px' } }
|
|
||||||
];
|
|
||||||
|
|
||||||
interface EnhancedTableProps {
|
interface EnhancedTableProps {
|
||||||
classes: ReturnType<typeof useStyles>;
|
classes: ReturnType<typeof useStyles>;
|
||||||
@ -89,12 +83,21 @@ interface EnhancedTableProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function EnhancedTableHead(props: EnhancedTableProps) {
|
function EnhancedTableHead(props: EnhancedTableProps) {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
const { classes, onSelectAllClick, order, orderBy, numSelected, rowCount, onRequestSort } = props;
|
const { classes, onSelectAllClick, order, orderBy, numSelected, rowCount, onRequestSort } = props;
|
||||||
|
|
||||||
const createSortHandler = (property: keyof MapInfo) => (event: React.MouseEvent<unknown>) => {
|
const createSortHandler = (property: keyof MapInfo) => (event: React.MouseEvent<unknown>) => {
|
||||||
onRequestSort(event, property);
|
onRequestSort(event, property);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const headCells: HeadCell[] = [
|
||||||
|
{ id: 'title', numeric: false, label: intl.formatMessage({ id: 'map.name', defaultMessage: 'Name' }) },
|
||||||
|
{ id: 'labels', numeric: false },
|
||||||
|
{ id: 'creator', numeric: false, label: intl.formatMessage({ id: 'map.creator', defaultMessage: 'Creator' }), style: { width: '70px', whiteSpace: 'nowrap' } },
|
||||||
|
{ id: 'modified', numeric: true, label: intl.formatMessage({ id: 'map.last-update', defaultMessage: 'Last Update' }), style: { width: '70px', whiteSpace: 'nowrap' } }
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
@ -196,6 +199,7 @@ export const MapsList = (props: MapsListProps) => {
|
|||||||
const [page, setPage] = React.useState(0);
|
const [page, setPage] = React.useState(0);
|
||||||
const [rowsPerPage, setRowsPerPage] = React.useState(10);
|
const [rowsPerPage, setRowsPerPage] = React.useState(10);
|
||||||
const client: Client = useSelector(activeInstance);
|
const client: Client = useSelector(activeInstance);
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelected([]);
|
setSelected([]);
|
||||||
@ -456,7 +460,7 @@ export const MapsList = (props: MapsListProps) => {
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell className={classes.bodyCell}>
|
||||||
<Tooltip title="Others">
|
<Tooltip title={intl.formatMessage({ id: 'map.more-actions', defaultMessage: 'More Actions' })}>
|
||||||
<IconButton aria-label="Others" size="small" onClick={handleActionClick(row.id)}>
|
<IconButton aria-label="Others" size="small" onClick={handleActionClick(row.id)}>
|
||||||
<MoreHorizIcon color="action" />
|
<MoreHorizIcon color="action" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
@ -71,16 +71,16 @@ const RegistrationForm = () => {
|
|||||||
<form onSubmit={handleOnSubmit}>
|
<form onSubmit={handleOnSubmit}>
|
||||||
<GlobalError error={error} />
|
<GlobalError error={error} />
|
||||||
|
|
||||||
<Input name="email" type="email" onChange={handleOnChange} label={{ id: "registration.email", defaultMessage: "Email" }}
|
<Input name="email" type="email" onChange={handleOnChange} label={intl.formatMessage({ id: "registration.email", defaultMessage: "Email" })}
|
||||||
autoComplete="email" error={error}/>
|
autoComplete="email" error={error}/>
|
||||||
|
|
||||||
<Input name="firstname" type="text" onChange={handleOnChange} label={{ id: "registration.firstname", defaultMessage: "First Name" }}
|
<Input name="firstname" type="text" onChange={handleOnChange} label={intl.formatMessage({ id: "registration.firstname", defaultMessage: "First Name" })}
|
||||||
autoComplete="given-name" error={error}/>
|
autoComplete="given-name" error={error}/>
|
||||||
|
|
||||||
<Input name="lastname" type="text" onChange={handleOnChange} label={{ id: "registration.lastname", defaultMessage: "Last Name" }}
|
<Input name="lastname" type="text" onChange={handleOnChange} label={intl.formatMessage({ id: "registration.lastname", defaultMessage: "Last Name" })}
|
||||||
autoComplete="family-name" error={error}/>
|
autoComplete="family-name" error={error}/>
|
||||||
|
|
||||||
<Input name="password" type="password" onChange={handleOnChange} label={{ id: "registration.password", defaultMessage: "Password" }}
|
<Input name="password" type="password" onChange={handleOnChange} label={intl.formatMessage({ id: "registration.password", defaultMessage: "Password" })}
|
||||||
autoComplete="new-password" error={error}/>
|
autoComplete="new-password" error={error}/>
|
||||||
|
|
||||||
<div style={{ width: '330px', padding: '5px 0px 5px 20px' }}>
|
<div style={{ width: '330px', padding: '5px 0px 5px 20px' }}>
|
||||||
|
Loading…
Reference in New Issue
Block a user