Skip to content

Commit a4949c3

Browse files
mattwr18abdellaniaonomike
authored andcommitted
create events functionality (AgileVentures#145)
- CreateEventPage to component as it is only presenting info - EventForm to container as it is changing state - create helper for timezones Co-authored-by: Abdellani <abdellani@gmail.com> Co-authored-by: Mike Aono <aonomike@gmail.com>
1 parent dc5ff14 commit a4949c3

33 files changed

+1066
-47
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ cypress/screenshots
88
.env
99
.vscode/
1010
yarn-error.log
11+
.tool-versions

cypress/fixtures/loggedInUser.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"data": {
3+
"id": 1,
4+
"email": "mattwr18@gmail.com",
5+
"created_at": "2015-01-26T23:19:00.575Z",
6+
"updated_at": "2016-08-22T09:23:23.947Z",
7+
"first_name": "Matt",
8+
"last_name": "Tester",
9+
"display_email": null,
10+
"slug": "matt-tester",
11+
"youtube_id": null,
12+
"display_profile": true,
13+
"country_name": "Brazil",
14+
"city": "Florianopolis",
15+
"region": "Santa Catarina",
16+
"youtube_user_name": null,
17+
"github_profile_url": null,
18+
"display_hire_me": null,
19+
"receive_mailings": true,
20+
"timezone_offset": -18000,
21+
"country_code": "BR",
22+
"status_count": 0,
23+
"deleted_at": null,
24+
"event_participation_count": 0,
25+
"can_see_dashboard": false,
26+
"skill_list": [],
27+
"title_list": [
28+
"Mentor"
29+
]
30+
}
31+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"event": {
3+
"id": 1,
4+
"name": "NewEvent",
5+
"category": "PairProgramming",
6+
"description": "",
7+
"repeats": "never",
8+
"repeats_every_n_weeks": null,
9+
"repeats_weekly_each_days_of_the_week_mask": 0,
10+
"repeat_ends": false,
11+
"repeat_ends_on": null,
12+
"time_zone": "UTC",
13+
"created_at": "2025-01-05T13:02:16.681Z",
14+
"updated_at": null,
15+
"url": null,
16+
"slug": "newevent",
17+
"start_datetime": "2025-01-05T00:00:00.000Z",
18+
"duration": 30,
19+
"exclusions": [],
20+
"project_id": null,
21+
"creator_id": 3493,
22+
"for": "All",
23+
"modifier_id": null,
24+
"creator_attendance": null
25+
}
26+
}

cypress/integration/common/web_steps.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,62 @@ Then("I should see the event's info", () => {
175175
cy.get('div.embed').should('have.length', 1)
176176
})
177177
})
178+
179+
Given('I am logged in', () => {
180+
cy.fixture('loggedInUser').then(loggedInUser => {
181+
cy.route({
182+
method: 'POST',
183+
url: /\/users\/sign_in/,
184+
response: loggedInUser,
185+
status: 200
186+
}).as('postLogInInfo')
187+
cy.visit('/login')
188+
.get('input[name=email]')
189+
.type('username@user.com')
190+
.get('input[name=password]')
191+
.type('user1234')
192+
.get('button[type=submit]')
193+
.click()
194+
cy.window()
195+
.its('store')
196+
.invoke('dispatch', { type: 'POST_LOGIN_INFO', payload: loggedInUser })
197+
})
198+
cy.wait('@postLogInInfo')
199+
})
200+
201+
Then('I should be able to create a new event quickly', () => {
202+
cy.fixture('newlyCreatedEvent').then(newlyCreatedEvent => {
203+
cy.route({
204+
method: 'POST',
205+
url: /\/events/,
206+
response: newlyCreatedEvent,
207+
status: 200
208+
}).as('newlyCreatedEvent')
209+
cy.visit('/events/new')
210+
.get('h1')
211+
.should('contain', 'Creating a new Event')
212+
.get('input[name=name]')
213+
.type('NewEvent')
214+
.get('button[type=submit]')
215+
.click()
216+
cy.window()
217+
.its('store')
218+
.invoke('dispatch', { type: 'GET_EVENT_INFO', payload: newlyCreatedEvent })
219+
})
220+
cy.wait('@newlyCreatedEvent')
221+
})
222+
223+
Then("I should be on the newly created event's page", () => {
224+
cy.url().should('include', 'events/newevent')
225+
.get('h2')
226+
.should('contain', 'NewEvent')
227+
.get('p')
228+
.should('contain', 'Event type: PairProgramming')
229+
.get('p')
230+
.should('contain', 'Event for: All')
231+
.get('img.ui.circular.image')
232+
.should('have.attr', 'src')
233+
.and('contain', 'https://www.gravatar.com/avatar/ad5b3d2d4c25801fcb632cf8014fb555?s=80&d=retro')
234+
.get('p')
235+
.should('contain', 'created by:')
236+
})
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Feature: Create new event
2+
Background:
3+
Given the server is running
4+
5+
Scenario: Quick create
6+
Given I am logged in
7+
Then I should be able to create a new event quickly
8+
And I should be on the newly created event's page

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"react": "16.8.0",
3636
"react-big-calendar": "^0.20.3",
3737
"react-cookie": "^3.0.8",
38+
"react-datepicker": "^2.1.0",
3839
"react-dom": "16.8.0",
3940
"react-html-parser": "^2.0.2",
4041
"react-loading-overlay": "^1.0.1",
@@ -43,6 +44,7 @@
4344
"react-select": "^2.3.0",
4445
"react-spinners": "^0.5.1",
4546
"react-stripe-checkout": "^2.6.3",
47+
"recompose": "^0.30.0",
4648
"redux": "^4.0.1",
4749
"redux-thunk": "^2.3.0",
4850
"semantic-ui-react": "^0.84.0",

src/actions/createEventAction.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import axios from 'axios'
2+
import { GET_EVENT_INFO, CREATE_EVENT_FAILURE } from '../types'
3+
4+
export let createEvent = props => dispatch => {
5+
const {
6+
headers,
7+
history,
8+
name,
9+
category,
10+
eventFor,
11+
startDate,
12+
startDateFormatted,
13+
startTime,
14+
project,
15+
description,
16+
timezones,
17+
duration,
18+
repeats,
19+
weekdaysLowerCase,
20+
repeatEnds,
21+
endDate
22+
} = props
23+
return axios({
24+
method: 'POST',
25+
url: '/events',
26+
data: {
27+
event: {
28+
name,
29+
category,
30+
for: eventFor,
31+
project_id: project,
32+
description,
33+
duration,
34+
repeats,
35+
start_datetime: startDate,
36+
time_zone: 'UTC',
37+
repeats_weekly_each_days_of_the_week: weekdaysLowerCase,
38+
repeat_ends_string: repeatEnds
39+
},
40+
start_date: startDateFormatted,
41+
next_date: startDateFormatted,
42+
start_time: startTime,
43+
start_time_tz: timezones,
44+
repeat_ends_on: endDate
45+
},
46+
headers: {
47+
Authorization: headers,
48+
Accept: 'application/json'
49+
}
50+
})
51+
.then(response => {
52+
dispatch({ type: GET_EVENT_INFO, payload: response.data })
53+
history.push(`/events/${response.data.event.slug}`)
54+
})
55+
.catch(error => {
56+
dispatch({
57+
type: CREATE_EVENT_FAILURE,
58+
message: error.message
59+
})
60+
})
61+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import axios from 'axios'
2+
import { GET_ACTIVE_PROJECTS, FETCH_PROJECTS_FAILURE } from '../types'
3+
4+
export let fetchActiveProjects = () => dispatch => {
5+
return axios.get('/api/v1/projects/active').then(response => {
6+
dispatch({ type: GET_ACTIVE_PROJECTS, payload: response.data })
7+
}).catch(error => {
8+
dispatch({
9+
type: FETCH_PROJECTS_FAILURE,
10+
message: error.message
11+
})
12+
})
13+
}

src/assets/eventForm.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.event-cancel-button {
2+
margin-bottom: 0.5rem !important;
3+
}
4+
5+
.event-save-button {
6+
margin-bottom: 2rem !important;
7+
}

src/components/App.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import PremiumF2FMembershipPage from '../containers/PremiumF2FMembershipPage'
1818
import GettingStartedPage from '../containers/GettingStartedPage'
1919
import EventsList from '../containers/EventsList'
2020
import EventInfo from '../containers/EventInfo'
21+
import EventForm from '../containers/EventForm'
2122
import { withCookies } from 'react-cookie'
2223

2324
class App extends Component {
@@ -73,6 +74,14 @@ class App extends Component {
7374
<Route path='/premium-mob' component={PremiumMobMembershipPage} />
7475
<Route path='/premium-f2f' component={PremiumF2FMembershipPage} />
7576
<Route exact path='/events' component={EventsList} />
77+
<Route path='/events/new' render={props => {
78+
return (
79+
<EventForm
80+
{...props}
81+
cookies={this.props.cookies}
82+
/>)
83+
}}
84+
/>
7685
<Route path='/events/:slug' component={EventInfo} />
7786
<Route path='/getting-started' component={GettingStartedPage} />
7887
</Switch>

0 commit comments

Comments
 (0)