1
0
Fork 0

Event page scaffold

master
Ambrose Chua 2017-04-16 17:55:31 +08:00
parent ba0295ed94
commit 62a8b0eabb
5 changed files with 129 additions and 15 deletions

View File

@ -31,6 +31,7 @@ A school event planner and timetable
- [x] Display events as agenda
- [x] Display events as calendar
- [ ] Drag one-time events around to modify
- [ ] Hide weekly events in month view
- [ ] Show heatmap of the availability of the users in a group when creating an event
- This is the event planning feature

View File

@ -7,6 +7,7 @@ import PageLogin from '../pages/login';
import PageLoginSchool from '../pages/login_school';
import PageGroups from '../pages/groups';
import PageGroup from '../pages/group';
import PageEvent from '../pages/event';
export default class App extends React.Component {
getChildContext() {
@ -33,9 +34,10 @@ export default class App extends React.Component {
<LayoutMain>
<Route exact path="/" component={PageHome} />
<Route path="/login" component={PageLogin} />
<Route path="/login/:id" component={PageLoginSchool} />
<Route exact path="/login/:id" component={PageLoginSchool} />
<Route exact path="/groups" component={PageGroups} />
<Route path="/groups/:id" component={PageGroup} />
<Route exact path="/groups/:id" component={PageGroup} />
<Route exact path="/groups/:group/events/:id" component={PageEvent} />
</LayoutMain>
</Router>
);

108
app/pages/event.jsx Normal file
View File

@ -0,0 +1,108 @@
import React from 'react';
import { List, ListSubHeader, ListItem, ListDivider, FontIcon } from 'react-toolbox';
export default class PageEvent extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
group: props.match.params.group,
id: props.match.params.id,
event: {
name: 'Event name',
attachments: [
{ id: 1, oid: '15310b96d210ab630f8d4dea3cda6e60c77a789a' },
{ id: 2, oid: '3a8fa8ed9294aac827ecbc5bd2b0a8aba4373792' },
{ id: 3, oid: '56930768d695303ade973f02bbcc304b5f441ea6' },
],
descriptions: [
{ id: 0, text: 'This is a very long description' },
],
},
};
// this.fetchEvent(context);
}
async fetchEvent(context = this.context) {
return fetch(`/api/v1/schools/${context.user.school}/groups${this.state.group}/eventsOnce/${this.state.id}`, {
headers: {
FakeAuth: true,
FakeID: context.user.id,
},
})
.then(data => data.json())
.then((data) => {
this.setState({
event: data,
});
})
.catch((err) => {
console.error(err);
});
}
render() {
return (
<main>
<h1>{this.state.event.name}</h1>
<List
selectable
ripple
>
<ListSubHeader
caption="Description"
/>
{this.state.event.descriptions && this.state.event.descriptions.map(d => (
<ListItem
key={d.id}
caption={d.text}
rightActions={[
<FontIcon key={0} value="mode_edit" onClick={() => console.log('Hi')} />,
]}
/>
))}
<ListDivider />
<ListSubHeader
caption="Attachments"
/>
{this.state.event.attachments && this.state.event.attachments.map(a => (
<ListItem
key={a.id}
caption={a.oid}
legend={`/files/${a.oid}`}
rightActions={[
<FontIcon key={0} value="delete" onClick={() => console.log('Hi')} />,
]}
/>
))}
<ListItem
caption="Upload an attachment"
leftIcon="add"
onClick={() => {}}
/>
</List>
</main>
);
}
}
PageEvent.contextTypes = {
router: React.PropTypes.shape({
history: React.PropTypes.shape({
push: React.PropTypes.func.isRequired,
}).isRequired,
}).isRequired,
// eslint-disable-next-line react/forbid-prop-types
user: React.PropTypes.object.isRequired,
token: React.PropTypes.string,
};
PageEvent.propTypes = {
match: React.PropTypes.shape({
params: React.PropTypes.shape({
group: React.PropTypes.string.isRequired,
id: React.PropTypes.string.isRequired,
}).isRequired,
}).isRequired,
};

View File

@ -1,6 +1,6 @@
import React from 'react';
import { Tabs, Tab, Card, CardTitle, CardText, CardActions, Button } from 'react-toolbox';
import { Tabs, Tab, Card, CardTitle, CardText, Button } from 'react-toolbox';
import BigCalendar from 'react-big-calendar';
import moment from 'moment-timezone';
@ -184,9 +184,6 @@ export default class PageHome extends React.Component {
<Card key={`${event.id}@${event.start}`} style={{ margin: '1em', width: 'auto' }}>
<CardTitle title={event.name} />
<CardText>{`${moment(event.start).format('dddd, MMMM Do YYYY, HH:mm')} to ${moment(event.end).format('MMMM Do, HH:mm')}`}</CardText>
<CardActions>
<Button label="Edit" accent />
</CardActions>
</Card>,
)}
</Tab>

View File

@ -141,8 +141,10 @@ export default class Database {
pwd_hash: undefined,
oid_id: undefined,
})),
eventsOnce: results[2],
eventsWeekly: results[3],
// eslint-disable-next-line no-underscore-dangle
eventsOnce: results[2].map(e => Object.assign({ group: e.group_ }, e)),
// eslint-disable-next-line no-underscore-dangle
eventsWeekly: results[3].map(e => Object.assign({ group: e.group_ }, e)),
}));
}
@ -167,12 +169,9 @@ export default class Database {
FROM event_once
WHERE event_once.group_ = ?
AND event_once.id = ?
`, [group, id]);
}
// eslint-disable-next-line
async getEventClashesWith(school, group, id) {
// TODO
`, [group, id])
// eslint-disable-next-line no-underscore-dangle
.then(e => Object.assign({ group: e.group_ }, e));
}
async getUserEventsBetween(school, user, start, end) {
@ -196,7 +195,12 @@ export default class Database {
AND member.user = ?
`, [user]);
return Promise.all([getEventsOnce, getEventsWeekly])
.then(results => ({ eventsOnce: results[0], eventsWeekly: results[1] }));
.then(results => ({
// eslint-disable-next-line no-underscore-dangle
eventsOnce: results[0].map(e => Object.assign({ group: e.group_ }, e)),
// eslint-disable-next-line no-underscore-dangle
eventsWeekly: results[1].map(e => Object.assign({ group: e.group_ }, e)),
}));
}
query(query, values, options = {}) {
@ -316,6 +320,8 @@ export default class Database {
`CREATE TABLE attachment (
event_once INT NOT NULL,
id INT NOT NULL,
type CHAR(3) NOT NULL,
text_oid VARCHAR(1024) NOT NULL,
PRIMARY KEY (event_once, id),
FOREIGN KEY (event_once) REFERENCES event_once(id) ON DELETE CASCADE ON UPDATE CASCADE
)`,