Last active
June 12, 2019 17:24
-
-
Save DominicTremblay/e9fdd366fbefeaeff379bbcb70ee3286 to your computer and use it in GitHub Desktop.
schoodle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>Results</title> | |
<link rel="stylesheet" href="/vendor/normalize-4.1.1.css" type="text/css" /> | |
<link rel="stylesheet" href="/vendor/border-box.css" type="text/css" /> | |
<link rel="stylesheet" href="/styles/layout.css" type="text/css" /> | |
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> | |
<script type="text/javascript" src="/vendor/jquery-3.0.0.js"></script> | |
<script type="text/javascript" src="/scripts/app.js"></script> | |
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> | |
</head> | |
<body> | |
<header> | |
<div class="nav"> | |
<a href="/"><img | |
src="/schoodlelogo2.png" | |
alt="schoodle" | |
width="230px" | |
height="80px" | |
></a> | |
</div> | |
</header> | |
<section class="block3"> | |
<h1> | |
Event title | |
</h1> | |
<h5> | |
eventDescription | |
</h5> | |
<div id="shareBox"> | |
<h6>Share event with guests: </h6> | |
<textarea name="shareURL" id="myInput">http://localhost:8080/events/<%= eventData.eventUrl%></textarea> | |
<h6>↪️</h6> | |
</div> | |
<div class="container3"> | |
<table class="table table-striped table-bordered table-hover" id=table> | |
<tr class="table-row"> | |
<th><h6>Dates</h6></th> | |
<% for (const timeslotObj of eventData.timeslots) { %> | |
<td><h6><%= timeslotObj.timeslot %></h6></td> | |
<% } %> | |
<td></td> | |
</tr> | |
<% for (const user in eventData.usersVotes) { %> | |
<tr> | |
<td><%= user %></td> | |
<% for (const vote of eventData.usersVotes[user].sort( | |
(a, b) => a.timeslotId - b.timeslotId | |
)) { %> | |
<td><input type='checkbox' name="<%= vote.timeslotId %>" <%= vote.checked ? 'checked' : null %>></td> | |
<% } %> | |
</tr> | |
<% } %> | |
<form action="/events/<%= eventData.eventUrl%>" method="POST"> | |
<tr> | |
<td> | |
<input type='text' class="textAreaTable" name="name" cols="7" rows="2" placeholder="your name"></textarea> | |
<input type='text' class="textAreaTable" name="email" cols="7" rows="2" placeholder="your email"></textarea> | |
</td> | |
<% for (const timeslotObj of eventData.timeslots) { %> | |
<td><input class="form-check-input" name="<%= timeslotObj.timeslotId %>" type="checkbox"</td> | |
<% } %> | |
<td><button type="submit" class="btn-success-btn-lg" value="submit">Save</button></td> | |
</tr> | |
</form> | |
</table> | |
</div> | |
</section> | |
<footer></footer> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
require('dotenv').config(); | |
const PORT = process.env.PORT || 8080; | |
const ENV = process.env.ENV || 'development'; | |
const express = require('express'); | |
const bodyParser = require('body-parser'); | |
const sass = require('node-sass-middleware'); | |
const app = express(); | |
const knexConfig = require('./knexfile'); | |
const knex = require('knex')(knexConfig[ENV]); | |
const morgan = require('morgan'); | |
const knexLogger = require('knex-logger'); | |
// Seperated Routes for each Resource | |
const usersRoutes = require('./routes/users'); | |
// Load the logger first so all (static) HTTP requests are logged to STDOUT | |
// 'dev' = Concise output colored by response status for development use. | |
// The :status token will be colored red for server error codes, yellow for client error codes, cyan for redirection codes, and uncolored for all other codes. | |
app.use(morgan('dev')); | |
// Log knex SQL queries to STDOUT as well | |
app.use(knexLogger(knex)); | |
app.set('view engine', 'ejs'); | |
app.use(bodyParser.urlencoded({ extended: true })); | |
app.use( | |
'/styles', | |
sass({ | |
src: __dirname + '/styles', | |
dest: __dirname + '/public/styles', | |
debug: true, | |
outputStyle: 'compressed', | |
}) | |
); | |
app.use(express.static('public')); | |
// Mount all resource routes | |
app.use('/api/users', usersRoutes(knex)); | |
// app.use("/api/events", usersRoutes(knex)); | |
// app.use("/api/timeslots", usersRoutes(knex)); | |
// app.use("/api/attendees", usersRoutes(knex)); | |
//String randomizing function | |
function generateRandomString() { | |
let randomize = Math.random() | |
.toString(36) | |
.substring(7); | |
return randomize; | |
} | |
const votesByName = (votesArr, timeslotIds) => { | |
const votesObj = {}; | |
for (const voteObj of votesArr) { | |
const key = voteObj.name; | |
votesObj[key] = | |
votesObj[key] || | |
timeslotIds.map(timeslotId => ({ | |
timeslotId, | |
checked: false, | |
})); | |
const timeslot = votesObj[key].find( | |
timeslotObj => voteObj.timeslotId === timeslotObj.timeslotId | |
); | |
timeslot.checked = true; | |
votesObj[key] = [ | |
timeslot, | |
...votesObj[key].filter( | |
timeslotObj => timeslotObj.timeslotId !== timeslot.timeslotId | |
), | |
]; | |
} | |
return votesObj; | |
}; | |
// Home page - redirects (create button) to /events/new | |
app.get('/', (req, res) => { | |
res.render('index'); | |
}); | |
app.get('/events/new', (req, res) => { | |
res.render('events_new'); | |
}); | |
// Save new event and redirect to event poll page | |
app.post('/events/new', (req, res) => { | |
// Add new URL and form entries to "event" DB table & "timeslot" DB table | |
// Redirect to event page "/events/:url" | |
let shortURL = generateRandomString(); | |
//input parameters | |
let name = req.body.name; | |
let email = req.body.email; | |
let event = req.body.event; | |
let description = req.body.description; | |
let timeslot1 = req.body.timeslot1; | |
let timeslot2 = req.body.timeslot2; | |
let timeslot3 = req.body.timeslot3; | |
knex('users') | |
.insert({ name, email }) | |
.returning('id') | |
.then(bunchOfIds => { | |
knex('events') | |
.insert({ | |
title: event, | |
description, | |
url: shortURL, | |
user_id: bunchOfIds[0], | |
}) | |
.returning('id') | |
.then(eventIds => { | |
knex('timeslots') | |
.insert({ timeslot: timeslot1, event_id: eventIds[0] }) | |
.then(result => console.log('ok')); | |
knex('timeslots') | |
.insert({ timeslot: timeslot2, event_id: eventIds[0] }) | |
.then(result => console.log('ok')); | |
knex('timeslots') | |
.insert({ timeslot: timeslot3, event_id: eventIds[0] }) | |
.then(result => | |
res.redirect(`http://localhost:8080/events/${shortURL}`) | |
); | |
}); | |
}); | |
}); | |
// Event form - enter event info & timeslots | |
app.get('/events/:id', (req, res) => { | |
let templateVars; | |
const { id: eventUrl } = req.params; | |
knex | |
.select('timeslots.id as timeslotId', 'timeslots.timeslot') | |
.from('events') | |
.where('url', eventUrl) | |
.innerJoin('timeslots', 'events.id', 'timeslots.event_id') | |
.then(timeslots => { | |
const eventData = {}; | |
eventData.eventUrl = eventUrl; | |
eventData.timeslots = timeslots; | |
// getting only the ids in an array | |
const timeslotIds = eventData.timeslots.map( | |
timeslotObj => timeslotObj.timeslotId | |
); | |
// console.log('timeslotIds', timeslotIds); | |
knex | |
.select( | |
'users.name', | |
'users.id as userId', | |
'votes.timeslot_id as timeslotId' | |
) | |
.from('votes') | |
.innerJoin('users', 'votes.user_id', 'users.id') | |
.whereIn('timeslot_id', timeslotIds) | |
.then(votes => { | |
// console.log('Votes', votes); | |
const usersVotes = votesByName(votes, timeslotIds); | |
// console.log('usersVotes:', usersVotes); | |
eventData.usersVotes = usersVotes; | |
// console.log('Event Data', eventData.usersVotes); | |
res.render('events_results', { eventData }); | |
// res.json(eventData); | |
}); | |
}); | |
// knex('votes') | |
// .select( | |
// 'votes.id as voteid', | |
// 'name', | |
// 'email', | |
// 'timeslot', | |
// 'title', | |
// 'description' | |
// ) | |
// .innerJoin('users', 'votes.user_id', 'users.id') | |
// .innerJoin('timeslots', 'votes.timeslot_id', 'timeslots.id') | |
// .innerJoin('events', 'timeslots.event_id', 'events.id') | |
// // .orderBy('timeslots.id') | |
// .orderBy('name') | |
// .then(result => { | |
// console.log(result); | |
// const templateVars = { | |
// shareURL: req.params.id, | |
// eventTitle: result[0].title, | |
// eventDescription: result[0].description, | |
// result: result, | |
// }; | |
// res.render('events_results', templateVars); | |
// }); | |
}); | |
app.get('/u/:shortURL', (req, res) => { | |
res.render('events_results'); | |
}); | |
// Save button actions - allows user to save new vote | |
app.post('/events/:shareURL', (req, res) => { | |
// Save new vote entry to: (a) Users table, (b) Votes table | |
// Redirect to same page (reload) | |
// let shareURL = req.params.shareURL; | |
console.log('Adding a new vote'); | |
console.log(req.body); | |
let shareURL = req.params.shareURL; | |
let name = req.body.name; | |
let email = req.body.email; | |
// extracting timeslot Ids from req.body into an array | |
const timeslotIds = Object.keys(req.body).filter( | |
key => req.body[key] === 'on' | |
); | |
console.log('timeslotIds', timeslotIds); | |
knex('users') | |
.insert({ name, email }) | |
.returning('id') | |
.then(([userId]) => { | |
// creating the array of votes | |
const votesArr = timeslotIds.map(timeslotId => ({ | |
user_id: userId, | |
timeslot_id: Number(timeslotId), | |
})); | |
console.log('votesArr', votesArr); | |
knex('votes') | |
.insert(votesArr) | |
.then(result => | |
res.redirect(`http://localhost:8080/events/${shareURL}`) | |
); | |
}); | |
// knex("events") | |
// .insert({ title: event, description, url: shortURL, user_id: id }) | |
// .then(result => console.log(result)); | |
// knex("users") | |
// .insert({ name, email }) | |
// .returning("id") | |
// .then((bunchOfIds) => { | |
// knex("votes") | |
// .insert({ | |
// user_id: bunchOfIds[0], | |
// timeslot_id: time | |
// // (knex('events') | |
// // .select('id') | |
// // .innerJoin('timeslots', 'id', 'event_id') | |
// // .where('url', 'shareURL')) | |
// }) | |
// .then(result => console.log(result)); | |
// }) | |
}); | |
// Edit button actions - allows user to edit existing vote | |
// app.post("/users/:userid/events/:url", (req, res) => { | |
// // Update votes table (in DB) with new availabilities | |
// // Redirect to same page (reload) | |
// }); | |
app.listen(PORT, () => { | |
console.log('Example app listening on port ' + PORT); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment