mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-25 23:54:55 +01:00
Complete public panel
This commit is contained in:
parent
c923c18cf9
commit
5f41821f00
@ -134,6 +134,15 @@
|
|||||||
"history.no-changes": {
|
"history.no-changes": {
|
||||||
"defaultMessage": "There is no changes available"
|
"defaultMessage": "There is no changes available"
|
||||||
},
|
},
|
||||||
|
"import.button": {
|
||||||
|
"defaultMessage": "Create"
|
||||||
|
},
|
||||||
|
"import.description": {
|
||||||
|
"defaultMessage": "You can import FreeMind 1.0.1 and WiseMapping maps to your list of maps. Select the file you want to import."
|
||||||
|
},
|
||||||
|
"import.title": {
|
||||||
|
"defaultMessage": "Import existing mindmap"
|
||||||
|
},
|
||||||
"login.desc": {
|
"login.desc": {
|
||||||
"defaultMessage": "Log into your account"
|
"defaultMessage": "Log into your account"
|
||||||
},
|
},
|
||||||
@ -201,6 +210,30 @@
|
|||||||
"menu.signout": {
|
"menu.signout": {
|
||||||
"defaultMessage": "Sign Out"
|
"defaultMessage": "Sign Out"
|
||||||
},
|
},
|
||||||
|
"publish.button": {
|
||||||
|
"defaultMessage": "Accept"
|
||||||
|
},
|
||||||
|
"publish.checkbox": {
|
||||||
|
"defaultMessage": "Enable public sharing"
|
||||||
|
},
|
||||||
|
"publish.description": {
|
||||||
|
"defaultMessage": "By publishing the map you make it visible to everyone on the Internet."
|
||||||
|
},
|
||||||
|
"publish.embedded": {
|
||||||
|
"defaultMessage": "Embedded"
|
||||||
|
},
|
||||||
|
"publish.embedded-msg": {
|
||||||
|
"defaultMessage": "Copy this snippet of code to embed in your blog or page:"
|
||||||
|
},
|
||||||
|
"publish.public-url": {
|
||||||
|
"defaultMessage": "Public URL"
|
||||||
|
},
|
||||||
|
"publish.public-url-msg": {
|
||||||
|
"defaultMessage": "Copy and paste the link below to share your map with colleagues:"
|
||||||
|
},
|
||||||
|
"publish.title": {
|
||||||
|
"defaultMessage": "Publish"
|
||||||
|
},
|
||||||
"registration.desc": {
|
"registration.desc": {
|
||||||
"defaultMessage": "Signing up is free and just take a moment"
|
"defaultMessage": "Signing up is free and just take a moment"
|
||||||
},
|
},
|
||||||
|
@ -55,6 +55,7 @@ interface Client {
|
|||||||
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>;
|
duplicateMap(id: number, basicInfo: BasicMapInfo): Promise<number>;
|
||||||
fetchMapInfo(id: number): Promise<BasicMapInfo>;
|
fetchMapInfo(id: number): Promise<BasicMapInfo>;
|
||||||
changeStarred(id: number, starred: boolean): Promise<void>;
|
changeStarred(id: number, starred: boolean): Promise<void>;
|
||||||
|
updateMapToPublic(id: number, starred: boolean): Promise<void>;
|
||||||
|
|
||||||
fetchLabels(): Promise<Label[]>;
|
fetchLabels(): Promise<Label[]>;
|
||||||
// createLabel(label: Label): Promise<void>;
|
// createLabel(label: Label): Promise<void>;
|
||||||
|
@ -54,15 +54,21 @@ class MockClient implements Client {
|
|||||||
return Promise.resolve(this.labels);
|
return Promise.resolve(this.labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
||||||
|
const mapInfo = this.maps.find(m => m.id == id);
|
||||||
|
if (mapInfo) {
|
||||||
|
mapInfo.isPublic = isPublic;
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
changeStarred(id: number, starred: boolean): Promise<void> {
|
changeStarred(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) {
|
if (!mapInfo) {
|
||||||
console.log(`Could not find the map iwth id ${id}`);
|
console.log(`Could not find the map iwth id ${id}`);
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
const newStarredValue = !mapInfo?.starred;
|
mapInfo.starred = starred;
|
||||||
mapInfo.starred = newStarredValue;
|
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,35 @@ export default class RestClient implements Client {
|
|||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
this.sessionExpired = sessionExpired;
|
this.sessionExpired = sessionExpired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMapToPublic(id: number, isPublic: boolean): Promise<void> {
|
||||||
|
/*
|
||||||
|
jQuery.ajax("c/restful/maps/${mindmap.id}/publish", {
|
||||||
|
async:false,
|
||||||
|
dataType:'json',
|
||||||
|
data:$('#dialogMainForm #enablePublicView')[0].checked ? 'true' : 'false',
|
||||||
|
type:'PUT',
|
||||||
|
contentType:"text/plain",
|
||||||
|
success:function (data, textStatus, jqXHR) {
|
||||||
|
$('#publish-dialog-modal').modal('hide');
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
const handler = (success: () => void, reject: (error: ErrorInfo) => void) => {
|
||||||
|
axios.put(`${this.baseUrl}/c/restful/maps/${id}/publish`,
|
||||||
|
isPublic,
|
||||||
|
{ headers: { 'Content-Type': 'text/plain' } }
|
||||||
|
).then(response => {
|
||||||
|
// All was ok, let's sent to success page ...;
|
||||||
|
success();
|
||||||
|
}).catch(error => {
|
||||||
|
const response = error.response;
|
||||||
|
const errorInfo = this.parseResponseOnError(response);
|
||||||
|
reject(errorInfo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Promise(handler);
|
||||||
|
}
|
||||||
revertHistory(id: number, cid: number): Promise<void> {
|
revertHistory(id: number, cid: number): Promise<void> {
|
||||||
// '/c/restful/maps/${mindmapId}/history'
|
// '/c/restful/maps/${mindmapId}/history'
|
||||||
|
|
||||||
@ -37,7 +66,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.description", 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) {
|
||||||
|
@ -269,6 +269,24 @@
|
|||||||
"value": "There is no changes available"
|
"value": "There is no changes available"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"import.button": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Create"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"import.description": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "You can import FreeMind 1.0.1 and WiseMapping maps to your list of maps. Select the file you want to import."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"import.title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Import existing mindmap"
|
||||||
|
}
|
||||||
|
],
|
||||||
"login.desc": [
|
"login.desc": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
@ -401,6 +419,54 @@
|
|||||||
"value": "Sign Out"
|
"value": "Sign Out"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"publish.button": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Accept"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publish.checkbox": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Enable public sharing"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publish.description": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "By publishing the map you make it visible to everyone on the Internet."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publish.embedded": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Embedded"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publish.embedded-msg": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Copy this snippet of code to embed in your blog or page:"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publish.public-url": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Public URL"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publish.public-url-msg": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Copy and paste the link below to share your map with colleagues:"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publish.title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Publish"
|
||||||
|
}
|
||||||
|
],
|
||||||
"registration.desc": [
|
"registration.desc": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
|
@ -12,15 +12,16 @@ import ShareOutlinedIcon from '@material-ui/icons/ShareOutlined';
|
|||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { LabelOutlined } from '@material-ui/icons';
|
import { LabelOutlined } from '@material-ui/icons';
|
||||||
|
|
||||||
export type ActionType = 'open' | 'share' | 'delete' | 'info' | 'create'| 'duplicate' | 'export' | 'label' | 'rename' | 'print' | 'info' | 'publish' | 'history' | undefined;
|
export type ActionType = 'open' | 'share' | 'import' | 'delete' | 'info' | 'create' | 'duplicate' | 'export' | 'label' | 'rename' | 'print' | 'info' | 'publish' | 'history' | undefined;
|
||||||
|
|
||||||
interface ActionProps {
|
interface ActionProps {
|
||||||
onClose: (action: ActionType) => void;
|
onClose: (action: ActionType) => void;
|
||||||
anchor: undefined | HTMLElement;
|
anchor: undefined | HTMLElement;
|
||||||
|
role: 'owner' | 'editor' | 'viewer'
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActionChooser = (props: ActionProps) => {
|
const ActionChooser = (props: ActionProps) => {
|
||||||
const { anchor, onClose } = props;
|
const { anchor, onClose, role } = props;
|
||||||
|
|
||||||
const handleOnClose = (action: ActionType): ((event: React.MouseEvent<HTMLLIElement>) => void) => {
|
const handleOnClose = (action: ActionType): ((event: React.MouseEvent<HTMLLIElement>) => void) => {
|
||||||
return (event): void => {
|
return (event): void => {
|
||||||
@ -38,12 +39,13 @@ const ActionChooser = (props: ActionProps) => {
|
|||||||
onClose={handleOnClose(undefined)}
|
onClose={handleOnClose(undefined)}
|
||||||
elevation={1}
|
elevation={1}
|
||||||
>
|
>
|
||||||
<MenuItem onClick={handleOnClose('open')} style={{width:"220px"}}>
|
<MenuItem onClick={handleOnClose('open')} style={{ width: "220px" }}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<DescriptionOutlinedIcon />
|
<DescriptionOutlinedIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<FormattedMessage id="action.open" defaultMessage="Open" />
|
<FormattedMessage id="action.open" defaultMessage="Open" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<MenuItem onClick={handleOnClose('duplicate')}>
|
<MenuItem onClick={handleOnClose('duplicate')}>
|
||||||
@ -53,12 +55,14 @@ const ActionChooser = (props: ActionProps) => {
|
|||||||
<FormattedMessage id="action.duplicate" defaultMessage="Duplicate" />
|
<FormattedMessage id="action.duplicate" defaultMessage="Duplicate" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
|
{role == 'owner' &&
|
||||||
<MenuItem onClick={handleOnClose('rename')}>
|
<MenuItem onClick={handleOnClose('rename')}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<EditOutlinedIcon />
|
<EditOutlinedIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<FormattedMessage id="action.rename" defaultMessage="Rename" />
|
<FormattedMessage id="action.rename" defaultMessage="Rename" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
}
|
||||||
|
|
||||||
<MenuItem onClick={handleOnClose('label')}>
|
<MenuItem onClick={handleOnClose('label')}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
@ -89,19 +93,23 @@ const ActionChooser = (props: ActionProps) => {
|
|||||||
<FormattedMessage id="action.print" defaultMessage="Print" />
|
<FormattedMessage id="action.print" defaultMessage="Print" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
|
{role != 'viewer' &&
|
||||||
<MenuItem onClick={handleOnClose('publish')}>
|
<MenuItem onClick={handleOnClose('publish')}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<PublicOutlinedIcon />
|
<PublicOutlinedIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<FormattedMessage id="action.publish" defaultMessage="Publish" />
|
<FormattedMessage id="action.publish" defaultMessage="Publish" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
}
|
||||||
|
|
||||||
|
{role != 'viewer' &&
|
||||||
<MenuItem onClick={handleOnClose('share')}>
|
<MenuItem onClick={handleOnClose('share')}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<ShareOutlinedIcon />
|
<ShareOutlinedIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<FormattedMessage id="action.share" defaultMessage="Share" />
|
<FormattedMessage id="action.share" defaultMessage="Share" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
}
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<MenuItem onClick={handleOnClose('info')}>
|
<MenuItem onClick={handleOnClose('info')}>
|
||||||
@ -111,12 +119,14 @@ const ActionChooser = (props: ActionProps) => {
|
|||||||
<FormattedMessage id="action.info" defaultMessage="Info" />
|
<FormattedMessage id="action.info" defaultMessage="Info" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
|
{role != 'viewer' &&
|
||||||
<MenuItem onClick={handleOnClose('history')}>
|
<MenuItem onClick={handleOnClose('history')}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<DeleteOutlinedIcon />
|
<DeleteOutlinedIcon />
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<FormattedMessage id="action.history" defaultMessage="History" />
|
<FormattedMessage id="action.history" defaultMessage="History" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
}
|
||||||
</Menu>);
|
</Menu>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ const BaseDialog = (props: DialogProps) => {
|
|||||||
(<FormattedMessage id="action.close-button" defaultMessage="Close" />)
|
(<FormattedMessage id="action.close-button" defaultMessage="Close" />)
|
||||||
}
|
}
|
||||||
</Button>
|
</Button>
|
||||||
{onSubmit ? (
|
{onSubmit &&
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
size="medium"
|
size="medium"
|
||||||
@ -66,7 +66,7 @@ const BaseDialog = (props: DialogProps) => {
|
|||||||
type="submit"
|
type="submit"
|
||||||
disableElevation={true}>
|
disableElevation={true}>
|
||||||
{props.submitButton}
|
{props.submitButton}
|
||||||
</Button>) : null
|
</Button>
|
||||||
}
|
}
|
||||||
</StyledDialogActions>
|
</StyledDialogActions>
|
||||||
</form>
|
</form>
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import { useMutation } from 'react-query';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { Button, FormControl } from '@material-ui/core';
|
||||||
|
|
||||||
|
|
||||||
|
import Client, { BasicMapInfo, ErrorInfo } from '../../../../client';
|
||||||
|
import { activeInstance } from '../../../../redux/clientSlice';
|
||||||
|
import Input from '../../../form/input';
|
||||||
|
import BaseDialog from '../base-dialog';
|
||||||
|
|
||||||
|
export type ImportModel = {
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CreateProps = {
|
||||||
|
open: boolean,
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultModel: ImportModel = { title: '', description: '' };
|
||||||
|
const ImportDialog = (props: CreateProps) => {
|
||||||
|
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.createMap(model);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: (mapId: number) => {
|
||||||
|
window.location.href = `/c/maps/${mapId}/edit`;
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
setError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleOnClose = (): void => {
|
||||||
|
props.onClose();
|
||||||
|
setModel(defaultModel);
|
||||||
|
setError(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||||
|
event.preventDefault();
|
||||||
|
mutation.mutate(model);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const name = event.target.name;
|
||||||
|
const value = event.target.value;
|
||||||
|
setModel({ ...model, [name as keyof BasicMapInfo]: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<BaseDialog onClose={handleOnClose} onSubmit={handleOnSubmit} error={error}
|
||||||
|
title={intl.formatMessage({ id: 'import.title', defaultMessage: 'Import existing mindmap' })}
|
||||||
|
description={intl.formatMessage({ id: 'import.description', defaultMessage: 'You can import FreeMind 1.0.1 and WiseMapping maps to your list of maps. Select the file you want to import.' })}
|
||||||
|
submitButton={intl.formatMessage({ id: 'import.button', defaultMessage: 'Create' })}>
|
||||||
|
|
||||||
|
<FormControl fullWidth={true}>
|
||||||
|
<Input name="title" type="text" label={intl.formatMessage({ id: "action.rename-name-placeholder", defaultMessage: "Name" })}
|
||||||
|
value={model.title} onChange={handleOnChange} error={error} fullWidth={true} />
|
||||||
|
|
||||||
|
<Input name="description" type="text" label={intl.formatMessage({ id: "action.rename-description-placeholder", defaultMessage: "Description" })}
|
||||||
|
value={model.description} onChange={handleOnChange} required={false} fullWidth={true} />
|
||||||
|
|
||||||
|
<input
|
||||||
|
accept="image/*"
|
||||||
|
id="contained-button-file"
|
||||||
|
type="file"
|
||||||
|
style={{display: 'none'}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="contained-button-file">
|
||||||
|
<Button variant="contained" color="primary" component="span">
|
||||||
|
Upload
|
||||||
|
</Button>
|
||||||
|
</label>
|
||||||
|
</FormControl>
|
||||||
|
</BaseDialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ImportDialog;
|
@ -11,6 +11,8 @@ 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';
|
import HistoryDialog from './history-dialog';
|
||||||
|
import ImportDialog from './import-dialog';
|
||||||
|
import PublishDialog from './publish-dialog';
|
||||||
|
|
||||||
export type BasicMapInfo = {
|
export type BasicMapInfo = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -44,11 +46,14 @@ const ActionDispatcher = (props: ActionDialogProps) => {
|
|||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
|
|
||||||
{action === 'create' ? <CreateDialog open={true} onClose={handleOnClose} /> : null}
|
{action === 'create' && <CreateDialog open={true} onClose={handleOnClose} /> }
|
||||||
{action === 'delete' ? <DeleteDialog open={true} onClose={handleOnClose} mapId={mapId} /> : null}
|
{action === 'delete' &&<DeleteDialog open={true} onClose={handleOnClose} mapId={mapId} />}
|
||||||
{action === 'rename' ? <RenameDialog open={true} onClose={handleOnClose} mapId={mapId} /> : null}
|
{action === 'rename' && <RenameDialog open={true} onClose={handleOnClose} mapId={mapId} />}
|
||||||
{action === 'duplicate' ? <DuplicateDialog open={true} onClose={handleOnClose} mapId={mapId} /> : null}
|
{action === 'duplicate' && <DuplicateDialog open={true} onClose={handleOnClose} mapId={mapId} />}
|
||||||
{action === 'history' ? <HistoryDialog open={true} onClose={handleOnClose} mapId={mapId} /> : null}
|
{action === 'history' && <HistoryDialog open={true} onClose={handleOnClose} mapId={mapId} />}
|
||||||
|
{action === 'import' && <ImportDialog open={true} onClose={handleOnClose} />}
|
||||||
|
{action === 'publish' && <PublishDialog onClose={handleOnClose} mapId={mapId}/>}
|
||||||
|
|
||||||
</span >
|
</span >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,121 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
import { useMutation, useQueryClient } from 'react-query';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { AppBar, Checkbox, FormControl, FormControlLabel, Tab, Typography } from '@material-ui/core';
|
||||||
|
|
||||||
|
|
||||||
|
import Client, { ErrorInfo } from '../../../../client';
|
||||||
|
import { activeInstance } from '../../../../redux/clientSlice';
|
||||||
|
import BaseDialog from '../base-dialog';
|
||||||
|
import { TabContext, TabList, TabPanel } from '@material-ui/lab';
|
||||||
|
import { fetchMapById, handleOnMutationSuccess } from '..';
|
||||||
|
|
||||||
|
export type PublishProps = {
|
||||||
|
mapId: number,
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const PublishDialog = (props: PublishProps) => {
|
||||||
|
const { mapId, onClose } = props;
|
||||||
|
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 [value, setValue] = React.useState('1');
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const mutation = useMutation<void, ErrorInfo, boolean>((model: boolean) => {
|
||||||
|
return client.updateMapToPublic(mapId, model);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
setModel(model);
|
||||||
|
handleOnMutationSuccess(onClose, queryClient);
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
setError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleOnClose = (): void => {
|
||||||
|
props.onClose();
|
||||||
|
setError(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
|
||||||
|
event.preventDefault();
|
||||||
|
mutation.mutate(model);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>, checked: boolean): void => {
|
||||||
|
event.preventDefault();
|
||||||
|
setModel(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleTabChange = (event, newValue) => {
|
||||||
|
setValue(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<BaseDialog onClose={handleOnClose} onSubmit={handleOnSubmit} error={error}
|
||||||
|
title={intl.formatMessage({ id: 'publish.title', defaultMessage: 'Publish' })}
|
||||||
|
description={intl.formatMessage({ id: 'publish.description', defaultMessage: 'By publishing the map you make it visible to everyone on the Internet.' })}
|
||||||
|
submitButton={intl.formatMessage({ id: 'publish.button', defaultMessage: 'Accept' })}>
|
||||||
|
|
||||||
|
<FormControl fullWidth={true}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
checked={model}
|
||||||
|
onChange={handleOnChange}
|
||||||
|
name="public"
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={intl.formatMessage({ id: 'publish.checkbox', defaultMessage: 'Enable public sharing' })}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<div style={!model ? { visibility: 'hidden' } : {}}>
|
||||||
|
<TabContext value={value}>
|
||||||
|
<AppBar position="static">
|
||||||
|
<TabList onChange={handleTabChange}>
|
||||||
|
<Tab label={intl.formatMessage({ id: 'publish.embedded', defaultMessage: 'Embedded' })} value="1" />
|
||||||
|
<Tab label={intl.formatMessage({ id: 'publish.public-url', defaultMessage: 'Public URL' })} value="2" />
|
||||||
|
</TabList>
|
||||||
|
</AppBar>
|
||||||
|
<TabPanel value="1">
|
||||||
|
<Typography variant="subtitle2">
|
||||||
|
<FormattedMessage id="publish.embedded-msg" defaultMessage="Copy this snippet of code to embed in your blog or page:" />
|
||||||
|
</Typography>
|
||||||
|
<p>
|
||||||
|
<textarea style={{ width: "100%" }}>
|
||||||
|
{`<iframe style="width:600px;height:400px;border:1px solid black" src="https://app.wisemapping.com/c/maps/${mapId}/embed?zoom=1.0"></iframe>`}
|
||||||
|
</textarea>
|
||||||
|
</p>
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel value="2">
|
||||||
|
<Typography variant="subtitle2">
|
||||||
|
<FormattedMessage id="publish.public-url-msg" defaultMessage="Copy and paste the link below to share your map with colleagues:" />
|
||||||
|
</Typography>
|
||||||
|
<p>
|
||||||
|
<textarea style={{ width: "100%" }}>
|
||||||
|
{`https://app.wisemapping.com/c/maps/${mapId}/public`}
|
||||||
|
</textarea>
|
||||||
|
</p>
|
||||||
|
</TabPanel>
|
||||||
|
</TabContext>
|
||||||
|
</div>
|
||||||
|
</BaseDialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default PublishDialog;
|
@ -105,7 +105,7 @@ const MapsPage = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<HandleClientStatus/>
|
<HandleClientStatus />
|
||||||
<AppBar
|
<AppBar
|
||||||
position="fixed"
|
position="fixed"
|
||||||
className={clsx(classes.appBar, {
|
className={clsx(classes.appBar, {
|
||||||
@ -129,8 +129,15 @@ const MapsPage = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip title="Import from external tools">
|
<Tooltip title="Import from external tools">
|
||||||
<Button color="primary" size="medium" variant="outlined" type="button"
|
<Button
|
||||||
disableElevation={true} startIcon={<CloudUploadTwoTone />} className={classes.importButton}>
|
color="primary"
|
||||||
|
size="medium"
|
||||||
|
variant="outlined"
|
||||||
|
type="button"
|
||||||
|
disableElevation={true}
|
||||||
|
startIcon={<CloudUploadTwoTone />}
|
||||||
|
className={classes.importButton}
|
||||||
|
onClick={e => setActiveDialog('import')}>
|
||||||
<FormattedMessage id="action.import" defaultMessage="Import" />
|
<FormattedMessage id="action.import" defaultMessage="Import" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -228,12 +235,13 @@ const StyleListItem = (props: ListItemProps) => {
|
|||||||
{icon}
|
{icon}
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText style={{ color: 'white' }} primary={label} />
|
<ListItemText style={{ color: 'white' }} primary={label} />
|
||||||
{filter.type == 'label' ?
|
{filter.type == 'label' &&
|
||||||
(<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
<IconButton edge="end" aria-label="delete" onClick={e => handleOnDelete(e, filter)}>
|
<IconButton edge="end" aria-label="delete" onClick={e => handleOnDelete(e, filter)}>
|
||||||
<DeleteOutlineTwoTone color="secondary" />
|
<DeleteOutlineTwoTone color="secondary" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</ListItemSecondaryAction>) : null}
|
</ListItemSecondaryAction>
|
||||||
|
}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -125,11 +125,13 @@ function EnhancedTableHead(props: EnhancedTableProps) {
|
|||||||
direction={orderBy === headCell.id ? order : 'asc'}
|
direction={orderBy === headCell.id ? order : 'asc'}
|
||||||
onClick={createSortHandler(headCell.id)}>
|
onClick={createSortHandler(headCell.id)}>
|
||||||
{headCell.label}
|
{headCell.label}
|
||||||
{orderBy === headCell.id ? (
|
|
||||||
|
{orderBy === headCell.id && (
|
||||||
<span className={classes.visuallyHidden}>
|
<span className={classes.visuallyHidden}>
|
||||||
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
)}
|
||||||
|
|
||||||
</TableSortLabel>
|
</TableSortLabel>
|
||||||
</TableCell>)
|
</TableCell>)
|
||||||
})}
|
})}
|
||||||
@ -321,7 +323,7 @@ export const MapsList = (props: MapsListProps) => {
|
|||||||
<Toolbar className={classes.toolbar} variant="dense">
|
<Toolbar className={classes.toolbar} variant="dense">
|
||||||
|
|
||||||
<div className={classes.toolbarActions}>
|
<div className={classes.toolbarActions}>
|
||||||
{selected.length > 0 ? (
|
{selected.length > 0 &&
|
||||||
<Tooltip title="Delete selected">
|
<Tooltip title="Delete selected">
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
@ -333,9 +335,9 @@ export const MapsList = (props: MapsListProps) => {
|
|||||||
<FormattedMessage id="action.delete" defaultMessage="Delete" />
|
<FormattedMessage id="action.delete" defaultMessage="Delete" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
}
|
||||||
|
|
||||||
{selected.length > 0 ? (
|
{selected.length > 0 &&
|
||||||
<Tooltip title="Add label to selected">
|
<Tooltip title="Add label to selected">
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
@ -348,7 +350,7 @@ export const MapsList = (props: MapsListProps) => {
|
|||||||
<FormattedMessage id="action.label" defaultMessage="Add Label" />
|
<FormattedMessage id="action.label" defaultMessage="Add Label" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : null}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={classes.toolbarListActions}>
|
<div className={classes.toolbarListActions}>
|
||||||
@ -465,7 +467,7 @@ export const MapsList = (props: MapsListProps) => {
|
|||||||
<MoreHorizIcon color="action" />
|
<MoreHorizIcon color="action" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<ActionChooser anchor={activeRowAction?.el} onClose={handleActionMenuClose} />
|
<ActionChooser anchor={activeRowAction?.el} onClose={handleActionMenuClose} role={row.role} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user