Skip to content

Commit

Permalink
Merge pull request #50 from googleinterns/activity-click-to-edit
Browse files Browse the repository at this point in the history
Activity click to edit feature.
  • Loading branch information
anan-ya-y authored Jul 16, 2020
2 parents 14a09d0 + 893746c commit 7c4ba9d
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 35 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/Utils/time.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as utils from './time';
import * as utils from './time.js';

const TZ_CHICAGO = 'America/Chicago';
const TZ_SINGAPORE = 'Asia/Singapore';
const TZ_SINGAPORE = 'Asia/Singapore';

test('new york date timestamp format', () => {
// Month parameter is zero indexed so it's actually the 10th month.
Expand Down
95 changes: 85 additions & 10 deletions frontend/src/components/ViewActivities/activity.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import React from 'react';
import Card from 'react-bootstrap/Card';
import * as time from '../Utils/time.js';
import * as DB from '../../constants/database.js'
import '../../styles/activities.css';
import Accordion from 'react-bootstrap/Accordion';
import { getField } from './activityfns.js';
import { Accordion, Button, Card, Col, Form, Row } from 'react-bootstrap';

/**
* Returns a dropdown of all the timezones.
*/
function timezonePicker() {
// TODO: Make this dropdown. (#51)
return <div></div>
}

/**
* A single activity.
Expand All @@ -12,20 +20,87 @@ import Accordion from 'react-bootstrap/Accordion';
* - `activity` The activity to display.
*/
class Activity extends React.Component {
/** {@inheritdoc} */
constructor(props) {
super(props);

this.state = { editing: false };

// Bind state users/modifiers to `this`.
this.setEditActivity = this.setEditActivity.bind(this);
this.finishEditActivity = this.finishEditActivity.bind(this);
this.displayCard = this.displayCard.bind(this);
}

/**
* Set the activity into editing mode.
*/
setEditActivity() {
this.setState({editing: true});
}

/**
* Set the activity into viewing mode.
*/
finishEditActivity() {
this.setState({editing: false});
}

/**
* Display the current activity, either in view or display mode.
*/
displayCard() {
let activity = this.props.activity;
if (!this.state.editing) { // View mode.
return (
<Card.Body onClick={this.setEditActivity}>
<p>Start time: {time.timestampToFormatted(activity[DB.ACTIVITIES_START_TIME])} </p>
<p>End time: {time.timestampToFormatted(activity[DB.ACTIVITIES_END_TIME])} </p>
</Card.Body>
);
} else { // Edit mode.
return (
// TODO: Save form. (#48)
<Form className="activity-editor" onSubmit={this.finishEditActivity}>
<Form.Group as={Row} controlId="formActivityTitle">
<Col sm={2}><Form.Label>Title:</Form.Label></Col>
<Col><Form.Control type="text" placeholder={activity[DB.ACTIVITIES_TITLE]}/></Col>
</Form.Group>
<Form.Group as={Row} controlId="formActivityStartTime">
<Col sm={2}><Form.Label>From:</Form.Label></Col>
<Col sm={4}><Form.Control type="date" label="date"/></Col>
<Col sm={2}><Form.Control type="time" label="time"/></Col>
<Col sm={1}>{timezonePicker()}</Col>
</Form.Group>
<Form.Group as={Row} controlId="formActivityEndTime">
<Col sm={2}><Form.Label>To:</Form.Label></Col>
<Col sm={4}><Form.Control type="date" label="date"/></Col>
<Col sm={2}><Form.Control type="time" label="time"/></Col>
<Col sm={1}>{timezonePicker()}</Col>
</Form.Group>
<Form.Group as={Row} controlId="formActivityDescription">
<Col sm={2}><Form.Label>Description:</Form.Label></Col>
<Col><Form.Control type="text"
placeholder={getField(activity, DB.ACTIVITIES_DESCRIPTION, "Add some details!") }/>
</Col>
</Form.Group>
<Button type="submit" className="float-right">Done!</Button>
</Form>
)
}
}

/** @inheritdoc */
render() {
const activity = this.props.activity;
return (
<Accordion defaultActiveKey='1'>
<Card>
<Accordion.Toggle as={Card.Header} eventKey='0' align='center' >
{activity[DB.ACTIVITIES_TITLE]}
</Accordion.Toggle>
<Accordion.Collapse eventKey='0'>
<Card.Body>
<p>Start time: {time.timestampToFormatted(activity[DB.ACTIVITIES_START_TIME])} </p>
<p>End time: {time.timestampToFormatted(activity[DB.ACTIVITIES_END_TIME])} </p>
</Card.Body>
<Accordion.Toggle as={Card.Header} eventKey='0' align='center' >
{activity[DB.ACTIVITIES_TITLE]}
</Accordion.Toggle>
<Accordion.Collapse eventKey='0' className={'view-activity' + (this.state.editing? ' edit': '')}>
{ this.displayCard() }
</Accordion.Collapse>
</Card>
</Accordion>
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/components/ViewActivities/activityfns.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,19 @@ export function compareActivities(a, b) {
}
return -1;
}


/**
* Get the field of field name `fieldName` from `activity` or the default value.
*
* @param {Object} activity
* @param {string} fieldName
* @param defaultValue
* @returns `activity[fieldName]` if possible, else `defaultValue`.
*/
export function getField(activity, fieldName, defaultValue) {
if (activity[fieldName] === null || activity[fieldName] === undefined) {
return defaultValue;
}
return activity[fieldName];
}
6 changes: 6 additions & 0 deletions frontend/src/components/ViewActivities/activityfns.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,9 @@ describe('sortByDate tests', () => {
expect(activityFns.sortByDate(tripActivities)).toEqual(expected);
})
})

test('getField', () => {
const activity = {field1: "yes"};
expect(activityFns.getField(activity, "field1", "nooo")).toBe("yes");
expect(activityFns.getField(activity, "field2", 4)).toBe(4);
})
44 changes: 21 additions & 23 deletions frontend/src/components/ViewActivities/activitylist.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,29 @@ const db = app.firestore();
* @param {string} tripId The trip ID.
*/
export async function getActivityList(tripId) {
return new Promise(function(resolve, reject) {
let tripActivities = [];

db.collection(DB.COLLECTION_TRIPS).doc(tripId)
.collection(DB.COLLECTION_ACTIVITIES).get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
let data = doc.data();
data['id'] = doc.id;

// TODO: if start date != end date, split into 2 days. (#37)
let tripActivities = [];

return db.collection(DB.COLLECTION_TRIPS).doc(tripId)
.collection(DB.COLLECTION_ACTIVITIES).get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
let data = doc.data();
data['id'] = doc.id;

// TODO: if start date != end date, split into 2 days. (#37)

// Eliminate nanoseconds, convert to milliseconds.
data[DB.ACTIVITIES_START_TIME] =
data[DB.ACTIVITIES_START_TIME]['seconds'] * 1000;
data[DB.ACTIVITIES_END_TIME] =
data[DB.ACTIVITIES_END_TIME]['seconds'] * 1000;
// Eliminate nanoseconds, convert to milliseconds.
data[DB.ACTIVITIES_START_TIME] =
data[DB.ACTIVITIES_START_TIME]['seconds'] * 1000;
data[DB.ACTIVITIES_END_TIME] =
data[DB.ACTIVITIES_END_TIME]['seconds'] * 1000;

tripActivities.push(data);
})
}).catch(error => {
console.log("It seems that an error has occured.");
tripActivities = null;
}).then( () => resolve(tripActivities) );
})
tripActivities.push(data);
})
}).catch(error => {
console.log("It seems that an error has occured.");
tripActivities = null;
}).then( () => {return tripActivities} );
}

/**
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/styles/activities.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@
margin: 0.5em auto;
max-width: 50pc;
}

/* TODO: auto height, transition. (#49)*/
.view-activity.edit {
height: 20em;
}
.view-activity {
overflow: scroll;
height: 7.5em;
transition: height 0.25s linear;
}

.activity-editor {
padding: 1em 1em 3em 1em;
}

0 comments on commit 7c4ba9d

Please sign in to comment.