Skip to content

Commit f2e9acc

Browse files
authored
Merge pull request #2203 from StoDevX/eventmapper
Allow editing events after fetching but before rendering
2 parents 60c6039 + aa224e7 commit f2e9acc

File tree

7 files changed

+102
-103
lines changed

7 files changed

+102
-103
lines changed

source/views/calendar/calendar-google.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import qs from 'querystring'
1313
import {GOOGLE_CALENDAR_API_KEY} from '../../lib/config'
1414
const TIMEZONE = 'America/Winnipeg'
1515

16-
type Props = TopLevelViewPropsType & {calendarId: string, poweredBy: ?PoweredBy}
16+
type Props = TopLevelViewPropsType & {
17+
calendarId: string,
18+
eventMapper?: EventType => EventType,
19+
poweredBy: ?PoweredBy,
20+
}
1721

1822
type State = {
1923
events: EventType[],
@@ -52,18 +56,30 @@ export class GoogleCalendarView extends React.Component<Props, State> {
5256
}
5357

5458
convertEvents(data: GoogleEventType[], now: moment): EventType[] {
55-
return data.map(event => {
59+
let events = data.map(event => {
5660
const startTime = moment(event.start.date || event.start.dateTime)
5761
const endTime = moment(event.end.date || event.end.dateTime)
62+
5863
return {
5964
startTime,
6065
endTime,
61-
summary: event.summary || '',
66+
title: event.summary || '',
67+
description: event.description || '',
6268
location: event.location || '',
6369
isOngoing: startTime.isBefore(now, 'day'),
64-
extra: {type: 'google', data: event},
70+
config: {
71+
startTime: true,
72+
endTime: true,
73+
subtitle: 'location',
74+
},
6575
}
6676
})
77+
78+
if (this.props.eventMapper) {
79+
events = events.map(this.props.eventMapper)
80+
}
81+
82+
return events
6783
}
6884

6985
getEvents = async (now: moment = moment.tz(TIMEZONE)) => {

source/views/calendar/calendar-util.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
import {Platform, Alert, Linking, Share} from 'react-native'
44
import RNCalendarEvents from 'react-native-calendar-events'
5-
import type {CleanedEventType} from './types'
5+
import getUrls from 'get-urls'
6+
import type {EventType} from './types'
67
import bugsnag from '../../bugsnag'
78
import {tracker} from '../../analytics'
8-
import {getTimes} from './clean-event'
9+
import {detailTimes} from './times'
910

10-
export function shareEvent(event: CleanedEventType): Promise<any> {
11+
export function shareEvent(event: EventType): Promise<any> {
1112
const title = event.title
1213
const times = getTimes(event)
1314
const location = event.location
@@ -17,7 +18,7 @@ export function shareEvent(event: CleanedEventType): Promise<any> {
1718
.catch(error => console.log(error.message))
1819
}
1920

20-
export function addToCalendar(event: CleanedEventType): Promise<boolean> {
21+
export function addToCalendar(event: EventType): Promise<boolean> {
2122
return RNCalendarEvents.authorizationStatus()
2223
.then(authStatus => {
2324
if (authStatus !== 'authorized') {
@@ -39,7 +40,7 @@ export function addToCalendar(event: CleanedEventType): Promise<boolean> {
3940
})
4041
}
4142

42-
async function saveEventToCalendar(event: CleanedEventType): Promise<boolean> {
43+
async function saveEventToCalendar(event: EventType): Promise<boolean> {
4344
try {
4445
await RNCalendarEvents.saveEvent(event.title, {
4546
location: event.location,
@@ -88,3 +89,19 @@ async function requestCalendarAccess(): Promise<boolean> {
8889

8990
return true
9091
}
92+
93+
export function getLinksFromEvent(event: EventType) {
94+
// Clean up returns, newlines, tabs, and misc symbols...
95+
// ...and search for links in the text
96+
return Array.from(getUrls(event.description))
97+
}
98+
99+
export function getTimes(event: EventType) {
100+
const {allDay, start, end} = detailTimes(event)
101+
102+
if (allDay) {
103+
return `All-Day on ${event.startTime.format('MMM D.')}`
104+
}
105+
106+
return `${start}${end ? ' to ' + end : ''}`
107+
}
Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,26 @@
11
// @flow
22
import type {EventType} from './types'
33
import {fastGetTrimmedText} from '../../lib/html'
4-
import getUrls from 'get-urls'
5-
import {detailTimes} from './times'
64

75
export function cleanEvent(event: EventType) {
8-
const title = fastGetTrimmedText(event.summary || '')
9-
const summary = fastGetTrimmedText(event.extra.data.description || '')
10-
const rawSummary = cleanDescription(event.extra.data.description || '')
11-
const location = fastGetTrimmedText(event.location || '')
12-
const times = getTimes(event) ? getTimes(event) : ''
6+
const title = fastGetTrimmedText(event.title)
7+
const description = cleanDescription(event.description)
8+
const location = fastGetTrimmedText(event.location)
139

1410
return {
1511
...event,
1612
title,
17-
summary,
18-
rawSummary,
13+
description,
1914
location,
20-
times,
2115
}
2216
}
2317

2418
function cleanDescription(desc: string) {
2519
const description = fastGetTrimmedText(desc || '')
20+
2621
if (description == 'See more details') {
2722
return ''
2823
}
2924

3025
return description
3126
}
32-
33-
export function getTimes(event: EventType) {
34-
const {allDay, start, end} = detailTimes(event)
35-
36-
if (allDay) {
37-
return `All-Day on ${event.startTime.format('MMM D.')}`
38-
}
39-
40-
return `${start}${end ? ' to ' + end : ''}`
41-
}
42-
43-
export function getLinksFromEvent(event: EventType) {
44-
// Clean up returns, newlines, tabs, and misc symbols...
45-
// ...and search for links in the text
46-
const description = event.extra.data.description || ''
47-
return Array.from(getUrls(description))
48-
}

source/views/calendar/event-detail.android.js

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
// @flow
22
import * as React from 'react'
33
import {Text, ScrollView, StyleSheet} from 'react-native'
4-
import type {CleanedEventType, PoweredBy} from './types'
4+
import type {EventType, PoweredBy} from './types'
55
import type {TopLevelViewPropsType} from '../types'
66
import {ShareButton} from '../components/nav-buttons'
77
import openUrl from '../components/open-url'
88
import {Card} from '../components/card'
9-
import {getLinksFromEvent} from './clean-event'
109
import * as c from '../components/colors'
1110
import {ButtonCell} from '../components/cells/button'
12-
import {addToCalendar, shareEvent} from './calendar-util'
11+
import {
12+
getLinksFromEvent,
13+
addToCalendar,
14+
shareEvent,
15+
getTimes,
16+
} from './calendar-util'
1317
import delay from 'delay'
1418
import {ListFooter} from '../components/list'
1519

@@ -36,39 +40,22 @@ const styles = StyleSheet.create({
3640
},
3741
})
3842

39-
function Title({event}: {event: CleanedEventType}) {
40-
return event.title ? <Text style={styles.name}>{event.title}</Text> : null
41-
}
42-
43-
function Description({event}: {event: CleanedEventType}) {
44-
return event.rawSummary ? (
45-
<Card header="Description" style={styles.card}>
46-
<Text style={styles.cardBody}>{event.rawSummary}</Text>
47-
</Card>
48-
) : null
49-
}
50-
51-
function When({event}: {event: CleanedEventType}) {
52-
return event.times ? (
53-
<Card header="When" style={styles.card}>
54-
<Text style={styles.cardBody}>{event.times}</Text>
43+
function MaybeCard({header, content}: {header: string, content: string}) {
44+
return content.trim() ? (
45+
<Card header={header} style={styles.card}>
46+
<Text style={styles.cardBody}>{content}</Text>
5547
</Card>
5648
) : null
5749
}
5850

59-
function Location({event}: {event: CleanedEventType}) {
60-
return event.location ? (
61-
<Card header="Location" style={styles.card}>
62-
<Text style={styles.cardBody}>{event.location}</Text>
63-
</Card>
64-
) : null
51+
function Title({title}: {title: EventType}) {
52+
return title ? <Text style={styles.name}>{title}</Text> : null
6553
}
6654

67-
function Links({event}: {event: CleanedEventType}) {
68-
const links = getLinksFromEvent(event)
69-
return links.length ? (
55+
function Links({urls}: {urls: Array<string>}) {
56+
return urls.length ? (
7057
<Card header="Links" style={styles.card}>
71-
{links.map(url => (
58+
{urls.map(url => (
7259
<Text key={url} onPress={() => openUrl(url)} style={styles.cardBody}>
7360
{url}
7461
</Text>
@@ -91,7 +78,7 @@ const CalendarButton = ({message, disabled, onPress}) => {
9178

9279
type Props = TopLevelViewPropsType & {
9380
navigation: {
94-
state: {params: {event: CleanedEventType, poweredBy: ?PoweredBy}},
81+
state: {params: {event: EventType, poweredBy: ?PoweredBy}},
9582
},
9683
}
9784

@@ -114,7 +101,7 @@ export class EventDetail extends React.PureComponent<Props, State> {
114101
disabled: false,
115102
}
116103

117-
addEvent = async (event: CleanedEventType) => {
104+
addEvent = async (event: EventType) => {
118105
const start = Date.now()
119106
this.setState(() => ({message: 'Adding event to calendar…'}))
120107

@@ -146,11 +133,13 @@ export class EventDetail extends React.PureComponent<Props, State> {
146133

147134
return (
148135
<ScrollView>
149-
<Title event={event} />
150-
<When event={event} />
151-
<Location event={event} />
152-
<Description event={event} />
153-
<Links event={event} />
136+
<Title title={event.title} />
137+
<MaybeCard content={getTimes(event)} header="When" />
138+
<MaybeCard content={event.location} header="Location" />
139+
<MaybeCard content={event.description} header="Description" />
140+
141+
<Links urls={getLinksFromEvent(event)} />
142+
154143
<CalendarButton
155144
disabled={this.state.disabled}
156145
message={this.state.message}

source/views/calendar/event-detail.ios.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
import * as React from 'react'
33
import {Text, ScrollView, StyleSheet} from 'react-native'
44
import {Cell, Section, TableView} from 'react-native-tableview-simple'
5-
import type {CleanedEventType, PoweredBy} from './types'
5+
import type {EventType, PoweredBy} from './types'
66
import type {TopLevelViewPropsType} from '../types'
77
import {ShareButton} from '../components/nav-buttons'
88
import openUrl from '../components/open-url'
99
import {ListFooter} from '../components/list'
10-
import {getLinksFromEvent} from './clean-event'
1110
import {ButtonCell} from '../components/cells/button'
12-
import {addToCalendar, shareEvent} from './calendar-util'
11+
import {
12+
getLinksFromEvent,
13+
addToCalendar,
14+
shareEvent,
15+
getTimes,
16+
} from './calendar-util'
1317
import delay from 'delay'
1418

1519
const styles = StyleSheet.create({
@@ -32,7 +36,7 @@ function MaybeSection({header, content}: {header: string, content: string}) {
3236
) : null
3337
}
3438

35-
function Links({header, event}: {header: string, event: CleanedEventType}) {
39+
function Links({header, event}: {header: string, event: EventType}) {
3640
const links = getLinksFromEvent(event)
3741

3842
return links.length ? (
@@ -63,7 +67,7 @@ const CalendarButton = ({message, disabled, onPress}) => {
6367

6468
type Props = TopLevelViewPropsType & {
6569
navigation: {
66-
state: {params: {event: CleanedEventType, poweredBy: ?PoweredBy}},
70+
state: {params: {event: EventType, poweredBy: ?PoweredBy}},
6771
},
6872
}
6973

@@ -86,7 +90,7 @@ export class EventDetail extends React.PureComponent<Props, State> {
8690
disabled: false,
8791
}
8892

89-
addEvent = async (event: CleanedEventType) => {
93+
addEvent = async (event: EventType) => {
9094
const start = Date.now()
9195
this.setState(() => ({message: 'Adding event to calendar…'}))
9296

@@ -120,9 +124,9 @@ export class EventDetail extends React.PureComponent<Props, State> {
120124
<ScrollView>
121125
<TableView>
122126
<MaybeSection content={event.title} header="EVENT" />
123-
<MaybeSection content={event.times} header="TIME" />
127+
<MaybeSection content={getTimes(event)} header="TIME" />
124128
<MaybeSection content={event.location} header="LOCATION" />
125-
<MaybeSection content={event.rawSummary} header="DESCRIPTION" />
129+
<MaybeSection content={event.description} header="DESCRIPTION" />
126130
<Links event={event} header="LINKS" />
127131
<CalendarButton
128132
disabled={this.state.disabled}

source/views/calendar/event-row.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,10 @@ export default class EventRow extends React.PureComponent<Props> {
4242

4343
render() {
4444
const {event} = this.props
45-
const title = fastGetTrimmedText(event.summary)
45+
const title = fastGetTrimmedText(event.title)
4646

47-
const location =
48-
event.location && event.location.trim().length ? (
49-
<Detail>{event.location}</Detail>
50-
) : null
47+
let subtitle = event[event.config.subtitle]
48+
subtitle = subtitle ? subtitle.trim() : null
5149

5250
return (
5351
<ListRow
@@ -68,7 +66,7 @@ export default class EventRow extends React.PureComponent<Props> {
6866
paddingTop={2}
6967
>
7068
<Title>{title}</Title>
71-
{location}
69+
{subtitle ? <Detail>{subtitle}</Detail> : null}
7270
</Column>
7371
</Row>
7472
</ListRow>
@@ -89,8 +87,12 @@ function CalendarTimes({event, style}: {event: EventType, style: any}) {
8987

9088
return (
9189
<Column style={style}>
92-
<Text style={[styles.time, styles.start]}>{start}</Text>
93-
<Text style={[styles.time, styles.end]}>{end}</Text>
90+
{event.config.startTime ? (
91+
<Text style={[styles.time, styles.start]}>{start}</Text>
92+
) : null}
93+
{event.config.endTime ? (
94+
<Text style={[styles.time, styles.end]}>{end}</Text>
95+
) : null}
9496
</Column>
9597
)
9698
}

0 commit comments

Comments
 (0)