From e66ddbdf2aec545dda940faca0059784822d6b91 Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Wed, 26 Feb 2014 03:47:39 +0000 Subject: [PATCH] Finished version 1.0. * Switched from a server-side rendering model to client-side. Now, the editing view is the same view as the print view, using CSS media qualifiers to switch between the eiting view on screen and the print view. This makes all the server-side code unnecessary. * Added logic to rewrite the service headers when the user changes the date so that they include the correct dates and grey out fifth Sundays and Wednesdays as appropriate. --- .../NurseryScheduleServlet.groovy | 132 ------------- src/www/css/schedule-maker.scss | 160 +++++++++------ src/www/index.html | 106 +++++----- src/www/js/schedule-maker.js | 91 ++++++++- src/www/schedule-maker.html | 182 ------------------ src/www/schedule.template | 57 ------ 6 files changed, 239 insertions(+), 489 deletions(-) delete mode 100644 src/java/com/jdbernard/nurseryschedule/NurseryScheduleServlet.groovy delete mode 100644 src/www/schedule-maker.html delete mode 100644 src/www/schedule.template diff --git a/src/java/com/jdbernard/nurseryschedule/NurseryScheduleServlet.groovy b/src/java/com/jdbernard/nurseryschedule/NurseryScheduleServlet.groovy deleted file mode 100644 index 9f14f3a..0000000 --- a/src/java/com/jdbernard/nurseryschedule/NurseryScheduleServlet.groovy +++ /dev/null @@ -1,132 +0,0 @@ -package com.jdbernard.nurseryschedule - -import com.jdbernard.util.SmartConfig -import groovy.json.JsonBuilder -import groovy.json.JsonException -import groovy.json.JsonSlurper -import groovy.text.SimpleTemplateEngine -import java.util.Calendar -import java.util.regex.Matcher -import javax.servlet.ServletConfig -import javax.servlet.ServletException -import javax.servlet.http.HttpServlet -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse -import javax.servlet.http.HttpSession - -import static java.util.Calendar.* -import static javax.servlet.http.HttpServletResponse.* - -public class NurseryScheduleServlet extends HttpServlet { - - /// This service currently only supports one user. - private String username - private String password - private String outputDirectory - - private static SimpleDateFormat dataDateFormat = - new SimpleDateFormat("yyyy-MM-dd") - private static SimpleDateFormat displayDateFormat = - new SimpleDateFormat("MMM dd") - - void init(ServletConfig config) { - this.username = config.getInitParameter("username") - this.password = config.getInitParameter("password") - this.outputDirectory = config.getInitParameter("outputDirectory") } - - void doPost(HttpServletRequest request, HttpServletResponse response) { - - HttpSession session = request.getSession(true); - - /// If the user is posting to `/login` then let's try to authenticate - /// them. We don't care about the state of the existing session. - if (request.servletPath == '/login') { - - /// Parse the username/password from the request. - def requestBody - try { requestBody = new JsonSlurper().parse(request.reader) } - catch (JsonException jsone) { - response.status = SC_BAD_REQUEST - return } - - /// If no username or password are configured we cannot - /// authenticate the user. - if (!password || !username) { - response.status = SC_UNAUTHORIZED - return } - - /// If the username or password do not match, deny the request. - if (username != requestBody.username || - password != requestBody.password) { - response.status = SC_UNAUTHORIZED - return } - - response.status = SC_OK - session.setAttribute('authenticated', 'true') - session.setAttribute('username', requestBody.username) - writeJSON([status: "ok"], response) - return } - - /// The other endpoints require the user to be authenticated. - if (!((boolean)session.getAttribute('authenticated'))) { - response.status = SC_UNAUTHORIZED - return } - - switch (request.servletPath) { - case ~ '/make-schedule': - - /// Parse the request body. - def data - try { data = new JsonSlurper().parse(request.reader) } - catch (JsonException jsone) { - response.status = SC_BAD_REQUEST - return } - - /// Calculate dates and modify the schedule data to include - /// them. - def cal = Calendar.getInstance() - cal.time = dataDateFormat.parse(data.date) - int month = cal.get(MONTH) - cal.set(HOUR_OF_DAY, 0) - cal.set(MINUTE, 0) - cal.set(SECOND, 0) - cal.set(MILLISECOND, 0) - - ['first', 'second', 'third', 'fourth', 'fifth'].eachWithIndex - { dayNum, idx -> - /// Set the sunday - cal.set(DAY_OF_WEEK, SUNDAY) - cal.set(DAY_OF_WEEK_IN_MONTH, idx + 1) - if (cal.get(MONTH) == month) - data.sundays[dayNum].date = displayDateFormat.format(cal.time) - - /// Set the wednesday. Note that we have to reformat the - /// input data from {"first": ["PersonA", "PersonB"]} to - /// {"date": "Oct. 6", "volunteers": ["PersonA", PersonB"]} - def volunteers = data.wednesdays[dayNum] - data.wednesdays[dayNum] = [:] - data.wednesdays[dayNum].volunteers = volunteers - - if (cal.get(MONTH) == month) - data.wednesdays[dayNum].date = - displayDateFormat.format(cal.time) } - - cal.set(DAY_OF_WEEK_IN_MONTH, 2) - data.sundays['second'].date = displayDateFormat.format(cal.time) - - /// Build the resulting page. - def engine = new SimpleTemplateEngine() - def scheduleTemplate = engine.createTemplate( - this.getClass().getResource('schedule.template')) - def output = scheduleTemplate.make(data) - - /// Write the results to file. - new File(outputDirectory, data.date + ".html").text = output - response.status = SC_OK - - default: - response.status = SC_NOT_FOUND - return - } - } -} diff --git a/src/www/css/schedule-maker.scss b/src/www/css/schedule-maker.scss index 186f854..7e3a324 100644 --- a/src/www/css/schedule-maker.scss +++ b/src/www/css/schedule-maker.scss @@ -16,65 +16,123 @@ article,aside,details,figcaption,figure, footer,header,hgroup,menu,nav,section { display:block; } +// Fonts +@import url(http://fonts.googleapis.com/css?family=Abel); + +html { font-size: 90%; } + body { - line-height: normal; + font-family: "Abel"; + line-height: 1.1em; margin: 2rem; } -.header { position: relative; } +.inactive { opacity: 0.5; } -.load-dialog { - background: rgba(0, 0, 0, 0.5); - bottom: 0; - display: none; - position: absolute; - top: 0; - left: 0; - right: 0; - z-index: 10; - - div { - text-align: center; - margin-top: 4rem; - - span { - background: whitesmoke; - border-radius: 3px; - padding: 1em; - - #fileLoad { width: 30rem; } } } } - -.tools { - - position: absolute; - top: 0; - right: 0; - - input[type="date"] { - border: solid thin gray; - border-radius: 3px; } - - ul { - list-style: none; +@media screen { + body { line-height: normal; } - li { - padding-right: 0.5rem; - display: inline-block; } } - - .publish { text-decoration: line-through; } } + .print-only { display: none; } -.sundays { border-right: solid thin lightgray; } -.wednesdays { padding-left: 2rem; } + .load-dialog { + background: rgba(0, 0, 0, 0.5); + bottom: 0; + display: none; + position: absolute; + top: 0; + left: 0; + right: 0; + z-index: 10; + + div { + text-align: center; + margin-top: 4rem; + + span { + background: whitesmoke; + border-radius: 3px; + padding: 1em; + + #fileLoad { width: 30rem; } } } } + + + .sundays { + border-right: solid thin lightgray; + .remove { left: 7.5rem; } + .clone { left: 6.5rem; } } + + .wednesdays { + padding-left: 2rem; + .remove { left: 11.5rem; } + .clone { left: 10.5rem; } } + + .sundays, .wednesdays { width: 49%; } + + .teacher-needed { + color: #A00; + font-style: italic; } + + header { position: relative; } + + .tools { + + position: absolute; + top: 0; + right: 0; + + input[type="date"] { + border: solid thin gray; + border-radius: 3px; } + + ul { + list-style: none; + + li { + padding-right: 0.5rem; + display: inline-block; } } + + .publish { text-decoration: line-through; } } + +} + +@media print { + body { + line-height: 1.1em; } + + .load-dialog, .tools, .teacher-needed, .screen-only { display: none; } + + .sundays, .wednesdays { width: 100%; } + + .sundays { border-bottom: solid thin lightgray; } +} + +h5 { + font-size: small; + font-weight: normal; + text-decoration: underline; } + +.first, .second, .third, .fourth, .fifth { + display: inline-block; + margin-bottom: 2rem; + vertical-align: top; + width: 19em; } + +.date { } + +ul { list-style: none; } + +.toddlers, .infants { + display: inline-block; + vertical-align: top; + width: 9rem; } + +div.am, div.pm, .wednesdays ul { + margin-top: 0.5rem; } .sundays, .wednesdays { display: inline-block; line-height: 1.1rem; margin-top: 2rem; vertical-align: top; - width: 49%; - - .teacher-needed { - color: #A00; - font-style: italic; } li { position: relative; @@ -98,11 +156,3 @@ body { &.editing:hover { .clone, .remove { display: none; } } } } - -.sundays { - .remove { left: 7.5rem; } - .clone { left: 6.5rem; } } - -.wednesdays { - .remove { left: 11.5rem; } - .clone { left: 10.5rem; } } diff --git a/src/www/index.html b/src/www/index.html index b6392e4..9574ad9 100644 --- a/src/www/index.html +++ b/src/www/index.html @@ -1,122 +1,116 @@ - + + + + + + + + + + + + +
+

Nursery Schedule Maker, +

+
+
+
-

First Sunday, Oct. 6th

+

First Sunday

Toddlers
    -
  • Sara Bernard
  • -
  • Priscilla Reid
  • -
  • Becca Torres
Infants
    -
  • Latonya Kirton
  • -
  • Susan Vacca
  • -
  • Brandie Kristoff
Evening Service
    -
  • Susan Miller
  • -
  • TBD
-

Second Sunday, Oct. 13th

+

Second Sunday

Toddlers
    -
  • Sara Bernard
  • -
  • Priscilla Reid
  • -
  • Rebecca Dombroski
Infants
    -
  • Latonya Kirton
  • -
  • Susan Vacca
  • -
  • Mila Hill
Evening Service
    -
  • Zoe Torres
  • -
  • Hannah Torres
-

Third Sunday, Oct. 20th

+

Third Sunday

Toddlers
    -
  • Sara Bernard
  • -
  • Priscilla Reid
  • -
  • Della Borrego
Infants
    -
  • Latonya Kirton
  • -
  • Susan Vacca
  • -
  • Deborah McDonald
Evening Service
    -
  • TBD
  • -
  • Alayna Robert
-

Fourth Sunday, Oct. 27th

+

Fourth Sunday

Toddlers
    -
  • Sara Bernard
  • -
  • Priscilla Reid
  • -
  • TBD
Infants
    -
  • Latonya Kirton
  • -
  • Susan Vacca
  • -
  • Crystal Johnson
Evening Service
    -
  • Deidra Dawson
  • -
  • Shekinah Dawson
@@ -127,71 +121,63 @@
Toddlers
    -
  • Sara Bernard
  • -
  • Priscilla Reid
  • -
  • Julie Froese
Infants
    -
  • Latonya Kirton
  • -
  • Susan Vacca
  • -
  • TBD
Evening Service
    -
  • TBD
  • -
  • TBD
+
-

First Wednesday, Oct. 2nd

+

First Wednesday

    -
  • Courtney or Bryan Bootka
  • -
  • Gabby Galvez
-

Second Wednesday, Oct. 9th

+

Second Wednesday

    -
  • Reeta or Lionel Aguilar
  • -
  • Stephanie Langley
-

Third Wednesday, Oct. 16th

+

Third Wednesday

    -
  • Christina Grooms
  • -
  • Lanell Hanson
-

Fourth Wednesday, Oct. 23rd

+

Fourth Wednesday

    -
  • Cassie Hernandez
  • -
  • Regena Dumas
-

Fifth Wednesday, Oct. 30th

+

Fifth Wednesday

    -
  • Regina Noble
  • -
  • TBD
+ +
+
+ Load It! +
+
+ diff --git a/src/www/js/schedule-maker.js b/src/www/js/schedule-maker.js index be356e9..91e3426 100644 --- a/src/www/js/schedule-maker.js +++ b/src/www/js/schedule-maker.js @@ -8,6 +8,15 @@ SM.minWedTeachers = 2; SM.views = []; + SM.date = new Date(); + + SM.monthNames = ["January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"]; + + SM.monthAbbr = ["Jan.", "Feb.", "Mar.", "Apr.", "May", "June", "July", + "Aug.", "Sep.", "Oct.", "Nov.", "Dec."]; + + SM.nameForNumber = ["first", "second", "third", "fourth", "fifth"] SM.ServiceView = function(element) { @@ -213,6 +222,7 @@ // Restore the date. $('input[type=date]').val(data.date); + SM.updateDate(); // Restore Sunday services for(var day in data.sundays) { @@ -234,12 +244,85 @@ var liEl = view.newName({target: $ulEl[0]}); $(liEl).find('span.name').text(personName); }); view.updatePlaceholders({target: $ulEl[0]}); } } - + fileReader.readAsText(fileName, "UTF-8"); }; - SM.publicShedule = function() { - // TODO + SM.updateDate = function() { + var schedDate = new Date($('.schedule-date').val() + ":"); + + if (schedDate.getMonth() == SM.date.getMonth() && + schedDate.getYear() == SM.date.getYear()) { return } + + SM.date = schedDate; + $('.month-name').text( + SM.monthNames[SM.date.getMonth()] + " " + + (SM.date.getYear() + 1900)); + + // Find the Sundays. + var tempDate = new Date(SM.date) // First find the first Sunday. + tempDate.setDate(1); // Start at the first day of the month + if (tempDate.getDay() != 0) { // If it is not a sunday + // then figure out how many days until the next Sunday (based on + // what day it is), add one (because setDate is 1-indexed) and add + // that so that we have the first Sunday of the month. + tempDate.setDate((7 - tempDate.getDay()) + 1) } + + // Now iterate through the sundays in this month and update the view. + for (var i = 0; i < 5; i++) { + var $h3 = $(".sundays ." + SM.nameForNumber[i] + " h3"); + var text = SM.nameForNumber[i]; + text = text[0].toUpperCase() + text.slice(1) + " Sunday"; + + if (tempDate.getMonth() == SM.date.getMonth()) { + text += ', ' + SM.monthAbbr[tempDate.getMonth()] + + " " + tempDate.getDate(); + if (text[text.length - 1] == '1' + && text[text.length - 2] != '1') text += "st"; + else if (text[text.length - 1] == '2') text += "nd"; + else if (text[text.length - 1] == '3') text += "rd"; + else text += "th"; + $h3.closest('div').removeClass('inactive'); } + + else { + text = "No " + text; + $h3.closest('div').addClass('inactive'); } + + $h3.text(text); + tempDate.setDate(tempDate.getDate() + 7); } + + // Find the Wednesdays. + var tempDate = new Date(SM.date) // First find the first Wednesday. + tempDate.setDate(1); // Start at the first day of the month + if (tempDate.getDay() != 3) { // figure out how many days until + // the next Sunday (based on what day it is), add one (because + // setDate is 1-indexed), add 3 to get to the next wednesday and + // add that so that we have the first Wednesday of the month. + tempDate.setDate((((7 - tempDate.getDay()) + 1) % 7) + 3) } + + // Now iterate through the wednesdays in this month and update the view. + for (var i = 0; i < 5; i++) { + var $h3 = $(".wednesdays ." + SM.nameForNumber[i] + " h3"); + var text = SM.nameForNumber[i]; + text = text[0].toUpperCase() + text.slice(1) + " Wednesday"; + + if (tempDate.getMonth() == SM.date.getMonth()) { + text += ', ' + SM.monthAbbr[tempDate.getMonth()] + + " " + tempDate.getDate(); + if (text[text.length - 1] == '1' + && text[text.length - 2] != '1') text += "st"; + else if (text[text.length - 1] == '2') text += "nd"; + else if (text[text.length - 1] == '3') text += "rd"; + else text += "th"; + $h3.closest('div').removeClass('inactive'); } + + else { + text = "No " + text; + $h3.closest('div').addClass('inactive'); } + + $h3.text(text); + tempDate.setDate(tempDate.getDate() + 7); } + }; SM.init = function() { @@ -253,6 +336,8 @@ $('.publish').on('click', SM.publishSchedule); $('.load-dialog').on('click', SM.hideLoadDialog); $('.load-dialog a').on('click', SM.loadSchedule); + $('.schedule-date').on('change', SM.updateDate); + $('.schedule-date').on('keyup', SM.updateDate); }; }).call(this); diff --git a/src/www/schedule-maker.html b/src/www/schedule-maker.html deleted file mode 100644 index e8f3d7b..0000000 --- a/src/www/schedule-maker.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - - - - - - - - - - -
-

Nursery Schedule Maker

-
-
- -
-
-

First Sunday

-
-
-
Toddlers
-
    -
-
-
-
Infants
-
    -
-
-
-
-
Evening Service
-
    -
-
-
- -
-

Second Sunday

-
-
-
Toddlers
-
    -
-
-
-
Infants
-
    -
-
-
-
-
Evening Service
-
    -
-
-
- -
-

Third Sunday

-
-
-
Toddlers
-
    -
-
-
-
Infants
-
    -
-
-
-
-
Evening Service
-
    -
-
-
- -
-

Fourth Sunday

-
-
-
Toddlers
-
    -
-
-
-
Infants
-
    -
-
-
-
-
Evening Service
-
    -
-
-
- -
-

Fifth Sunday

-
-
-
Toddlers
-
    -
-
-
-
Infants
-
    -
-
-
-
-
Evening Service
-
    -
-
-
- -
- -
-
-

First Wednesday

-
    -
-
- -
-

Second Wednesday

-
    -
-
- -
-

Third Wednesday

-
    -
-
- -
-

Fourth Wednesday

-
    -
-
- -
-

Fifth Wednesday

-
    -
-
- -
- -
-
- Load It! -
-
- - - diff --git a/src/www/schedule.template b/src/www/schedule.template deleted file mode 100644 index 36b6b54..0000000 --- a/src/www/schedule.template +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - -
<% - ['first', 'second', 'third', 'fourth', 'fifth'].each { - dayNumber -> - - if (sundays[dayNumber].date) { %> - -
-

${dayNumber.capitalize()} Sunday, ${sundays[dayNumber].date}

-
-
-
Toddlers
-
    <% - sundays[dayNumber].toddlers.each { volunteer -> %> -
  • ${volunteer}
  • <% } %> -
-
-
-
Infants
-
    <% - sundays[dayNumber].infants.each { volunteer -> %> -
  • ${volunteer}
  • <% } %> -
-
-
-
-
Evening Service
-
    <% - sundays[dayNumber].pm.each { volunteer -> %> -
  • ${volunteer}
  • <% } %> -
-
-
<% }} %> - -
- -
<% - ['first', 'second', 'third', 'fourth', 'fifth'].each { - dayNumber -> - - if (wednesdays[dayNumber].date) { %> -
-

${dayNumber.capitalize()} Wednesday, ${wednesdays[dayNumber].date}

-
    <% wednesdays[dayNumber].volunteers.each { - volunteer -> %> -
  • ${volunteer}
  • <% } %> -
-
<% }} %> - -
- -