Skip to content

Commit

Permalink
Initial commit with README and examples
Browse files Browse the repository at this point in the history
  • Loading branch information
theLAZYmd committed Nov 23, 2019
1 parent b42fbcf commit 7ce814c
Show file tree
Hide file tree
Showing 9 changed files with 794 additions and 1 deletion.
116 changes: 115 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,116 @@
# react-google-calendar
A functional calendar renderer for events from a google calendar
========================================

React Google Calendar is a functional and easy way

- Easy to use
- Modularised (doesn't re-render components unnecessarily)
- API light (makes use of the Google Calendar APIs)
- Customisable: provides a whole range of options to affect how Calendar data is parsed
- Light on dependencies: relies on axios, he, and react
- Native strong typing - no need to install @types/ definition

Install
-------

react-google-calendar is available on [npm](https://www.npmjs.com/package/react-google-calendar). It
can be installed with the following command:

npm install react-google-calendar

If you don't want to use npm, [clone this respository](https://github.com/theLAZYmd/react-google-calendar.git) to your project source.


Homepage & Demo
----------------

- [Demo](https://oxfordunichess.github.io/oucc-frontend/termcard)

To learn how to use React Google Calendar:

- [Examples](https://github.com/theLAZYmd/react-google-calendar/blob/master/examples)


React Google Calendar in your React projects
--------------------

Simply import the package into your component with

```jsx
import Calendar from 'react-google-calendar';
```

And use as a React component, specifying three settings of:
- SessionID: [optional] a query parameter with which to make requests through axios. Not required, used to request new data from CDNs in the project in which this was first designed (leave as '' for none).
- Settings: See below for settings format
- Styles: a module.css component

```html
<Calendar sessionID={sessionID} settings={settings} styles={styles}/>
```

Register for an API key at https://developers.google.com/calendar

The settings config should be of the following format:

```js
{

// Register for an API key
"APIkey": "",

/**
* Calendar IDs should be an object of key-value pairs.
* Each key should be a calendar link of the format
* {random string of 26-letters}@group.calendar.google.com
* Example: [email protected]
* Alternatively personal user calendars will appear as
* [email protected]
* Get this calendar ID by going to
* Settings and Sharing > Integrate Calendar > CalendarID
* Make your calendar publically visible in Access Permissions
* The value fields of this object should be html colours
*/
"calendarIDs": {
[calendarID: string]: [colour: string]

// If you want your locations to be rendered as a link to a map. Leave blank for none. Use Google Maps (below) as default
},
"mapsLink": "https://www.google.com/maps/search/",

/**
* The renderer takes the first line of a location
* in the Google Calendar entry and renders it
* Use this to 'adjust' any locations
*/
"locationReplacers": {
"Christ Church Cathedral": "Christ Church"
},

// When should the calendar start date be? (a Sunday)
"start": "6 October 2019",

// When should the calendar finish date be?
"finish": "8 December 2019",

// What should the calendar title be?
"title": "MT'19",

// How should the days of the week be displayed on the top row?
// (Must start with a Sunday)
"days": [
"SUN",
"MON",
"TUES",
"WED",
"THURS",
"FRI",
"SAT"
]
}
```

Contributing
------------

To discuss a new feature or ask a question, open an issue. To fix a bug, submit a pull request to be credited with the [contributors](https://github.com/theLAZYmd/react-google-calendar/graphs/contributors)! Remember, a pull request, *with test*, is best.
81 changes: 81 additions & 0 deletions event.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import he from 'he';
import {GoogleEvent, GoogleLocation, StringDictionary} from './interfaces';

const regexes = {
space: /\s+/g,
facebook: /(?:(?:http|https):\/\/)?(?:www.)?facebook.com\/(?:events\/)?(?:[0-9]*\/)/
};


export default class Event {

link: string;
title: string;
status: string;
start: Date;
created: Date;
end: Date;
calendarName: string;
color: string;
rawLocation: GoogleLocation | string;
locationReplacers: StringDictionary;
rawDescription: string;
map: string;

private _location: string;
private _facebookEvent: string;
private _description: string;

constructor(event: GoogleEvent, calendarName: string, color: string, {
locationReplacers,
mapsLink
}: {
locationReplacers: StringDictionary,
mapsLink: string
}) {
this.created = new Date(event.created);
this.link = event.htmlLink;
this.title = event.summary;
this.status = event.status;
this.start = new Date(event.start.dateTime);
this.end = new Date(event.end.dateTime);
this.calendarName = calendarName;
this.color = color;

this.rawLocation = event.location || '';
this.locationReplacers = locationReplacers;
this.rawDescription = he.decode(event.description || '');
this.map = mapsLink ? mapsLink + this.rawLocation.replace(regexes.space, '+') : '';
}

get location(): string {
if (this._location) return this._location;
let location;
let l = this.rawLocation.split(',').shift();
if (this.locationReplacers[l]) location = this.locationReplacers[l];
else location = l;
return this._location = location;
}


get facebookEvent(): string {
if (this._facebookEvent) return this._facebookEvent;
let facebookEvent = '';
if (regexes.facebook.test(this.rawDescription)) facebookEvent = this.rawDescription.match(regexes.facebook)[0];
return this._facebookEvent = facebookEvent;
}

get description(): string {
if (this._description) return this._description;
let description = this.rawDescription;

let start = description.indexOf('<a');
while (start !== -1) {
let end = description.indexOf('/a>') + 3;
description = description.slice(0, start) + description.slice(end);
start = description.indexOf('<a');
}
description = description.replace(this.facebookEvent, '').trim();
return this._description = description;
}
}
22 changes: 22 additions & 0 deletions examples/Termcard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { ReactElement } from 'react';
import {CalendarSettings} from '../interfaces';

import Calendar from '../index';
const settings = require('./config.json') as CalendarSettings;

const styles = require('./calendar.module.css');

export default class Termcard extends React.Component {

render(): ReactElement {
let sessionID = Math.random().toString(16).slice(2);
return (
<div>
<div>
<Calendar sessionID={sessionID} settings={settings} styles={styles}/>
</div>
</div>
);
}

}
63 changes: 63 additions & 0 deletions examples/calendar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
div.key {
display: flex;
flex-direction: row;
}

div.key > div {
display: flex;
flex-direction: row;
padding: 0 6px;
}

span.status {
padding: 0 8px;
cursor: pointer;
}

.event {
display: flex;
flex-direction: column;
align-items: center;
padding: 5px 0;
}

.eventHeader {
display: flex;
flex-direction: row;
}

.eventName {
margin-block-start: 0;
margin-block-end: 0;
}

a.eventTitle {text-decoration: none}
a.eventTitle:link {text-decoration: none}
a.eventTitle:visited {text-decoration: none}
a.eventTitle:hover {text-decoration: none}
a.noEvent {
color: black
}
.table {
white-space: pre-wrap;
table-layout: fixed;
max-width: 100%;
min-width: 800px;
}

.table td > div {
word-wrap: break-word;
height: 100%;
}

.table th.firstColumn {
width: 100px;
}

td.cell:hover {
background-color: #ffebb9 !important;
}

td.today {
background-color: peachpuff !important;
}
28 changes: 28 additions & 0 deletions examples/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"APIkey": "",
"calendarIDs": {
"[email protected]": "blue",
"[email protected]": "red",
"[email protected]": "orange",
"[email protected]": "yellow",
"[email protected]": "lawngreen",
"[email protected]": "limegreen",
"[email protected]": "forestgreen"
},
"mapsLink": "https://www.google.com/maps/search/",
"locationReplacers": {
"Christ Church Cathedral": "Christ Church"
},
"start": "6 October 2019",
"finish": "8 December 2019",
"title": "MT'19",
"days": [
"SUN",
"MON",
"TUES",
"WED",
"THURS",
"FRI",
"SAT"
]
}
Loading

0 comments on commit 7ce814c

Please sign in to comment.