diff --git a/src/Pim/index.tsx b/src/Pim/index.tsx deleted file mode 100644 index d62eddc..0000000 --- a/src/Pim/index.tsx +++ /dev/null @@ -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 ( - -

Item Change History

- -
- ); -}); - -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; - 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 ( - -

404 Page Not Found

-
- ); -} - - -const CollectionRoutes = withStyles(styles)(withRouter( - class CollectionRoutesInner extends React.PureComponent { - - 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 ( - - ( - - - - )} - /> - { - const itemUid = decodeURIComponent(match.params.itemUid); - if (this.itemUndefined(itemUid)) { - return PageNotFound(); - } - return ( - - {(itemUid in props.items) && - - } - - ); - }} - /> - {props.routePrefix === "pim.events" && - { - const itemUid = decodeURIComponent(match.params.itemUid); - if (this.itemUndefined(itemUid)) { - return PageNotFound(); - } - return ( - - {(itemUid in props.items) && - - } - - ); - }} - /> - } - { - const paramItemUid = decodeURIComponent(match.params.itemUid); - if (this.itemUndefined(paramItemUid)) { - return PageNotFound(); - } - return ( - - - - ); - }} - /> - { - const itemUid = decodeURIComponent(match.params.itemUid); - if (this.itemUndefined(itemUid)) { - return PageNotFound(); - } - return ( - -
- - - - - {props.routePrefix === "pim.events" && - - } -
- -
- ); - }} - /> -
- ); - } - } -)); - -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 { - 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(fetchEntries(this.props.etesync, journal.uid, prevUid)) - .then((entriesAction: Action) => { - - 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(fetchEntries(this.props.etesync, journal.uid, prevUid)) - .then((entriesAction: Action) => { - - 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 ( - - ( - - )} - /> - - ); - } -} - -export default Pim; diff --git a/src/SyncGate.tsx b/src/SyncGate.tsx index 64b8b72..0e8b673 100644 --- a/src/SyncGate.tsx +++ b/src/SyncGate.tsx @@ -16,6 +16,7 @@ import AppBarOverride from "./widgets/AppBarOverride"; import LoadingIndicator from "./widgets/LoadingIndicator"; import ContactsMain from "./Contacts/Main"; import CalendarsMain from "./Calendars/Main"; +import TasksMain from "./Tasks/Main"; import Journals from "./Journals"; import Settings from "./Settings"; @@ -102,7 +103,7 @@ export default function SyncGate() { - tasks + diff --git a/src/Tasks/Main.tsx b/src/Tasks/Main.tsx new file mode 100644 index 0000000..5df1dc3 --- /dev/null +++ b/src/Tasks/Main.tsx @@ -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>>(); + const [cachedCollections, setCachedCollections] = React.useState(); + 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 ( + + ); + } + + async function onItemSave(item: PimType, collectionUid: string, originalItem?: PimType): Promise { + 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 ( + + + history.push( + routeResolver.getRoute("pim.tasks._id", { itemUid: getItemNavigationUid(item) }) + )} + onItemSave={onItemSave} + /> + history.push( + routeResolver.getRoute("pim.tasks.new") + )} + /> + + + + + { + const [colUid, itemUid] = match.params.itemUid.split("|"); + const item = entries.get(colUid)?.get(itemUid); + if (!item) { + return (); + } + + /* FIXME: + const collection = collections!.find((x) => x.uid === colUid)!; + const readOnly = collection.accessLevel; + */ + const readOnly = false; + + return ( + + + + + +

Not currently implemented.

+
+ +
+ + + + +
+ +
+
+ ); + }} + /> +
+ ); +} + diff --git a/src/components/Tasks/QuickAdd.tsx b/src/Tasks/QuickAdd.tsx similarity index 82% rename from src/components/Tasks/QuickAdd.tsx rename to src/Tasks/QuickAdd.tsx index 48684f7..fd104d5 100644 --- a/src/components/Tasks/QuickAdd.tsx +++ b/src/Tasks/QuickAdd.tsx @@ -3,20 +3,19 @@ import * as React from "react"; -import * as EteSync from "etesync"; - import ICAL from "ical.js"; import uuid from "uuid"; import TextField from "@material-ui/core/TextField"; -import { TaskType, PimType, TaskStatusType } from "../../pim-types"; +import { TaskType, PimType, TaskStatusType } from "../pim-types"; +import { CachedCollection } from "../Pim/helpers"; interface PropsType { style: React.CSSProperties; onSubmit: (item: PimType, journalUid: string, originalItem?: PimType) => void; - defaultCollection: EteSync.CollectionInfo; + defaultCollection: CachedCollection; } function QuickAdd(props: PropsType) { @@ -37,7 +36,7 @@ function QuickAdd(props: PropsType) { task.status = TaskStatusType.NeedsAction; task.lastModified = ICAL.Time.now(); - save(task, defaultCollection.uid, undefined); + save(task, defaultCollection.collection.uid, undefined); setTitle(""); } @@ -56,4 +55,4 @@ function QuickAdd(props: PropsType) { ); } -export default QuickAdd; \ No newline at end of file +export default QuickAdd; diff --git a/src/components/Tasks/Sidebar.tsx b/src/Tasks/Sidebar.tsx similarity index 90% rename from src/components/Tasks/Sidebar.tsx rename to src/Tasks/Sidebar.tsx index 677355f..db46e04 100644 --- a/src/components/Tasks/Sidebar.tsx +++ b/src/Tasks/Sidebar.tsx @@ -6,11 +6,11 @@ import InboxIcon from "@material-ui/icons/Inbox"; import LabelIcon from "@material-ui/icons/LabelOutlined"; import TodayIcon from "@material-ui/icons/Today"; -import { setSettings } from "../../store/actions"; -import { StoreState } from "../../store"; +import { setSettings } from "../store/actions"; +import { StoreState } from "../store"; -import { List, ListItem, ListSubheader } from "../../widgets/List"; -import { TaskType } from "../../pim-types"; +import { List, ListItem, ListSubheader } from "../widgets/List"; +import { TaskType } from "../pim-types"; interface ListItemPropsType { name: string | null; @@ -69,4 +69,4 @@ export default React.memo(function Sidebar(props: { tasks: TaskType[] }) { {tagsList} ); -}); \ No newline at end of file +}); diff --git a/src/components/Tasks/Task.tsx b/src/Tasks/Task.tsx similarity index 89% rename from src/components/Tasks/Task.tsx rename to src/Tasks/Task.tsx index 2ddf95e..8d08e57 100644 --- a/src/components/Tasks/Task.tsx +++ b/src/Tasks/Task.tsx @@ -3,11 +3,11 @@ import * as React from "react"; -import PimItemHeader from "../PimItemHeader"; +import PimItemHeader from "../components/PimItemHeader"; -import { formatDate, formatOurTimezoneOffset } from "../../helpers"; +import { formatDate, formatOurTimezoneOffset } from "../helpers"; -import { TaskType } from "../../pim-types"; +import { TaskType } from "../pim-types"; class Task extends React.PureComponent { public props: { diff --git a/src/components/Tasks/TaskEdit.tsx b/src/Tasks/TaskEdit.tsx similarity index 97% rename from src/components/Tasks/TaskEdit.tsx rename to src/Tasks/TaskEdit.tsx index e36a943..319f96f 100644 --- a/src/components/Tasks/TaskEdit.tsx +++ b/src/Tasks/TaskEdit.tsx @@ -24,11 +24,11 @@ import IconDelete from "@material-ui/icons/Delete"; import IconCancel from "@material-ui/icons/Clear"; import IconSave from "@material-ui/icons/Save"; -import DateTimePicker from "../../widgets/DateTimePicker"; +import DateTimePicker from "../widgets/DateTimePicker"; -import ConfirmationDialog from "../../widgets/ConfirmationDialog"; -import TimezonePicker from "../../widgets/TimezonePicker"; -import Toast from "../../widgets/Toast"; +import ConfirmationDialog from "../widgets/ConfirmationDialog"; +import TimezonePicker from "../widgets/TimezonePicker"; +import Toast from "../widgets/Toast"; import { Location } from "history"; import { withRouter } from "react-router"; @@ -38,14 +38,14 @@ import * as ICAL from "ical.js"; import * as EteSync from "etesync"; -import { getCurrentTimezone, mapPriority } from "../../helpers"; +import { getCurrentTimezone, mapPriority } from "../helpers"; -import { TaskType, TaskStatusType, timezoneLoadFromName, TaskPriorityType, TaskTags } from "../../pim-types"; +import { TaskType, TaskStatusType, timezoneLoadFromName, TaskPriorityType, TaskTags } from "../pim-types"; import { History } from "history"; -import ColoredRadio from "../../widgets/ColoredRadio"; -import RRule, { RRuleOptions } from "../../widgets/RRule"; +import ColoredRadio from "../widgets/ColoredRadio"; +import RRule, { RRuleOptions } from "../widgets/RRule"; interface PropsType { collections: EteSync.CollectionInfo[]; diff --git a/src/components/Tasks/TaskList.tsx b/src/Tasks/TaskList.tsx similarity index 73% rename from src/components/Tasks/TaskList.tsx rename to src/Tasks/TaskList.tsx index 54e334a..c5b6cdb 100644 --- a/src/components/Tasks/TaskList.tsx +++ b/src/Tasks/TaskList.tsx @@ -3,17 +3,15 @@ import * as React from "react"; -import * as EteSync from "etesync"; +import { List } from "../widgets/List"; +import Toast, { PropsType as ToastProps } from "../widgets/Toast"; -import { List } from "../../widgets/List"; -import Toast, { PropsType as ToastProps } from "../../widgets/Toast"; - -import { TaskType, PimType, TaskStatusType } from "../../pim-types"; +import { TaskType, PimType, TaskStatusType } from "../pim-types"; import Divider from "@material-ui/core/Divider"; import Grid from "@material-ui/core/Grid"; import { useTheme, makeStyles } from "@material-ui/core/styles"; -import { useSelector, useDispatch } from "react-redux"; +import { useSelector } from "react-redux"; import Fuse from "fuse.js"; @@ -22,13 +20,9 @@ import Sidebar from "./Sidebar"; import Toolbar from "./Toolbar"; import QuickAdd from "./QuickAdd"; -import { StoreState, UserInfoData } from "../../store"; -import { formatDate } from "../../helpers"; -import { SyncInfo } from "../../SyncGate"; -import { fetchEntries } from "../../store/actions"; -import { Action } from "redux-actions"; -import { addJournalEntries } from "../../etesync-helpers"; -import { useCredentials } from "../../login"; +import { StoreState } from "../store"; +import { formatDate } from "../helpers"; +import { CachedCollection } from "../Pim/helpers"; function sortCompleted(a: TaskType, b: TaskType) { return (!!a.finished === !!b.finished) ? 0 : (a.finished) ? 1 : -1; @@ -106,11 +100,9 @@ const useStyles = makeStyles((theme) => ({ interface PropsType { entries: TaskType[]; - collections: EteSync.CollectionInfo[]; + collections: CachedCollection[]; onItemClick: (entry: TaskType) => void; onItemSave: (item: PimType, journalUid: string, originalItem?: PimType) => Promise; - syncInfo: SyncInfo; - userInfo: UserInfoData; } export default function TaskList(props: PropsType) { @@ -120,62 +112,25 @@ export default function TaskList(props: PropsType) { const [toast, setToast] = React.useState<{ message: string, severity: ToastProps["severity"] }>({ message: "", severity: undefined }); const settings = useSelector((state: StoreState) => state.settings.taskSettings); const { filterBy, sortBy } = settings; - const etesync = useCredentials()!; const theme = useTheme(); const classes = useStyles(); - const dispatch = useDispatch(); const { onItemClick } = props; - const handleToggleComplete = (task: TaskType, completed: boolean) => { + const handleToggleComplete = async (task: TaskType, completed: boolean) => { const clonedTask = task.clone(); clonedTask.status = completed ? TaskStatusType.Completed : TaskStatusType.NeedsAction; const nextTask = completed ? task.getNextOccurence() : null; - const syncJournal = props.syncInfo.get((task as any).journalUid); - - if (syncJournal === undefined) { - setToast({ message: "Could not sync.", severity: "error" }); - return; - } - - const journal = syncJournal.journal; - - let prevUid: string | null = null; - let last = syncJournal.journalEntries.last() as EteSync.Entry; - if (last) { - prevUid = last.uid; + try { + await props.onItemSave(clonedTask, task.collectionUid!, task); + if (nextTask) { + setToast({ message: `${nextTask.title} rescheduled for ${formatDate(nextTask.startDate ?? nextTask.dueDate)}`, severity: "success" }); + } + } catch (_e) { + setToast({ message: "Failed to save changes. This may be due to a network error.", severity: "error" }); } - - dispatch(fetchEntries(etesync, journal.uid, prevUid)) - .then((entriesAction: Action) => { - last = entriesAction.payload!.slice(-1).pop() as EteSync.Entry; - - if (last) { - prevUid = last.uid; - } - - const changeTask = [EteSync.SyncEntryAction.Change, clonedTask.toIcal()]; - - const updates = []; - updates.push(changeTask as [EteSync.SyncEntryAction, string]); - - if (nextTask) { - const addNextTask = [EteSync.SyncEntryAction.Add, nextTask.toIcal()]; - updates.push(addNextTask as [EteSync.SyncEntryAction, string]); - } - - return dispatch(addJournalEntries(etesync, props.userInfo, journal, prevUid, updates)); - }) - .then(() => { - if (nextTask) { - setToast({ message: `${nextTask.title} rescheduled for ${formatDate(nextTask.startDate ?? nextTask.dueDate)}`, severity: "success" }); - } - }) - .catch(() => { - setToast({ message: "Failed to save changes. This may be due to a network error.", severity: "error" }); - }); }; const potentialEntries = React.useMemo( diff --git a/src/components/Tasks/TaskListItem.tsx b/src/Tasks/TaskListItem.tsx similarity index 92% rename from src/components/Tasks/TaskListItem.tsx rename to src/Tasks/TaskListItem.tsx index 687af33..1020924 100644 --- a/src/components/Tasks/TaskListItem.tsx +++ b/src/Tasks/TaskListItem.tsx @@ -3,15 +3,15 @@ import * as React from "react"; -import { TaskType, TaskPriorityType } from "../../pim-types"; -import { ListItem } from "../../widgets/List"; +import { TaskType, TaskPriorityType } from "../pim-types"; +import { ListItem } from "../widgets/List"; import Checkbox from "@material-ui/core/Checkbox"; import CheckBoxOutlineBlankIcon from "@material-ui/icons/CheckBoxOutlineBlank"; import * as colors from "@material-ui/core/colors"; import Chip from "@material-ui/core/Chip"; -import { mapPriority, formatDate } from "../../helpers"; +import { mapPriority, formatDate } from "../helpers"; const checkboxColor = { [TaskPriorityType.Undefined]: colors.grey[600], diff --git a/src/components/Tasks/Toolbar.tsx b/src/Tasks/Toolbar.tsx similarity index 95% rename from src/components/Tasks/Toolbar.tsx rename to src/Tasks/Toolbar.tsx index 2046176..10b1957 100644 --- a/src/components/Tasks/Toolbar.tsx +++ b/src/Tasks/Toolbar.tsx @@ -1,7 +1,5 @@ import * as React from "react"; -import * as EteSync from "etesync"; - import Switch from "@material-ui/core/Switch"; import IconButton from "@material-ui/core/IconButton"; import MoreVertIcon from "@material-ui/icons/MoreVert"; @@ -14,15 +12,16 @@ import { makeStyles } from "@material-ui/core/styles"; import { Transition } from "react-transition-group"; import InputAdornment from "@material-ui/core/InputAdornment"; -import { PimType } from "../../pim-types"; +import { PimType } from "../pim-types"; import { useSelector, useDispatch } from "react-redux"; -import { setSettings } from "../../store/actions"; -import { StoreState } from "../../store"; +import { setSettings } from "../store/actions"; +import { StoreState } from "../store"; -import Menu from "../../widgets/Menu"; +import Menu from "../widgets/Menu"; import { ListItemText, ListItemSecondaryAction } from "@material-ui/core"; +import { CachedCollection } from "../Pim/helpers"; const transitionTimeout = 300; @@ -44,7 +43,7 @@ const useStyles = makeStyles((theme) => ({ })); interface PropsType { - defaultCollection: EteSync.CollectionInfo; + defaultCollection: CachedCollection; onItemSave: (item: PimType, journalUid: string, originalItem?: PimType) => Promise; showCompleted: boolean; showHidden: boolean; @@ -176,4 +175,4 @@ export default function Toolbar(props: PropsType) { ); -} \ No newline at end of file +}