Create tasks route.
parent
32426b2460
commit
b39f100bdb
@ -1,413 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: © 2017 EteSync Authors
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
import * as React from "react";
|
|
||||||
import { Route, Switch } from "react-router";
|
|
||||||
import Button from "@material-ui/core/Button";
|
|
||||||
import IconEdit from "@material-ui/icons/Edit";
|
|
||||||
import IconDuplicate from "@material-ui/icons/FileCopy";
|
|
||||||
import IconChangeHistory from "@material-ui/icons/ChangeHistory";
|
|
||||||
import { withStyles } from "@material-ui/core/styles";
|
|
||||||
|
|
||||||
import { RouteComponentProps, withRouter } from "react-router";
|
|
||||||
|
|
||||||
import { Action } from "redux-actions";
|
|
||||||
|
|
||||||
import * as EteSync from "etesync";
|
|
||||||
|
|
||||||
import { createSelector } from "reselect";
|
|
||||||
|
|
||||||
import { History } from "history";
|
|
||||||
|
|
||||||
import { PimType, ContactType, EventType, TaskType } from "../pim-types";
|
|
||||||
|
|
||||||
import Container from "../widgets/Container";
|
|
||||||
|
|
||||||
import JournalEntries from "../components/JournalEntries";
|
|
||||||
import TaskEdit from "../components/Tasks/TaskEdit";
|
|
||||||
import Task from "../components/Tasks/Task";
|
|
||||||
|
|
||||||
import { routeResolver } from "../App";
|
|
||||||
|
|
||||||
import { store, CredentialsData, UserInfoData } from "../store";
|
|
||||||
import { fetchEntries } from "../store/actions";
|
|
||||||
|
|
||||||
import { SyncInfo } from "../SyncGate";
|
|
||||||
|
|
||||||
import { addJournalEntry } from "../etesync-helpers";
|
|
||||||
|
|
||||||
import { syncEntriesToItemMap, syncEntriesToEventItemMap, syncEntriesToTaskItemMap } from "../journal-processors";
|
|
||||||
|
|
||||||
const itemsSelector = createSelector(
|
|
||||||
(props: {syncInfo: SyncInfo}) => props.syncInfo,
|
|
||||||
(syncInfo) => {
|
|
||||||
const collectionsAddressBook: EteSync.CollectionInfo[] = [];
|
|
||||||
const collectionsCalendar: EteSync.CollectionInfo[] = [];
|
|
||||||
const collectionsTaskList: EteSync.CollectionInfo[] = [];
|
|
||||||
let addressBookItems: {[key: string]: ContactType} = {};
|
|
||||||
let calendarItems: {[key: string]: EventType} = {};
|
|
||||||
let taskListItems: {[key: string]: TaskType} = {};
|
|
||||||
syncInfo.forEach(
|
|
||||||
(syncJournal) => {
|
|
||||||
const syncEntries = syncJournal.entries;
|
|
||||||
|
|
||||||
const collectionInfo = syncJournal.collection;
|
|
||||||
|
|
||||||
if (collectionInfo.type === "ADDRESS_BOOK") {
|
|
||||||
addressBookItems = syncEntriesToItemMap(collectionInfo, syncEntries, addressBookItems);
|
|
||||||
collectionsAddressBook.push(collectionInfo);
|
|
||||||
} else if (collectionInfo.type === "CALENDAR") {
|
|
||||||
calendarItems = syncEntriesToEventItemMap(collectionInfo, syncEntries, calendarItems);
|
|
||||||
collectionsCalendar.push(collectionInfo);
|
|
||||||
} else if (collectionInfo.type === "TASKS") {
|
|
||||||
taskListItems = syncEntriesToTaskItemMap(collectionInfo, syncEntries, taskListItems);
|
|
||||||
collectionsTaskList.push(collectionInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
collectionsAddressBook, collectionsCalendar, collectionsTaskList, addressBookItems, calendarItems, taskListItems,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const ItemChangeLog = React.memo((props: any) => {
|
|
||||||
const {
|
|
||||||
syncInfo,
|
|
||||||
paramItemUid,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const tmp = paramItemUid.split("|");
|
|
||||||
const journalUid = tmp.shift();
|
|
||||||
const uid = tmp.join("|");
|
|
||||||
const journalItem = syncInfo.get(journalUid);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<h2>Item Change History</h2>
|
|
||||||
<JournalEntries
|
|
||||||
journal={journalItem.journal}
|
|
||||||
entries={journalItem.entries}
|
|
||||||
uid={uid}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type CollectionRoutesPropsType = RouteComponentProps<{}> & {
|
|
||||||
syncInfo: SyncInfo;
|
|
||||||
routePrefix: string;
|
|
||||||
collections: EteSync.CollectionInfo[];
|
|
||||||
componentEdit: any;
|
|
||||||
componentView: any;
|
|
||||||
items: {[key: string]: PimType};
|
|
||||||
onItemSave: (item: PimType, journalUid: string, originalItem?: PimType) => Promise<void>;
|
|
||||||
onItemDelete: (item: PimType, journalUid: string) => void;
|
|
||||||
onItemCancel: () => void;
|
|
||||||
classes: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
const styles = (theme: any) => ({
|
|
||||||
button: {
|
|
||||||
marginLeft: theme.spacing(1),
|
|
||||||
},
|
|
||||||
leftIcon: {
|
|
||||||
marginRight: theme.spacing(1),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function PageNotFound() {
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<h1>404 Page Not Found</h1>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const CollectionRoutes = withStyles(styles)(withRouter(
|
|
||||||
class CollectionRoutesInner extends React.PureComponent<CollectionRoutesPropsType> {
|
|
||||||
|
|
||||||
private itemUndefined(itemUid: string) {
|
|
||||||
return this.props.items[itemUid] === undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
const props = this.props;
|
|
||||||
const { classes } = this.props;
|
|
||||||
const ComponentEdit = props.componentEdit;
|
|
||||||
const ComponentView = props.componentView;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Switch>
|
|
||||||
<Route
|
|
||||||
path={routeResolver.getRoute(props.routePrefix + ".new")}
|
|
||||||
exact
|
|
||||||
render={() => (
|
|
||||||
<Container style={{ maxWidth: "30rem" }}>
|
|
||||||
<ComponentEdit
|
|
||||||
key={props.routePrefix}
|
|
||||||
collections={props.collections}
|
|
||||||
onSave={props.onItemSave}
|
|
||||||
onCancel={props.onItemCancel}
|
|
||||||
history={props.history}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path={routeResolver.getRoute(props.routePrefix + "._id.edit")}
|
|
||||||
exact
|
|
||||||
render={({ match }) => {
|
|
||||||
const itemUid = decodeURIComponent(match.params.itemUid);
|
|
||||||
if (this.itemUndefined(itemUid)) {
|
|
||||||
return PageNotFound();
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Container style={{ maxWidth: "30rem" }}>
|
|
||||||
{(itemUid in props.items) &&
|
|
||||||
<ComponentEdit
|
|
||||||
key={(props.items[itemUid] as any).journalUid}
|
|
||||||
initialCollection={(props.items[itemUid] as any).journalUid}
|
|
||||||
item={props.items[itemUid]}
|
|
||||||
collections={props.collections}
|
|
||||||
onSave={props.onItemSave}
|
|
||||||
onDelete={props.onItemDelete}
|
|
||||||
onCancel={props.onItemCancel}
|
|
||||||
history={props.history}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{props.routePrefix === "pim.events" &&
|
|
||||||
<Route
|
|
||||||
path={routeResolver.getRoute(props.routePrefix + "._id.duplicate")}
|
|
||||||
exact
|
|
||||||
render={({ match }) => {
|
|
||||||
const itemUid = decodeURIComponent(match.params.itemUid);
|
|
||||||
if (this.itemUndefined(itemUid)) {
|
|
||||||
return PageNotFound();
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Container style={{ maxWidth: "30rem" }}>
|
|
||||||
{(itemUid in props.items) &&
|
|
||||||
<ComponentEdit
|
|
||||||
key={(props.items[itemUid] as any).journalUid}
|
|
||||||
initialCollection={(props.items[itemUid] as any).journalUid}
|
|
||||||
item={props.items[itemUid]}
|
|
||||||
collections={props.collections}
|
|
||||||
onSave={props.onItemSave}
|
|
||||||
onDelete={props.onItemDelete}
|
|
||||||
onCancel={props.onItemCancel}
|
|
||||||
history={props.history}
|
|
||||||
duplicate
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
<Route
|
|
||||||
path={routeResolver.getRoute(props.routePrefix + "._id.log")}
|
|
||||||
exact
|
|
||||||
render={({ match }) => {
|
|
||||||
const paramItemUid = decodeURIComponent(match.params.itemUid);
|
|
||||||
if (this.itemUndefined(paramItemUid)) {
|
|
||||||
return PageNotFound();
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<ItemChangeLog
|
|
||||||
syncInfo={props.syncInfo}
|
|
||||||
paramItemUid={paramItemUid}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path={routeResolver.getRoute(props.routePrefix + "._id")}
|
|
||||||
exact
|
|
||||||
render={({ match, history }) => {
|
|
||||||
const itemUid = decodeURIComponent(match.params.itemUid);
|
|
||||||
if (this.itemUndefined(itemUid)) {
|
|
||||||
return PageNotFound();
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<div style={{ textAlign: "right", marginBottom: 15 }}>
|
|
||||||
<Button
|
|
||||||
variant="contained"
|
|
||||||
className={classes.button}
|
|
||||||
onClick={() =>
|
|
||||||
history.push(routeResolver.getRoute(
|
|
||||||
props.routePrefix + "._id.log",
|
|
||||||
{ itemUid: match.params.itemUid }))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<IconChangeHistory className={classes.leftIcon} />
|
|
||||||
Change History
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
color="secondary"
|
|
||||||
variant="contained"
|
|
||||||
disabled={!props.componentEdit}
|
|
||||||
className={classes.button}
|
|
||||||
style={{ marginLeft: 15 }}
|
|
||||||
onClick={() =>
|
|
||||||
history.push(routeResolver.getRoute(
|
|
||||||
props.routePrefix + "._id.edit",
|
|
||||||
{ itemUid: match.params.itemUid }))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<IconEdit className={classes.leftIcon} />
|
|
||||||
Edit
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{props.routePrefix === "pim.events" &&
|
|
||||||
<Button
|
|
||||||
color="secondary"
|
|
||||||
variant="contained"
|
|
||||||
disabled={!props.componentEdit}
|
|
||||||
className={classes.button}
|
|
||||||
style={{ marginLeft: 15 }}
|
|
||||||
onClick={() =>
|
|
||||||
history.push(routeResolver.getRoute(
|
|
||||||
props.routePrefix + "._id.duplicate",
|
|
||||||
{ itemUid: match.params.itemUid }))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<IconDuplicate className={classes.leftIcon} />
|
|
||||||
Duplicate
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<ComponentView item={props.items[decodeURIComponent(match.params.itemUid)]} />
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
class Pim extends React.PureComponent {
|
|
||||||
public props: {
|
|
||||||
etesync: CredentialsData;
|
|
||||||
userInfo: UserInfoData;
|
|
||||||
syncInfo: SyncInfo;
|
|
||||||
history: History;
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
this.onCancel = this.onCancel.bind(this);
|
|
||||||
this.onItemDelete = this.onItemDelete.bind(this);
|
|
||||||
this.onItemSave = this.onItemSave.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public onItemSave(item: PimType, journalUid: string, originalEvent?: PimType): Promise<void> {
|
|
||||||
const syncJournal = this.props.syncInfo.get(journalUid);
|
|
||||||
|
|
||||||
if (syncJournal === undefined) {
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
const journal = syncJournal.journal;
|
|
||||||
|
|
||||||
const action = (originalEvent === undefined) ? EteSync.SyncEntryAction.Add : EteSync.SyncEntryAction.Change;
|
|
||||||
|
|
||||||
let prevUid: string | null = null;
|
|
||||||
let last = syncJournal.journalEntries.last() as EteSync.Entry;
|
|
||||||
if (last) {
|
|
||||||
prevUid = last.uid;
|
|
||||||
}
|
|
||||||
return store.dispatch<any>(fetchEntries(this.props.etesync, journal.uid, prevUid))
|
|
||||||
.then((entriesAction: Action<EteSync.Entry[]>) => {
|
|
||||||
|
|
||||||
last = entriesAction.payload!.slice(-1).pop() as EteSync.Entry;
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
prevUid = last.uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
return store.dispatch(
|
|
||||||
addJournalEntry(
|
|
||||||
this.props.etesync, this.props.userInfo, journal,
|
|
||||||
prevUid, action, item.toIcal()));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public onItemDelete(item: PimType, journalUid: string) {
|
|
||||||
const syncJournal = this.props.syncInfo.get(journalUid);
|
|
||||||
|
|
||||||
if (syncJournal === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const journal = syncJournal.journal;
|
|
||||||
|
|
||||||
const action = EteSync.SyncEntryAction.Delete;
|
|
||||||
|
|
||||||
let prevUid: string | null = null;
|
|
||||||
let last = syncJournal.journalEntries.last() as EteSync.Entry;
|
|
||||||
if (last) {
|
|
||||||
prevUid = last.uid;
|
|
||||||
}
|
|
||||||
store.dispatch<any>(fetchEntries(this.props.etesync, journal.uid, prevUid))
|
|
||||||
.then((entriesAction: Action<EteSync.Entry[]>) => {
|
|
||||||
|
|
||||||
last = entriesAction.payload!.slice(-1).pop() as EteSync.Entry;
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
prevUid = last.uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteItem = store.dispatch(
|
|
||||||
addJournalEntry(
|
|
||||||
this.props.etesync, this.props.userInfo, journal,
|
|
||||||
prevUid, action, item.toIcal()));
|
|
||||||
(deleteItem as any).then(() => {
|
|
||||||
this.props.history.push(routeResolver.getRoute("pim"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public onCancel() {
|
|
||||||
this.props.history.goBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
const { collectionsTaskList, taskListItems } = itemsSelector(this.props);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Switch>
|
|
||||||
<Route
|
|
||||||
path={routeResolver.getRoute("pim.tasks")}
|
|
||||||
render={() => (
|
|
||||||
<CollectionRoutes
|
|
||||||
syncInfo={this.props.syncInfo}
|
|
||||||
routePrefix="pim.tasks"
|
|
||||||
collections={collectionsTaskList}
|
|
||||||
items={taskListItems}
|
|
||||||
componentEdit={TaskEdit}
|
|
||||||
componentView={Task}
|
|
||||||
onItemSave={this.onItemSave}
|
|
||||||
onItemDelete={this.onItemDelete}
|
|
||||||
onItemCancel={this.onCancel}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Pim;
|
|
@ -0,0 +1,232 @@
|
|||||||
|
// SPDX-FileCopyrightText: © 2020 EteSync Authors
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import { Switch, Route, useHistory } from "react-router";
|
||||||
|
|
||||||
|
import * as Etebase from "etebase";
|
||||||
|
|
||||||
|
import { Button, useTheme } from "@material-ui/core";
|
||||||
|
import IconEdit from "@material-ui/icons/Edit";
|
||||||
|
import IconChangeHistory from "@material-ui/icons/ChangeHistory";
|
||||||
|
|
||||||
|
import { TaskType, PimType } from "../pim-types";
|
||||||
|
import { useCredentials } from "../credentials";
|
||||||
|
import { useItems, useCollections, getCollectionManager } from "../etebase-helpers";
|
||||||
|
import { routeResolver } from "../App";
|
||||||
|
import TaskList from "./TaskList";
|
||||||
|
import Task from "./Task";
|
||||||
|
import LoadingIndicator from "../widgets/LoadingIndicator";
|
||||||
|
import TaskEdit from "./TaskEdit";
|
||||||
|
import PageNotFound from "../PageNotFound";
|
||||||
|
|
||||||
|
import { CachedCollection, getItemNavigationUid, getDecryptCollectionsFunction, getDecryptItemsFunction, PimFab } from "../Pim/helpers";
|
||||||
|
|
||||||
|
const colType = "etebase.vtodo";
|
||||||
|
|
||||||
|
const decryptCollections = getDecryptCollectionsFunction(colType);
|
||||||
|
const decryptItems = getDecryptItemsFunction(colType, TaskType.parse);
|
||||||
|
|
||||||
|
export default function TasksMain() {
|
||||||
|
const [entries, setEntries] = React.useState<Map<string, Map<string, TaskType>>>();
|
||||||
|
const [cachedCollections, setCachedCollections] = React.useState<CachedCollection[]>();
|
||||||
|
const theme = useTheme();
|
||||||
|
const history = useHistory();
|
||||||
|
const etebase = useCredentials()!;
|
||||||
|
const collections = useCollections(etebase, colType);
|
||||||
|
const items = useItems(etebase, colType);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (items) {
|
||||||
|
decryptItems(items)
|
||||||
|
.then((entries) => setEntries(entries));
|
||||||
|
// FIXME: handle failure to decrypt items
|
||||||
|
}
|
||||||
|
if (collections) {
|
||||||
|
decryptCollections(collections)
|
||||||
|
.then((entries) => setCachedCollections(entries));
|
||||||
|
// FIXME: handle failure to decrypt collections
|
||||||
|
}
|
||||||
|
}, [items, collections]);
|
||||||
|
|
||||||
|
if (!entries || !cachedCollections) {
|
||||||
|
return (
|
||||||
|
<LoadingIndicator />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onItemSave(item: PimType, collectionUid: string, originalItem?: PimType): Promise<void> {
|
||||||
|
const itemUid = originalItem?.itemUid;
|
||||||
|
const colMgr = getCollectionManager(etebase);
|
||||||
|
const collection = collections!.find((x) => x.uid === collectionUid)!;
|
||||||
|
const itemMgr = colMgr.getItemManager(collection);
|
||||||
|
|
||||||
|
const mtime = (new Date()).getUTCMilliseconds();
|
||||||
|
const content = item.toIcal();
|
||||||
|
|
||||||
|
let eteItem;
|
||||||
|
if (itemUid) {
|
||||||
|
// Existing item
|
||||||
|
eteItem = items!.get(collectionUid)?.get(itemUid)!;
|
||||||
|
await eteItem.setContent(content);
|
||||||
|
const meta = await eteItem.getMeta();
|
||||||
|
meta.mtime = mtime;
|
||||||
|
await eteItem.setMeta(meta);
|
||||||
|
} else {
|
||||||
|
// New
|
||||||
|
const meta: Etebase.CollectionItemMetadata = {
|
||||||
|
mtime,
|
||||||
|
name: item.uid,
|
||||||
|
};
|
||||||
|
eteItem = await itemMgr.create(meta, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
await itemMgr.batch([eteItem]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onItemDelete(item: PimType, collectionUid: string) {
|
||||||
|
const itemUid = item.itemUid!;
|
||||||
|
const colMgr = getCollectionManager(etebase);
|
||||||
|
const collection = collections!.find((x) => x.uid === collectionUid)!;
|
||||||
|
const itemMgr = colMgr.getItemManager(collection);
|
||||||
|
|
||||||
|
const eteItem = items!.get(collectionUid)?.get(itemUid)!;
|
||||||
|
const mtime = (new Date()).getUTCMilliseconds();
|
||||||
|
const meta = await eteItem.getMeta();
|
||||||
|
meta.mtime = mtime;
|
||||||
|
await eteItem.setMeta(meta);
|
||||||
|
await eteItem.delete();
|
||||||
|
await itemMgr.batch([eteItem]);
|
||||||
|
|
||||||
|
history.push(routeResolver.getRoute("pim.tasks"));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCancel() {
|
||||||
|
history.goBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
const flatEntries = [];
|
||||||
|
for (const col of entries.values()) {
|
||||||
|
for (const item of col.values()) {
|
||||||
|
flatEntries.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
button: {
|
||||||
|
marginLeft: theme.spacing(1),
|
||||||
|
},
|
||||||
|
leftIcon: {
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Switch>
|
||||||
|
<Route
|
||||||
|
path={routeResolver.getRoute("pim.tasks")}
|
||||||
|
exact
|
||||||
|
>
|
||||||
|
<TaskList
|
||||||
|
entries={flatEntries}
|
||||||
|
collections={cachedCollections}
|
||||||
|
onItemClick={(item: TaskType) => history.push(
|
||||||
|
routeResolver.getRoute("pim.tasks._id", { itemUid: getItemNavigationUid(item) })
|
||||||
|
)}
|
||||||
|
onItemSave={onItemSave}
|
||||||
|
/>
|
||||||
|
<PimFab
|
||||||
|
onClick={() => history.push(
|
||||||
|
routeResolver.getRoute("pim.tasks.new")
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
<Route
|
||||||
|
path={routeResolver.getRoute("pim.tasks.new")}
|
||||||
|
exact
|
||||||
|
>
|
||||||
|
<TaskEdit
|
||||||
|
collections={cachedCollections}
|
||||||
|
onSave={onItemSave}
|
||||||
|
onDelete={onItemDelete}
|
||||||
|
onCancel={onCancel}
|
||||||
|
history={history}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
<Route
|
||||||
|
path={routeResolver.getRoute("pim.tasks._id")}
|
||||||
|
render={({ match }) => {
|
||||||
|
const [colUid, itemUid] = match.params.itemUid.split("|");
|
||||||
|
const item = entries.get(colUid)?.get(itemUid);
|
||||||
|
if (!item) {
|
||||||
|
return (<PageNotFound />);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME:
|
||||||
|
const collection = collections!.find((x) => x.uid === colUid)!;
|
||||||
|
const readOnly = collection.accessLevel;
|
||||||
|
*/
|
||||||
|
const readOnly = false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Switch>
|
||||||
|
<Route
|
||||||
|
path={routeResolver.getRoute("pim.tasks._id.edit")}
|
||||||
|
exact
|
||||||
|
>
|
||||||
|
<TaskEdit
|
||||||
|
key={itemUid}
|
||||||
|
initialCollection={item.collectionUid}
|
||||||
|
item={item}
|
||||||
|
collections={cachedCollections}
|
||||||
|
onSave={onItemSave}
|
||||||
|
onDelete={onItemDelete}
|
||||||
|
onCancel={onCancel}
|
||||||
|
history={history}
|
||||||
|
/>
|
||||||
|
</Route>
|
||||||
|
<Route
|
||||||
|
path={routeResolver.getRoute("pim.tasks._id.log")}
|
||||||
|
>
|
||||||
|
<h1>Not currently implemented.</h1>
|
||||||
|
</Route>
|
||||||
|
<Route
|
||||||
|
path={routeResolver.getRoute("pim.tasks._id")}
|
||||||
|
exact
|
||||||
|
>
|
||||||
|
<div style={{ textAlign: "right", marginBottom: 15 }}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
style={styles.button}
|
||||||
|
onClick={() =>
|
||||||
|
history.push(routeResolver.getRoute("pim.tasks._id.log", { itemUid: getItemNavigationUid(item) }))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<IconChangeHistory style={styles.leftIcon} />
|
||||||
|
Change History
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color="secondary"
|
||||||
|
variant="contained"
|
||||||
|
disabled={readOnly}
|
||||||
|
style={{ ...styles.button, marginLeft: 15 }}
|
||||||
|
onClick={() =>
|
||||||
|
history.push(routeResolver.getRoute("pim.tasks._id.edit", { itemUid: getItemNavigationUid(item) }))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<IconEdit style={styles.leftIcon} />
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<Task item={item} />
|
||||||
|
</Route>
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue