WIP: Add delete action for sharing

This commit is contained in:
Paulo Gustavo Veiga 2021-02-19 18:41:49 -08:00
parent cf3b2c90f7
commit 8703e14612
6 changed files with 302 additions and 17 deletions

View File

@ -1,4 +1,22 @@
{ {
"account.delete-warning": {
"defaultMessage": "Keep in mind that you will not be able retrieve any mindmap you have added. All your information will be deleted and it can not be restored."
},
"accountinfo.button": {
"defaultMessage": "Accept"
},
"accountinfo.email": {
"defaultMessage": "Email"
},
"accountinfo.firstname": {
"defaultMessage": "First Name"
},
"accountinfo.lastname": {
"defaultMessage": "Last Name"
},
"accountinfo.title": {
"defaultMessage": "Account info"
},
"action.cancel-button": { "action.cancel-button": {
"defaultMessage": "Cancel" "defaultMessage": "Cancel"
}, },
@ -62,6 +80,24 @@
"action.share": { "action.share": {
"defaultMessage": "Share" "defaultMessage": "Share"
}, },
"changepwd.button": {
"defaultMessage": "Change"
},
"changepwd.confirm-password": {
"defaultMessage": "Confirm Password"
},
"changepwd.description": {
"defaultMessage": "Please, provide the new password for your account."
},
"changepwd.password": {
"defaultMessage": "Password"
},
"changepwd.password-match": {
"defaultMessage": "Password do not match. Please, try again."
},
"changepwd.title": {
"defaultMessage": "Change Password"
},
"common.wait": { "common.wait": {
"defaultMessage": "Please wait ..." "defaultMessage": "Please wait ..."
}, },
@ -149,6 +185,9 @@
"header.haveaccount": { "header.haveaccount": {
"defaultMessage": "Already have an account?" "defaultMessage": "Already have an account?"
}, },
"help.support": {
"defaultMessage": "Support"
},
"history.no-changes": { "history.no-changes": {
"defaultMessage": "There is no changes available" "defaultMessage": "There is no changes available"
}, },
@ -203,7 +242,7 @@
"language.change": { "language.change": {
"defaultMessage": "Change Language" "defaultMessage": "Change Language"
}, },
"languange.help": { "language.help": {
"defaultMessage": "Help to Translate" "defaultMessage": "Help to Translate"
}, },
"login.desc": { "login.desc": {
@ -279,6 +318,9 @@
"menu.account": { "menu.account": {
"defaultMessage": "Account" "defaultMessage": "Account"
}, },
"menu.change-password": {
"defaultMessage": "Change password"
},
"menu.signout": { "menu.signout": {
"defaultMessage": "Sign Out" "defaultMessage": "Sign Out"
}, },
@ -341,5 +383,38 @@
}, },
"resetpassword.success.title": { "resetpassword.success.title": {
"defaultMessage": "Your account has been created successfully" "defaultMessage": "Your account has been created successfully"
},
"role.editor": {
"defaultMessage": "Editor"
},
"role.owner": {
"defaultMessage": "Onwer"
},
"role.viewer": {
"defaultMessage": "Viewer"
},
"share.add-button": {
"defaultMessage": "Add"
},
"share.add-message": {
"defaultMessage": "Add message"
},
"share.can-edit": {
"defaultMessage": "Can edit"
},
"share.can-view": {
"defaultMessage": "Can view"
},
"share.delete": {
"defaultMessage": "Delete collaborator"
},
"share.delete-description": {
"defaultMessage": "Invite people to collaborate with you in the creation of your midnmap. They will be notified by email."
},
"share.delete-title": {
"defaultMessage": "Share with people"
},
"share.message": {
"defaultMessage": "Message"
} }
} }

View File

@ -80,8 +80,10 @@ interface Client {
deleteMap(id: number): Promise<void>; deleteMap(id: number): Promise<void>;
renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>; renameMap(id: number, basicInfo: BasicMapInfo): Promise<void>;
fetchAllMaps(): Promise<MapInfo[]>; fetchAllMaps(): Promise<MapInfo[]>;
fetchMapPermissions(id: number): Promise<Permission[]>; fetchMapPermissions(id: number): Promise<Permission[]>;
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void>; 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>;

View File

@ -36,6 +36,12 @@ class MockClient implements Client {
{ id: 2, title: "Blue Label", iconName: "", color: 'blue' } { 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();
}
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> { addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
let perm = this.permissionsByMap.get(id) || []; let perm = this.permissionsByMap.get(id) || [];
@ -50,9 +56,17 @@ class MockClient implements Client {
let perm = this.permissionsByMap.get(id); let perm = this.permissionsByMap.get(id);
if (!perm) { if (!perm) {
perm = [{ perm = [{
name: 'Cosme Sharing', name: 'Cosme Editor',
email: 'pepe@gmail.com', email: 'pepe@example.com',
role: 'editor' role: 'editor'
}, {
name: 'Cosme Owner',
email: 'pepe2@example.com',
role: 'owner'
}, {
name: 'Cosme Viewer',
email: 'pepe3@example.com',
role: 'viewer'
}]; }];
this.permissionsByMap.set(id, perm); this.permissionsByMap.set(id, perm);
} }

View File

@ -11,6 +11,10 @@ export default class RestClient implements Client {
this.sessionExpired = sessionExpired; this.sessionExpired = sessionExpired;
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
deleteMapPermission(id: number, email: string): Promise<void> {
throw new Error('Method not implemented.');
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> { addMapPermissions(id: number, message: string, permissions: Permission[]): Promise<void> {
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }

View File

@ -1,4 +1,40 @@
{ {
"account.delete-warning": [
{
"type": 0,
"value": "Keep in mind that you will not be able retrieve any mindmap you have added. All your information will be deleted and it can not be restored."
}
],
"accountinfo.button": [
{
"type": 0,
"value": "Accept"
}
],
"accountinfo.email": [
{
"type": 0,
"value": "Email"
}
],
"accountinfo.firstname": [
{
"type": 0,
"value": "First Name"
}
],
"accountinfo.lastname": [
{
"type": 0,
"value": "Last Name"
}
],
"accountinfo.title": [
{
"type": 0,
"value": "Account info"
}
],
"action.cancel-button": [ "action.cancel-button": [
{ {
"type": 0, "type": 0,
@ -125,6 +161,42 @@
"value": "Share" "value": "Share"
} }
], ],
"changepwd.button": [
{
"type": 0,
"value": "Change"
}
],
"changepwd.confirm-password": [
{
"type": 0,
"value": "Confirm Password"
}
],
"changepwd.description": [
{
"type": 0,
"value": "Please, provide the new password for your account."
}
],
"changepwd.password": [
{
"type": 0,
"value": "Password"
}
],
"changepwd.password-match": [
{
"type": 0,
"value": "Password do not match. Please, try again."
}
],
"changepwd.title": [
{
"type": 0,
"value": "Change Password"
}
],
"common.wait": [ "common.wait": [
{ {
"type": 0, "type": 0,
@ -179,6 +251,12 @@
"value": "Mindmap Tools: Export your mindmap in thirdparty mindmap tool formats" "value": "Mindmap Tools: Export your mindmap in thirdparty mindmap tool formats"
} }
], ],
"export.document-label": [
{
"type": 0,
"value": "Document: Export your mindmap in a self-contained document ready to share"
}
],
"export.image": [ "export.image": [
{ {
"type": 0, "type": 0,
@ -194,7 +272,7 @@
"export.warning": [ "export.warning": [
{ {
"type": 0, "type": 0,
"value": "Exporting to Image (SVG,PNG,JPEG )is available only in the editor toolbar." "value": "Exporting to Image (SVG,PNG,JPEG,PDF) is only available in the editor toolbar."
} }
], ],
"footer.aboutus": [ "footer.aboutus": [
@ -293,6 +371,12 @@
"value": "Already have an account?" "value": "Already have an account?"
} }
], ],
"help.support": [
{
"type": 0,
"value": "Support"
}
],
"history.no-changes": [ "history.no-changes": [
{ {
"type": 0, "type": 0,
@ -395,6 +479,18 @@
"value": "Info" "value": "Info"
} }
], ],
"language.change": [
{
"type": 0,
"value": "Change Language"
}
],
"language.help": [
{
"type": 0,
"value": "Help to Translate"
}
],
"login.desc": [ "login.desc": [
{ {
"type": 0, "type": 0,
@ -539,6 +635,12 @@
"value": "Account" "value": "Account"
} }
], ],
"menu.change-password": [
{
"type": 0,
"value": "Change password"
}
],
"menu.signout": [ "menu.signout": [
{ {
"type": 0, "type": 0,
@ -664,5 +766,71 @@
"type": 0, "type": 0,
"value": "Your account has been created successfully" "value": "Your account has been created successfully"
} }
],
"role.editor": [
{
"type": 0,
"value": "Editor"
}
],
"role.owner": [
{
"type": 0,
"value": "Onwer"
}
],
"role.viewer": [
{
"type": 0,
"value": "Viewer"
}
],
"share.add-button": [
{
"type": 0,
"value": "Add"
}
],
"share.add-message": [
{
"type": 0,
"value": "Add message"
}
],
"share.can-edit": [
{
"type": 0,
"value": "Can edit"
}
],
"share.can-view": [
{
"type": 0,
"value": "Can view"
}
],
"share.delete": [
{
"type": 0,
"value": "Delete collaborator"
}
],
"share.delete-description": [
{
"type": 0,
"value": "Invite people to collaborate with you in the creation of your midnmap. They will be notified by email."
}
],
"share.delete-title": [
{
"type": 0,
"value": "Share with people"
}
],
"share.message": [
{
"type": 0,
"value": "Message"
}
] ]
} }

View File

@ -23,6 +23,7 @@ import Checkbox from "@material-ui/core/Checkbox";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import { useStyles } from "./style"; import { useStyles } from "./style";
import RoleIcon from "../../role-icon"; import RoleIcon from "../../role-icon";
import { Tooltip } from "@material-ui/core";
type ShareModel = { type ShareModel = {
@ -41,7 +42,22 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
const [model, setModel] = React.useState<ShareModel>(defaultModel); const [model, setModel] = React.useState<ShareModel>(defaultModel);
const [error, setError] = React.useState<ErrorInfo>(); const [error, setError] = React.useState<ErrorInfo>();
const mutation = useMutation( const deleteMutation = useMutation(
(email: string) => {
return client.deleteMapPermission(mapId, email);
},
{
onSuccess: () => {
queryClient.invalidateQueries(`perm-${mapId}`);
setModel(defaultModel);
},
onError: (error: ErrorInfo) => {
setError(error);
}
}
);
const addMutation = useMutation(
(model: ShareModel) => { (model: ShareModel) => {
const emails = model.emails.split("'"); const emails = model.emails.split("'");
const permissions = emails.map((email) => { return { email: email, role: model.role } }); const permissions = emails.map((email) => { return { email: email, role: model.role } });
@ -70,9 +86,14 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
setModel({ ...model, [name as keyof ShareModel]: value }); setModel({ ...model, [name as keyof ShareModel]: value });
} }
const handleOnClick = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void => { const handleOnAddClick = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void => {
event.stopPropagation(); event.stopPropagation();
mutation.mutate(model); addMutation.mutate(model);
};
const handleOnDeleteClick = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>, email: string): void => {
event.stopPropagation();
deleteMutation.mutate(email);
}; };
const { isLoading, data: permissions = [] } = useQuery<unknown, ErrorInfo, Permission[]>(`perm-${mapId}`, () => { const { isLoading, data: permissions = [] } = useQuery<unknown, ErrorInfo, Permission[]>(`perm-${mapId}`, () => {
@ -84,7 +105,7 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
<BaseDialog <BaseDialog
onClose={handleOnClose} onClose={handleOnClose}
title={intl.formatMessage({ id: "share.delete-title", defaultMessage: "Share with people" })} title={intl.formatMessage({ id: "share.delete-title", defaultMessage: "Share with people" })}
description={intl.formatMessage({ id: "share.delete-description", defaultMessage: "Invite people to collaborate with you on the creation of your midnmap. They will be notified by email. " })} description={intl.formatMessage({ id: "share.delete-description", defaultMessage: "Invite people to collaborate with you in the creation of your midnmap. They will be notified by email. " })}
PaperProps={{ classes: { root: classes.paper } }} PaperProps={{ classes: { root: classes.paper } }}
error={error} error={error}
> >
@ -98,7 +119,7 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
size="small" size="small"
type="email" type="email"
variant="outlined" variant="outlined"
placeholder="Add collaboration email" placeholder="Add collaborator email"
label="Emails" label="Emails"
onChange={handleOnChange} onChange={handleOnChange}
value={model.emails} value={model.emails}
@ -129,7 +150,7 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
type="button" type="button"
variant="contained" variant="contained"
disableElevation={true} disableElevation={true}
onClick={handleOnClick}> onClick={handleOnAddClick}>
<FormattedMessage id="share.add-button" defaultMessage="Add " /> <FormattedMessage id="share.add-button" defaultMessage="Add " />
</Button> </Button>
@ -143,7 +164,7 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
name="message" name="message"
onChange={handleOnChange} onChange={handleOnChange}
value={model.message} value={model.message}
placeholder="Include a customize message to ..." label={intl.formatMessage({ id: 'share.message', defaultMessage: 'Message' })}
/> />
} }
</div> </div>
@ -154,14 +175,15 @@ const ShareDialog = ({ mapId, onClose }: SimpleDialogProps): React.ReactElement
{permissions && permissions.map((permission) => { {permissions && permissions.map((permission) => {
return ( return (
<ListItem key={permission.email} role={undefined} dense button> <ListItem key={permission.email} role={undefined} dense button>
<ListItemText id={`${permission.name}<${permission.email}>`} primary={permission.email} /> <ListItemText id={permission.email} primary={`${permission.name}<${permission.email}>`} />
<RoleIcon role={permission.role} /> <RoleIcon role={permission.role} />
< ListItemSecondaryAction >
<ListItemSecondaryAction> <Tooltip title={<FormattedMessage id="share.delete" defaultMessage="Delete collaborator" />}>
<IconButton edge="end"> <IconButton edge="end" disabled={permission.role == 'owner'} onClick={e => handleOnDeleteClick(e, permission.email)}>
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>
</Tooltip>
</ListItemSecondaryAction> </ListItemSecondaryAction>
</ListItem> </ListItem>
); );