From 864dad372f37f900313adbe303147fbca294648c Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Fri, 8 Dec 2017 09:51:14 +0000 Subject: [PATCH] Make special types for events and calendars. This will simplify extracting values and already removes some redundancy. --- src/AddressBook.tsx | 15 ++++++++------- src/Calendar.tsx | 25 ++++--------------------- src/Contact.tsx | 14 +++++++------- src/Event.tsx | 4 +++- src/JournalAddressBook.tsx | 10 +++++----- src/JournalCalendar.tsx | 8 ++++---- src/JournalEntries.tsx | 10 ++++++---- src/Pim.tsx | 4 +--- src/PimMain.tsx | 10 ++++++---- src/journal-processors.tsx | 14 ++++++++------ src/pim-types.tsx | 31 +++++++++++++++++++++++++++++++ 11 files changed, 83 insertions(+), 62 deletions(-) create mode 100644 src/pim-types.tsx diff --git a/src/AddressBook.tsx b/src/AddressBook.tsx index cbdd7ac..dd829d4 100644 --- a/src/AddressBook.tsx +++ b/src/AddressBook.tsx @@ -1,18 +1,18 @@ import * as React from 'react'; import { List, ListItem } from 'material-ui/List'; -import * as ICAL from 'ical.js'; +import { ContactType } from './pim-types'; class AddressBook extends React.Component { props: { - entries: Array, - onItemClick: (contact: ICAL.Component) => void, + entries: Array, + onItemClick: (contact: ContactType) => void, }; render() { let entries = this.props.entries.sort((_a, _b) => { - const a = _a.getFirstPropertyValue('fn'); - const b = _b.getFirstPropertyValue('fn'); + const a = _a.fn; + const b = _b.fn; if (a < b) { return -1; @@ -24,8 +24,9 @@ class AddressBook extends React.Component { }); let itemList = entries.map((entry) => { - const uid = entry.getFirstPropertyValue('uid'); - const name = entry.getFirstPropertyValue('fn'); + const uid = entry.uid; + const name = entry.fn; + return ( (this.props.onItemClick(entry))} /> ); diff --git a/src/Calendar.tsx b/src/Calendar.tsx index 3e55e45..b2e558a 100644 --- a/src/Calendar.tsx +++ b/src/Calendar.tsx @@ -3,33 +3,18 @@ import BigCalendar from 'react-big-calendar'; import 'react-big-calendar/lib/css/react-big-calendar.css'; import * as moment from 'moment'; -import * as ICAL from 'ical.js'; +import { EventType } from './pim-types'; BigCalendar.momentLocalizer(moment); -class EventWrapper extends ICAL.Event { - - get title() { - return this.summary; - } - - get start() { - return this.startDate.toJSDate(); - } - - get end() { - return this.endDate.toJSDate(); - } -} - class Calendar extends React.Component { state: { currentDate?: Date; }; props: { - entries: Array, - onItemClick: (contact: ICAL.Event) => void, + entries: Array, + onItemClick: (contact: EventType) => void, }; constructor(props: any) { @@ -38,9 +23,7 @@ class Calendar extends React.Component { } render() { - let entries = this.props.entries.map((value) => ( - new EventWrapper(value) - )).sort((a, b) => { + let entries = this.props.entries.sort((a, b) => { if (a.summary < b.summary) { return -1; } else if (a.summary > b.summary) { diff --git a/src/Contact.tsx b/src/Contact.tsx index d18b3c3..626a3b0 100644 --- a/src/Contact.tsx +++ b/src/Contact.tsx @@ -6,11 +6,11 @@ import CommunicationChatBubble from 'material-ui/svg-icons/communication/chat-bu import CommunicationEmail from 'material-ui/svg-icons/communication/email'; import { indigo500 } from 'material-ui/styles/colors'; -import * as ICAL from 'ical.js'; +import { ContactType } from './pim-types'; class Contact extends React.Component { props: { - contact?: ICAL.Component, + contact?: ContactType, }; render() { @@ -19,10 +19,10 @@ class Contact extends React.Component { } const contact = this.props.contact; - const uid = contact.getFirstPropertyValue('uid'); - const name = contact.getFirstPropertyValue('fn'); + const uid = contact.comp.getFirstPropertyValue('uid'); + const name = contact.comp.getFirstPropertyValue('fn'); - const phoneNumbers = contact.getAllProperties('tel').map((prop, idx) => { + const phoneNumbers = contact.comp.getAllProperties('tel').map((prop, idx) => { const json = prop.toJSON(); const values = prop.getValues().map((val) => ( { + const emails = contact.comp.getAllProperties('email').map((prop, idx) => { const json = prop.toJSON(); const values = prop.getValues().map((val) => ( ( + const theRest = contact.comp.getAllProperties().filter((prop) => ( skips.indexOf(prop.name) === -1 )).map((prop, idx) => { const values = prop.getValues().map((_val) => { diff --git a/src/Event.tsx b/src/Event.tsx index 9ab8d53..60a4f24 100644 --- a/src/Event.tsx +++ b/src/Event.tsx @@ -3,6 +3,8 @@ import * as moment from 'moment'; import * as ICAL from 'ical.js'; +import { EventType } from './pim-types'; + function formatDateRange(start: ICAL.Time, end: ICAL.Time) { const mStart = moment(start.toJSDate()); const mEnd = moment(end.toJSDate()); @@ -33,7 +35,7 @@ function formatDateRange(start: ICAL.Time, end: ICAL.Time) { class Event extends React.Component { props: { - event?: ICAL.Event, + event?: EventType, }; render() { diff --git a/src/JournalAddressBook.tsx b/src/JournalAddressBook.tsx index 39084ad..b2ba572 100644 --- a/src/JournalAddressBook.tsx +++ b/src/JournalAddressBook.tsx @@ -1,8 +1,6 @@ import * as React from 'react'; import { Route, Switch, withRouter } from 'react-router'; -import * as ICAL from 'ical.js'; - import * as EteSync from './api/EteSync'; import { routeResolver } from './App'; @@ -10,10 +8,12 @@ import { routeResolver } from './App'; import AddressBook from './AddressBook'; import Contact from './Contact'; +import { ContactType } from './pim-types'; + class JournalAddressBook extends React.Component { props: { journal: EteSync.Journal, - entries: Map, + entries: Map, history?: any, }; @@ -22,8 +22,8 @@ class JournalAddressBook extends React.Component { this.contactClicked = this.contactClicked.bind(this); } - contactClicked(contact: ICAL.Component) { - const uid = contact.getFirstPropertyValue('uid'); + contactClicked(contact: ContactType) { + const uid = contact.uid; this.props.history.push( routeResolver.getRoute('journals._id.items._id', { journalUid: this.props.journal.uid, itemUid: uid })); diff --git a/src/JournalCalendar.tsx b/src/JournalCalendar.tsx index f183e50..801873f 100644 --- a/src/JournalCalendar.tsx +++ b/src/JournalCalendar.tsx @@ -6,14 +6,14 @@ import { routeResolver } from './App'; import Calendar from './Calendar'; import Event from './Event'; -import * as ICAL from 'ical.js'; +import { EventType } from './pim-types'; import * as EteSync from './api/EteSync'; class JournalCalendar extends React.Component { props: { journal: EteSync.Journal, - entries: Map, + entries: Map, history?: any, }; @@ -22,7 +22,7 @@ class JournalCalendar extends React.Component { this.eventClicked = this.eventClicked.bind(this); } - eventClicked(event: ICAL.Event) { + eventClicked(event: EventType) { const uid = event.uid; this.props.history.push( @@ -48,7 +48,7 @@ class JournalCalendar extends React.Component { render={({match}) => { return ( - + ); }} /> diff --git a/src/JournalEntries.tsx b/src/JournalEntries.tsx index e91219c..1303b32 100644 --- a/src/JournalEntries.tsx +++ b/src/JournalEntries.tsx @@ -8,6 +8,8 @@ import IconEdit from 'material-ui/svg-icons/editor/mode-edit'; import * as ICAL from 'ical.js'; +import { EventType, ContactType } from './pim-types'; + import * as EteSync from './api/EteSync'; class JournalEntries extends React.Component { @@ -49,13 +51,13 @@ class JournalEntries extends React.Component { let name; let uid; if (comp.name === 'vcalendar') { - const vevent = new ICAL.Event(comp.getFirstSubcomponent('vevent')); + const vevent = new EventType(comp.getFirstSubcomponent('vevent')); name = vevent.summary; uid = vevent.uid; } else if (comp.name === 'vcard') { - const vcard = comp; - name = vcard.getFirstPropertyValue('fn'); - uid = vcard.getFirstPropertyValue('uid'); + const vcard = new ContactType(comp); + name = vcard.fn; + uid = vcard.uid; } else { name = 'Error processing entry'; uid = ''; diff --git a/src/Pim.tsx b/src/Pim.tsx index 56517b3..d656414 100644 --- a/src/Pim.tsx +++ b/src/Pim.tsx @@ -1,8 +1,6 @@ import * as React from 'react'; import { Route, Switch } from 'react-router'; -import * as ICAL from 'ical.js'; - import * as EteSync from './api/EteSync'; import Contact from './Contact'; @@ -91,7 +89,7 @@ class Pim extends React.Component { path={routeResolver.getRoute('pim.events._id')} exact={true} render={({match}) => ( - + )} /> diff --git a/src/PimMain.tsx b/src/PimMain.tsx index 37d72c4..9c87e47 100644 --- a/src/PimMain.tsx +++ b/src/PimMain.tsx @@ -6,12 +6,14 @@ import * as ICAL from 'ical.js'; import AddressBook from './AddressBook'; import Calendar from './Calendar'; +import { EventType, ContactType } from './pim-types'; + import { routeResolver } from './App'; class Pim extends React.Component { props: { - contacts: Array, - events: Array, + contacts: Array, + events: Array, history?: any, }; @@ -28,8 +30,8 @@ class Pim extends React.Component { routeResolver.getRoute('pim.events._id', { eventUid: uid })); } - contactClicked(contact: ICAL.Component) { - const uid = contact.getFirstPropertyValue('uid'); + contactClicked(contact: ContactType) { + const uid = contact.uid; this.props.history.push( routeResolver.getRoute('pim.contacts._id', { contactUid: uid })); diff --git a/src/journal-processors.tsx b/src/journal-processors.tsx index d2f2d1c..a7890cf 100644 --- a/src/journal-processors.tsx +++ b/src/journal-processors.tsx @@ -1,14 +1,16 @@ import * as ICAL from 'ical.js'; +import { EventType, ContactType } from './pim-types'; + import * as EteSync from './api/EteSync'; export function syncEntriesToItemMap(entries: EteSync.SyncEntry[]) { - let items: Map = new Map(); + let items: Map = new Map(); for (const syncEntry of entries) { - let comp = new ICAL.Component(ICAL.parse(syncEntry.content)); + let comp = new ContactType(new ICAL.Component(ICAL.parse(syncEntry.content))); - const uid = comp.getFirstPropertyValue('uid'); + const uid = comp.uid; if ((syncEntry.action === EteSync.SyncEntryAction.Add) || (syncEntry.action === EteSync.SyncEntryAction.Change)) { @@ -22,16 +24,16 @@ export function syncEntriesToItemMap(entries: EteSync.SyncEntry[]) { } export function syncEntriesToCalendarItemMap(entries: EteSync.SyncEntry[]) { - let items: Map = new Map(); + let items: Map = new Map(); for (const syncEntry of entries) { - let comp = new ICAL.Component(ICAL.parse(syncEntry.content)).getFirstSubcomponent('vevent'); + let comp = new EventType(new ICAL.Component(ICAL.parse(syncEntry.content)).getFirstSubcomponent('vevent')); if (comp === null) { continue; } - const uid = comp.getFirstPropertyValue('uid'); + const uid = comp.uid; if ((syncEntry.action === EteSync.SyncEntryAction.Add) || (syncEntry.action === EteSync.SyncEntryAction.Change)) { diff --git a/src/pim-types.tsx b/src/pim-types.tsx new file mode 100644 index 0000000..c461a9c --- /dev/null +++ b/src/pim-types.tsx @@ -0,0 +1,31 @@ +import * as ICAL from 'ical.js'; + +export class EventType extends ICAL.Event { + get title() { + return this.summary; + } + + get start() { + return this.startDate.toJSDate(); + } + + get end() { + return this.endDate.toJSDate(); + } +} + +export class ContactType { + comp: ICAL.Component; + + constructor(comp: ICAL.Component) { + this.comp = comp; + } + + get uid() { + return this.comp.getFirstPropertyValue('uid'); + } + + get fn() { + return this.comp.getFirstPropertyValue('fn'); + } +}