Event page scaffold
parent
ba0295ed94
commit
62a8b0eabb
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
)`,
|
||||
|
|
Loading…
Reference in New Issue