mirror of
https://bitbucket.org/wisemapping/wisemapping-frontend.git
synced 2024-11-22 14:47:56 +01:00
Add create dialog
This commit is contained in:
parent
67fec75d91
commit
481c1fe619
@ -56,6 +56,15 @@
|
|||||||
"common.wait": {
|
"common.wait": {
|
||||||
"defaultMessage": "Please wait ..."
|
"defaultMessage": "Please wait ..."
|
||||||
},
|
},
|
||||||
|
"create.button": {
|
||||||
|
"defaultMessage": "Create"
|
||||||
|
},
|
||||||
|
"create.description": {
|
||||||
|
"defaultMessage": "Please, fill the new map name and description."
|
||||||
|
},
|
||||||
|
"create.title": {
|
||||||
|
"defaultMessage": "Create a new mindmap"
|
||||||
|
},
|
||||||
"duplicate.title": {
|
"duplicate.title": {
|
||||||
"defaultMessage": "Duplicate"
|
"defaultMessage": "Duplicate"
|
||||||
},
|
},
|
||||||
|
@ -33,6 +33,7 @@ export type ErrorInfo = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Client {
|
interface Client {
|
||||||
|
createMap(rest: { name: string; description?: string | undefined })
|
||||||
deleteLabel(label: string): Promise<unknown>;
|
deleteLabel(label: string): Promise<unknown>;
|
||||||
registerNewUser(user: NewUser): Promise<void>;
|
registerNewUser(user: NewUser): Promise<void>;
|
||||||
resetPassword(email: string): Promise<void>;
|
resetPassword(email: string): Promise<void>;
|
||||||
|
@ -43,7 +43,10 @@ class MockClient implements Client {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createMap(rest: { name: string; description?: string | undefined; }) {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
s
|
||||||
fetchLabels(): Promise<string[]> {
|
fetchLabels(): Promise<string[]> {
|
||||||
console.log("Fetching labels from server")
|
console.log("Fetching labels from server")
|
||||||
return Promise.resolve(this.labels);
|
return Promise.resolve(this.labels);
|
||||||
|
@ -113,6 +113,24 @@
|
|||||||
"value": "Please wait ..."
|
"value": "Please wait ..."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"create.button": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Create"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"create.description": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Please, fill the new map name and description."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"create.title": [
|
||||||
|
{
|
||||||
|
"type": 0,
|
||||||
|
"value": "Create a new mindmap"
|
||||||
|
}
|
||||||
|
],
|
||||||
"duplicate.title": [
|
"duplicate.title": [
|
||||||
{
|
{
|
||||||
"type": 0,
|
"type": 0,
|
||||||
|
@ -12,7 +12,7 @@ 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' | 'duplicate' | 'export' | 'label' | 'rename' | 'print' | 'info' | 'publish' | 'history' | undefined;
|
export type ActionType = 'open' | 'share' | 'delete' | 'info' | 'create'| 'duplicate' | 'export' | 'label' | 'rename' | 'print' | 'info' | 'publish' | 'history' | undefined;
|
||||||
|
|
||||||
interface ActionProps {
|
interface ActionProps {
|
||||||
onClose: (action: ActionType) => void;
|
onClose: (action: ActionType) => void;
|
||||||
|
@ -68,7 +68,7 @@ const BaseDialog = (props: DialogProps) => {
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
type="submit"
|
type="submit"
|
||||||
disableElevation={true}>
|
disableElevation={true}>
|
||||||
{props.title}
|
{props.submitButton}
|
||||||
</Button>) : null
|
</Button>) : null
|
||||||
}
|
}
|
||||||
</StyledDialogActions>
|
</StyledDialogActions>
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
import { useMutation, useQueryClient } from "react-query";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { FormControl } from "@material-ui/core";
|
||||||
|
|
||||||
|
import Client, { BasicMapInfo, ErrorInfo } from "../../../../client";
|
||||||
|
import { activeInstance } from '../../../../reducers/serviceSlice';
|
||||||
|
import Input from "../../../form/input";
|
||||||
|
import { DialogProps, fetchMapById, handleOnMutationSuccess } from "..";
|
||||||
|
import BaseDialog from "../action-dialog";
|
||||||
|
|
||||||
|
export type CreateModel = {
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CreateProps = {
|
||||||
|
open: boolean,
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultModel: CreateModel = { name: '', description: ''};
|
||||||
|
const CreateDialog = (props: CreateProps) => {
|
||||||
|
const client: Client = useSelector(activeInstance);
|
||||||
|
const [model, setModel] = React.useState<CreateModel>(defaultModel);
|
||||||
|
const [error, setError] = React.useState<ErrorInfo>();
|
||||||
|
const { open } = props;
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const mutation = useMutation<CreateModel, ErrorInfo, CreateModel>((model: CreateModel) => {
|
||||||
|
const { ...rest } = model;
|
||||||
|
return client.createMap(rest).then(() => model);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
handleOnMutationSuccess(props.onClose, queryClient);
|
||||||
|
},
|
||||||
|
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 open={open} onClose={handleOnClose} onSubmit={handleOnSubmit} error={error}
|
||||||
|
title={intl.formatMessage({ id: 'create.title', defaultMessage: 'Create a new mindmap' })}
|
||||||
|
description={intl.formatMessage({ id: 'create.description', defaultMessage: 'Please, fill the new map name and description.' })}
|
||||||
|
submitButton={intl.formatMessage({ id: 'create.button', defaultMessage: 'Create' })}>
|
||||||
|
|
||||||
|
<FormControl fullWidth={true}>
|
||||||
|
<Input name="name" type="text" label={{ id: "action.rename-name-placeholder", defaultMessage: "Name" }}
|
||||||
|
value={model.name} onChange={handleOnChange} error={error} fullWidth={true} />
|
||||||
|
|
||||||
|
<Input name="description" type="text" label={{ id: "action.rename-description-placeholder", defaultMessage: "Description" }}
|
||||||
|
value={model.description} onChange={handleOnChange} required={false} fullWidth={true} />
|
||||||
|
</FormControl>
|
||||||
|
</BaseDialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CreateDialog;
|
@ -10,6 +10,7 @@ import { activeInstance } from '../../../reducers/serviceSlice';
|
|||||||
import DuplicateDialog from './duplicate';
|
import DuplicateDialog from './duplicate';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import InfoDialog from './info';
|
import InfoDialog from './info';
|
||||||
|
import CreateDialog from './create';
|
||||||
|
|
||||||
|
|
||||||
export type BasicMapInfo = {
|
export type BasicMapInfo = {
|
||||||
@ -43,6 +44,7 @@ const ActionDispatcher = (props: ActionDialogProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
|
<CreateDialog open={action === 'create'} onClose={handleOnClose}/>
|
||||||
<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} />
|
||||||
|
@ -16,11 +16,12 @@ import { useQuery, useMutation, useQueryClient } from 'react-query';
|
|||||||
import { activeInstance } from '../../reducers/serviceSlice';
|
import { activeInstance } from '../../reducers/serviceSlice';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import Client from '../../client';
|
import Client from '../../client';
|
||||||
|
import ActionDispatcher from './action-dispatcher';
|
||||||
|
import { ActionType } from './action-chooser';
|
||||||
|
|
||||||
const logoIcon = require('../../images/logo-small.svg');
|
const logoIcon = require('../../images/logo-small.svg');
|
||||||
const poweredByIcon = require('../../images/pwrdby-white.svg');
|
const poweredByIcon = require('../../images/pwrdby-white.svg');
|
||||||
|
|
||||||
|
|
||||||
export type Filter = GenericFilter | LabelFilter;
|
export type Filter = GenericFilter | LabelFilter;
|
||||||
|
|
||||||
export interface GenericFilter {
|
export interface GenericFilter {
|
||||||
@ -42,6 +43,7 @@ const MapsPage = () => {
|
|||||||
const [filter, setFilter] = React.useState<Filter>({ type: 'all' });
|
const [filter, setFilter] = React.useState<Filter>({ type: 'all' });
|
||||||
const client: Client = useSelector(activeInstance);
|
const client: Client = useSelector(activeInstance);
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const [activeDialog, setActiveDialog] = React.useState<ActionType | undefined>(undefined);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -103,8 +105,14 @@ const MapsPage = () => {
|
|||||||
|
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Tooltip title="Create a New Map">
|
<Tooltip title="Create a New Map">
|
||||||
<Button color="primary" size="medium" variant="contained" type="button"
|
<Button color="primary"
|
||||||
disableElevation={true} startIcon={<AddCircleTwoTone />} className={classes.newMapButton}>
|
size="medium"
|
||||||
|
variant="contained"
|
||||||
|
type="button"
|
||||||
|
disableElevation={true}
|
||||||
|
startIcon={<AddCircleTwoTone />}
|
||||||
|
className={classes.newMapButton}
|
||||||
|
onClick={e => setActiveDialog('create')}>
|
||||||
<FormattedMessage id="action.new" defaultMessage="New Map" />
|
<FormattedMessage id="action.new" defaultMessage="New Map" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -115,6 +123,7 @@ const MapsPage = () => {
|
|||||||
<FormattedMessage id="action.import" defaultMessage="Import" />
|
<FormattedMessage id="action.import" defaultMessage="Import" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
<ActionDispatcher action={activeDialog} onClose={() => setActiveDialog(undefined)} mapId={-1} />
|
||||||
|
|
||||||
<div className={classes.rightButtonGroup}>
|
<div className={classes.rightButtonGroup}>
|
||||||
<HelpToobarButton />
|
<HelpToobarButton />
|
||||||
|
@ -392,75 +392,79 @@ export const MapsList = (props: MapsListProps) => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{isLoading ? (<TableRow></TableRow>) : stableSort(mapsInfo, getComparator(order, orderBy))
|
{isLoading ? (
|
||||||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
<TableRow><TableCell rowSpan={6}>Loading ...</TableCell></TableRow>) :
|
||||||
.map((row: MapInfo) => {
|
(mapsInfo.length == 0 ?
|
||||||
const isItemSelected = isSelected(row.id);
|
(<TableRow><TableCell rowSpan={6}>No matching records found</TableCell></TableRow>) :
|
||||||
const labelId = row.id;
|
stableSort(mapsInfo, getComparator(order, orderBy))
|
||||||
|
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||||
|
.map((row: MapInfo) => {
|
||||||
|
const isItemSelected = isSelected(row.id);
|
||||||
|
const labelId = row.id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
hover
|
hover
|
||||||
onClick={(event: any) => handleRowClick(event, row.id)}
|
onClick={(event: any) => handleRowClick(event, row.id)}
|
||||||
role="checkbox"
|
role="checkbox"
|
||||||
aria-checked={isItemSelected}
|
aria-checked={isItemSelected}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
key={row.id}
|
key={row.id}
|
||||||
selected={isItemSelected}
|
selected={isItemSelected}
|
||||||
style={{ border: "0" }}
|
style={{ border: "0" }}
|
||||||
>
|
>
|
||||||
<TableCell
|
<TableCell
|
||||||
padding="checkbox"
|
padding="checkbox"
|
||||||
className={classes.bodyCell}>
|
className={classes.bodyCell}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={isItemSelected}
|
checked={isItemSelected}
|
||||||
inputProps={{ 'aria-labelledby': String(labelId) }}
|
inputProps={{ 'aria-labelledby': String(labelId) }}
|
||||||
size="small" />
|
size="small" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell
|
<TableCell
|
||||||
padding="checkbox"
|
padding="checkbox"
|
||||||
className={classes.bodyCell}>
|
className={classes.bodyCell}>
|
||||||
<Tooltip title="Starred">
|
<Tooltip title="Starred">
|
||||||
<IconButton aria-label="Starred" size="small" onClick={(e) => handleStarred(e, row.id)}>
|
<IconButton aria-label="Starred" size="small" onClick={(e) => handleStarred(e, row.id)}>
|
||||||
<StarRateRoundedIcon color="action" style={{ color: row.starred ? 'yellow' : 'gray' }} />
|
<StarRateRoundedIcon color="action" style={{ color: row.starred ? 'yellow' : 'gray' }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell className={classes.bodyCell}>
|
||||||
<Tooltip title="Open for edition" placement="bottom-start">
|
<Tooltip title="Open for edition" placement="bottom-start">
|
||||||
<Link href={`c/maps/${row.id}/edit`} color="textPrimary" underline="always">
|
<Link href={`c/maps/${row.id}/edit`} color="textPrimary" underline="always">
|
||||||
{row.name}
|
{row.name}
|
||||||
</Link>
|
</Link>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell className={classes.bodyCell}>
|
||||||
{row.labels}
|
{row.labels}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell className={classes.bodyCell}>
|
||||||
{row.creator}
|
{row.creator}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell className={classes.bodyCell}>
|
||||||
<Tooltip title={moment(row.modified).format("lll")} placement="bottom-start">
|
<Tooltip title={moment(row.modified).format("lll")} placement="bottom-start">
|
||||||
<span>{moment(row.modified).fromNow()}</span>
|
<span>{moment(row.modified).fromNow()}</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className={classes.bodyCell}>
|
<TableCell className={classes.bodyCell}>
|
||||||
<Tooltip title="Others">
|
<Tooltip title="Others">
|
||||||
<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>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<ActionChooser anchor={activeRowAction?.el} onClose={handleActionMenuClose} />
|
<ActionChooser anchor={activeRowAction?.el} onClose={handleActionMenuClose} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
})}
|
}))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
|
Loading…
Reference in New Issue
Block a user