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 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 '../api/EteSync'; import { createSelector } from 'reselect'; import { pure } from 'recompose'; import { History } from 'history'; import { PimType, ContactType, EventType, TaskType } from '../pim-types'; import Container from '../widgets/Container'; import JournalEntries from '../components/JournalEntries'; import ContactEdit from '../components/ContactEdit'; import Contact from '../components/Contact'; import EventEdit from '../components/EventEdit'; import Event from '../components/Event'; import TaskEdit from '../components/TaskEdit'; import Task from '../components/Task'; import PimMain from './PimMain'; import { routeResolver } from '../App'; import { store, CredentialsData, UserInfoData } from '../store'; import { fetchEntries } from '../store/actions'; import { SyncInfo } from '../SyncGate'; import { createJournalEntry } from '../etesync-helpers'; import { syncEntriesToItemMap, syncEntriesToEventItemMap, syncEntriesToTaskItemMap } from '../journal-processors'; function objValues(obj: any) { return Object.keys(obj).map((x) => obj[x]); } 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 = pure((props: any) => { const { syncInfo, items, uid, } = props; const journalItem = syncInfo.get(items[uid].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, originalContact?: PimType) => void; onItemDelete: (item: PimType, journalUid: string) => void; onItemCancel: () => void; classes: any; }; const styles = (theme: any) => ({ button: { marginLeft: theme.spacing.unit, }, leftIcon: { marginRight: theme.spacing.unit, }, }); const CollectionRoutes = withStyles(styles)(withRouter( class CollectionRoutesInner extends React.PureComponent { public render() { const props = this.props; const { classes } = this.props; const ComponentEdit = props.componentEdit; const ComponentView = props.componentView; return ( ( )} /> ( {(match.params.itemUid in props.items) && } )} /> ( )} /> (
)} />
); } } )); 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) { const syncJournal = this.props.syncInfo.get(journalUid); if (syncJournal === undefined) { return; } 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; } 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 saveEvent = store.dispatch( createJournalEntry( this.props.etesync, this.props.userInfo, journal, prevUid, action, item.toIcal())); (saveEvent as any).then(() => { this.props.history.goBack(); }); }); } 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( createJournalEntry( 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 { collectionsAddressBook, collectionsCalendar, collectionsTaskList, addressBookItems, calendarItems, taskListItems } = itemsSelector(this.props); return ( ( )} /> ( )} /> ( )} /> ( )} /> ); } } export default Pim;