diff --git a/app/routes.js b/app/routes.js index 58ddb33..ca9f9aa 100644 --- a/app/routes.js +++ b/app/routes.js @@ -3,7 +3,7 @@ var fs = require('fs'); var path = require('path'); var adminPath; -var PRODUCT_LIST_PATH = "VAP_Availability_List_Oct2016.pdf"; +var PRODUCT_LIST_PATH = "VAP_Availability_List_Nov2016.pdf"; //Notes: //Use res.send or res.sendFile for static resources (like images or html) @@ -222,9 +222,9 @@ module.exports = function(app, rootPath, passport, smtpTransport, sequelize) { //TODO: Can we just use extend? Object.keys(req.body).forEach(function(key) {params[key] = req.body[key]}); - // if(params.msgpack) { - // params = msgpack.decode(params.msgpack); - // } + //The client must wrapper any JSON it wants to send into another JSON object whose sole attribute is 'request' and whose value is the actual parameter JSON stringified. + //This is because for some unknown reason, jquery.ajax (or derivative methods) does not stringify the JSON correctly (converts bool, int, etc, into strings), and the server cannot convert the strings back into native types. + params = params.request ? JSON.parse(params.request) : params; if(!model) { res.status(400).end(); @@ -325,10 +325,11 @@ module.exports = function(app, rootPath, passport, smtpTransport, sequelize) { break; } case 'restore': { + params.paranoid = false; model.find(params).then(function(value) { if(value) { - value.deletedAt = null; - value.save().then(function() { + value.setDataValue('deletedAt', null); + value.save({paranoid: false}).then(function() { res.status(200).end(); }).catch(function(err) { console.log(err); @@ -378,7 +379,10 @@ module.exports = function(app, rootPath, passport, smtpTransport, sequelize) { res.status(400).end(); } } - catch(e) {console.log(e); res.status(400).end();} + catch(e) { + console.log(e); + res.status(400).end(); + } }); /* diff --git a/downloaded tools/bootstrap-3.3.7-dist.zip b/downloaded tools/bootstrap-3.3.7-dist.zip new file mode 100644 index 0000000..6fbb95e Binary files /dev/null and b/downloaded tools/bootstrap-3.3.7-dist.zip differ diff --git a/migrations/20160602030149-Item.js b/migrations/20160602030149-Item.js index d5fbd95..dbcb38b 100644 --- a/migrations/20160602030149-Item.js +++ b/migrations/20160602030149-Item.js @@ -19,6 +19,10 @@ module.exports = { type: DataTypes.JSON, allowNull: false }, + aliases: { + type: DataTypes.JSON, + allowNull: true + }, defaultPrice: { type: DataTypes.DECIMAL(9,2), allowNull: false diff --git a/migrations/20160602030150-Sale.js b/migrations/20160602030150-Sale.js index 944b0c5..227c0ef 100644 --- a/migrations/20160602030150-Sale.js +++ b/migrations/20160602030150-Sale.js @@ -15,7 +15,7 @@ module.exports = { type: DataTypes.DATEONLY, allowNull: false }, - quantity: { + amount: { type: DataTypes.DECIMAL(13,2), allowNull: false }, @@ -58,15 +58,11 @@ module.exports = { updatedAt: { type: DataTypes.DATE, allowNull: false - }, - deletedAt: { - type: DataTypes.DATE, - allowNull: true } }, { charset: 'utf8', timestamps: true, - paranoid: true + paranoid: false }); }, diff --git a/models/item.js b/models/item.js index 81779d0..4019eb1 100644 --- a/models/item.js +++ b/models/item.js @@ -18,6 +18,10 @@ module.exports = function(sequelize, DataTypes) { type: DataTypes.JSON, allowNull: false }, + aliases: { //An array of alias names (strings) for this item. Used only to find the item, and not checked to ensure that names are unique. + type: DataTypes.JSON, + allowNull: true + }, defaultPrice: { type: DataTypes.DECIMAL(9,2), allowNull: false diff --git a/models/sale.js b/models/sale.js index cc67bd3..8dff827 100644 --- a/models/sale.js +++ b/models/sale.js @@ -13,7 +13,7 @@ module.exports = function(sequelize, DataTypes) { type: DataTypes.DATEONLY, allowNull: false }, - quantity: { + amount: { type: DataTypes.DECIMAL(13,2), allowNull: false }, diff --git a/package.json b/package.json index 26db660..e05ad6e 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,12 @@ "1. start": "node server.js", "3. update-db": "sequelize db:migrate", "4. create-db-migration": "sequelize migration:create", - "2. install": "npm install" + "2. install": "npm install", + "5. prune": "npm prune", + "start": "node server.js", + "migrateDB": "sequelize db:migrate", + "dropDB": "sudo -u postgres dropdb PetitTeton", + "createDB": "sudo -u postgres createdb PetitTeton" }, "dependencies": { "bcrypt-nodejs": "^0.0.3", diff --git a/public/VAP_Availability_List_Nov2016.pdf b/public/VAP_Availability_List_Nov2016.pdf new file mode 100644 index 0000000..9bd68bc Binary files /dev/null and b/public/VAP_Availability_List_Nov2016.pdf differ diff --git a/public/admin/Venues.html b/public/admin/Venues.html index 3ed6c07..51cf856 100644 --- a/public/admin/Venues.html +++ b/public/admin/Venues.html @@ -4,7 +4,7 @@

Manage Venues

-
+
New Edit @@ -75,46 +75,57 @@ var $btnDelete = $page.find("#deleteButton"); var $btnRestore = $page.find("#restoreButton"); - $btnEdit.hide(); - $btnDelete.hide(); - $btnRestore.hide(); + $btnEdit.disable(true); + $btnDelete.disable(true); + $btnRestore.disable(true); + + var selectionChanged = function($tr, model) { + if($tr && model) { + $btnEdit.disable(false); + + //If the object was deleted (hidden), then allow it to be restored, otherwise allow the model to be deleted. + if(model.deletedAt) { + $btnRestore.disable(false); + $btnDelete.disable(true); + } + else { + $btnRestore.disable(true); + $btnDelete.disable(false); + } + } + else { + $btnEdit.disable(true); + $btnDelete.disable(true); + $btnRestore.disable(true); + } + }; var dataTable = new LinkedTable($page.find('#dataTable'), { url: "data/Venue/readAll", attr: "data-key-name", selection: "row", - selectionChanged: function($tr, model) { - if($tr && model) { - $btnEdit.show(); - - //If the object was deleted (hidden), then allow it to be restored, otherwise allow the model to be deleted. - if(model.deletedAt) { - $btnRestore.show(); - $btnDelete.hide(); - } - else { - $btnRestore.hide(); - $btnDelete.show(); - } - } - else { - $btnEdit.hide(); - $btnDelete.hide(); - $btnRestore.hide(); - } - }, + selectionChanged: selectionChanged, parameters: function() { - return {msgpack: msgpack.encode({paranoid: !$page.find('#includeDeletedToggle').is(":checked")})}; + return {paranoid: !$page.find('#includeDeletedToggle').is(":checked")}; }, postAddRowHandler: function($row, dataObject) { if(dataObject.deletedAt) { $("td:first", $row).prepend(""); } + }, + postUpdateRowHandler: function($row, dataObject) { + if(dataObject.deletedAt) { + $("td:first", $row).prepend(""); + } + + if($row.is(dataTable.getSelectedRow())) { + selectionChanged($row, dataObject); + } } }); //Call the refresh user table function once initially. - dataTable.refresh(); + dataTable.build(); //Refresh the data table if the user toggles the button to show/hide deleted elements. $page.find('#includeDeletedToggle').on('click', function(event) { @@ -126,7 +137,7 @@ var model = dataTable.getSelectedRow() ? dataTable.getSelectedRow().data('model') : undefined; if(model && model.deletedAt) { - $.post("data/Venue/restore", {id: model.id}, "json").done(function(data) { + $.post("data/Venue/restore", {request: JSON.stringify({where: {id: model.id}})}, "json").done(function(data) { dataTable.refresh(); }).fail(function(data) { alert("Failed to restore the desired object due to a server side error."); @@ -175,21 +186,14 @@ var createFunction = function(close) { $editorForm.data('bs.validator').validate(function(isValid) { if(isValid) { - try { - $.post("data/Venue/create", { - name: $editorForm.find("#DFName").val() - }, function(data) { - if(data.result == "success") { - if(close) $editorDialog.modal("hide"); - dataTable.refresh(); - } - else { - alert(data.result); - } - }, "json"); - } catch(e) { - alert(e); - } + $.ajax({url: "data/Venue/create", type: "POST", dataType: "json", data: encodeData({ + name: $editorForm.find("#DFName").val() + })}).done(function(data) { + if(close) $editorDialog.modal("hide"); + dataTable.refresh(); + }).fail(function(data) { + alert("Server call failed."); + }); } }); }; @@ -203,22 +207,15 @@ $editorDialog.find('#DFSave').on('click', function(event) { $editorForm.data('bs.validator').validate(function(isValid) { if(isValid) { - try { - $.post("data/Venue/edit", { - id: dataTable.getSelectedRow().data("model").id, - name: $editorForm.find("#DFName").val() - }, function(data) { - if(data.result == "success") { - $editorDialog.modal("hide"); - dataTable.refresh(); - } - else { - alert(data.result); - } - }, "json"); - } catch(e) { - alert(e); - } + $.ajax({url: "data/Venue/edit", type: "POST", dataType: "json", data: encodeData({ + id: dataTable.getSelectedRow().data("model").id, + name: $editorForm.find("#DFName").val() + })}).done(function(data) { + if(close) $editorDialog.modal("hide"); + dataTable.refresh(); + }).fail(function(data) { + alert("Server call failed."); + }); } }); }); @@ -244,11 +241,11 @@ //Delete the element and close the dialog. $deleteDialog.find('#DFDelete').on("click", function(event) { if(dataTable.getSelectedRow() != null) { - $.post("data/Venue/delete", {where: {id: dataTable.getSelectedRow().data("model").id}}, "json").done(function(data) { + $.ajax({url: "data/Venue/delete", type: "POST", dataType: "json", data: encodeData({where: {id: dataTable.getSelectedRow().data("model").id}})}).done(function(data) { $deleteDialog.modal("hide"); dataTable.refresh(); }).fail(function(data) { - alert("Failed to delete the selection.") + alert("Server call failed."); }); } }); diff --git a/public/admin/categories.html b/public/admin/categories.html index d1aa6a6..a3b3cda 100644 --- a/public/admin/categories.html +++ b/public/admin/categories.html @@ -4,7 +4,7 @@

Manage Categories

-
+
New Edit @@ -74,6 +74,31 @@ var $btnDelete = $page.find("#deleteButton"); var $btnRestore = $page.find("#restoreButton"); + $btnEdit.disable(true); + $btnDelete.disable(true); + $btnRestore.disable(true) + + var selectionChanged = function($tr, model) { + if($tr && model) { + $btnEdit.disable(false); + + //If the object was deleted (hidden), then allow it to be restored, otherwise allow the model to be deleted. + if(model.deletedAt) { + $btnRestore.disable(false); + $btnDelete.disable(true); + } + else { + $btnRestore.disable(true); + $btnDelete.disable(false); + } + } + else { + $btnEdit.disable(true); + $btnDelete.disable(true); + $btnRestore.disable(true); + } + }; + var dataTable = new LinkedTable($page.find('#dataTable'), { url: "data/Category/readAll", attr: "data-key-name", @@ -81,35 +106,25 @@ parameters: function() { return {paranoid: !$page.find('#includeDeletedToggle').is(":checked")}; }, - selectionChanged: function($tr, model) { - if($tr && model) { - $btnEdit.show(); - - //If the object was deleted (hidden), then allow it to be restored, otherwise allow the model to be deleted. - if(model.deletedAt) { - $btnRestore.show(); - $btnDelete.hide(); - } - else { - $btnRestore.hide(); - $btnDelete.show(); - } - } - else { - $btnEdit.hide(); - $btnDelete.hide(); - $btnRestore.hide(); - } - }, + selectionChanged: selectionChanged, postAddRowHandler: function($row, dataObject) { if(dataObject.deletedAt) { $("td:first", $row).prepend(""); } + }, + postUpdateRowHandler: function($row, dataObject) { + if(dataObject.deletedAt) { + $("td:first", $row).prepend(""); + } + + if($row.is(dataTable.getSelectedRow())) { + selectionChanged($row, dataObject); + } } }); //Call the refresh user table function once initially. - dataTable.refresh(); + dataTable.build(); //Refresh the data table if the user toggles the button to show/hide deleted elements. $page.find('#includeDeletedToggle').on('click', function(event) { @@ -170,21 +185,14 @@ var createFunction = function(close) { $editorForm.data('bs.validator').validate(function(isValid) { if(isValid) { - try { - $.post("data/Category/create", { - name: $editorForm.find("#DFName").val() - }, function(data) { - if(data.result == "success") { - if(close) $editorDialog.modal("hide"); - dataTable.refresh(); - } - else { - alert(data.result); - } - }, "json"); - } catch(e) { - alert(e); - } + $.ajax({url: "data/Category/create", type: "POST", dataType: "json", data: encodeData({ + name: $editorForm.find("#DFName").val() + })}).done(function(data) { + if(close) $editorDialog.modal("hide"); + dataTable.refresh(); + }).fail(function(data) { + alert("Server call failed."); + }); } }); }; @@ -198,22 +206,15 @@ $editorDialog.find('#DFSave').on('click', function(event) { $editorForm.data('bs.validator').validate(function(isValid) { if(isValid) { - try { - $.post("data/Category/edit", { - id: dataTable.getSelectedRow().data("model").id, - name: $editorForm.find("#DFName").val() - }, function(data) { - if(data.result == "success") { - $editorDialog.modal("hide"); - dataTable.refresh(); - } - else { - alert(data.result); - } - }, "json"); - } catch(e) { - alert(e); - } + $.ajax({url: "data/Category/edit", type: "POST", dataType: "json", data: { + id: dataTable.getSelectedRow().data("model").id, + name: $editorForm.find("#DFName").val() + }}).done(function(data) { + $editorDialog.modal("hide"); + dataTable.refresh(); + }).fail(function(data) { + alert("Server side error."); + }); } }); }); @@ -239,15 +240,12 @@ //Delete the element and close the dialog. $deleteDialog.find('#deleteButton').on("click", function(event) { if(dataTable.getSelectedRow() != null) { - $.post("data/Category/delete", {where: {id: dataTable.getSelectedRow().data("model").id}}, function(data) { - if(data.result == "success") { - $deleteDialog.modal("hide"); - dataTable.refresh(); - } - else { - alert(data.result); - } - }, "json"); + $.ajax({url: "data/Category/delete", type: "POST", dataType: "json", data: encodeData({where: {id: dataTable.getSelectedRow().data("model").id}})}).done(function(data) { + $deleteDialog.modal("hide"); + dataTable.refresh(); + }).fail(function(data) { + alert("Server call failed."); + }); } }); $deleteDialog.find('#DFCancelDelete').on('click', function(event) { diff --git a/public/admin/css/bootstrap-datetimepicker.css b/public/admin/css/bootstrap-datetimepicker.css new file mode 100644 index 0000000..4e484c5 --- /dev/null +++ b/public/admin/css/bootstrap-datetimepicker.css @@ -0,0 +1,373 @@ +/*! + * Datetimepicker for Bootstrap 3 + * version : 4.17.43 + * https://github.com/Eonasdan/bootstrap-datetimepicker/ + */ +.bootstrap-datetimepicker-widget { + list-style: none; +} +.bootstrap-datetimepicker-widget.dropdown-menu { + margin: 2px 0; + padding: 4px; + width: 19em; +} +@media (min-width: 768px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 992px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +@media (min-width: 1200px) { + .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs { + width: 38em; + } +} +.bootstrap-datetimepicker-widget.dropdown-menu:before, +.bootstrap-datetimepicker-widget.dropdown-menu:after { + content: ''; + display: inline-block; + position: absolute; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + top: -7px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + top: -6px; + left: 8px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:before { + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-top: 7px solid #ccc; + border-top-color: rgba(0, 0, 0, 0.2); + bottom: -7px; + left: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.top:after { + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-top: 6px solid white; + bottom: -6px; + left: 7px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before { + left: auto; + right: 6px; +} +.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after { + left: auto; + right: 7px; +} +.bootstrap-datetimepicker-widget .list-unstyled { + margin: 0; +} +.bootstrap-datetimepicker-widget a[data-action] { + padding: 6px 0; +} +.bootstrap-datetimepicker-widget a[data-action]:active { + box-shadow: none; +} +.bootstrap-datetimepicker-widget .timepicker-hour, +.bootstrap-datetimepicker-widget .timepicker-minute, +.bootstrap-datetimepicker-widget .timepicker-second { + width: 54px; + font-weight: bold; + font-size: 1.2em; + margin: 0; +} +.bootstrap-datetimepicker-widget button[data-action] { + padding: 6px; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Increment Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Decrement Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Hours"; +} +.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Show Minutes"; +} +.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle AM/PM"; +} +.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Clear the picker"; +} +.bootstrap-datetimepicker-widget .btn[data-action="today"]::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Set the date to today"; +} +.bootstrap-datetimepicker-widget .picker-switch { + text-align: center; +} +.bootstrap-datetimepicker-widget .picker-switch::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Toggle Date and Time Screens"; +} +.bootstrap-datetimepicker-widget .picker-switch td { + padding: 0; + margin: 0; + height: auto; + width: auto; + line-height: inherit; +} +.bootstrap-datetimepicker-widget .picker-switch td span { + line-height: 2.5; + height: 2.5em; + width: 100%; +} +.bootstrap-datetimepicker-widget table { + width: 100%; + margin: 0; +} +.bootstrap-datetimepicker-widget table td, +.bootstrap-datetimepicker-widget table th { + text-align: center; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table th { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table th.picker-switch { + width: 145px; +} +.bootstrap-datetimepicker-widget table th.disabled, +.bootstrap-datetimepicker-widget table th.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table th.prev::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Previous Month"; +} +.bootstrap-datetimepicker-widget table th.next::after { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + content: "Next Month"; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th { + cursor: pointer; +} +.bootstrap-datetimepicker-widget table thead tr:first-child th:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td { + height: 54px; + line-height: 54px; + width: 54px; +} +.bootstrap-datetimepicker-widget table td.cw { + font-size: .8em; + height: 20px; + line-height: 20px; + color: #777777; +} +.bootstrap-datetimepicker-widget table td.day { + height: 20px; + line-height: 20px; + width: 20px; +} +.bootstrap-datetimepicker-widget table td.day:hover, +.bootstrap-datetimepicker-widget table td.hour:hover, +.bootstrap-datetimepicker-widget table td.minute:hover, +.bootstrap-datetimepicker-widget table td.second:hover { + background: #eeeeee; + cursor: pointer; +} +.bootstrap-datetimepicker-widget table td.old, +.bootstrap-datetimepicker-widget table td.new { + color: #777777; +} +.bootstrap-datetimepicker-widget table td.today { + position: relative; +} +.bootstrap-datetimepicker-widget table td.today:before { + content: ''; + display: inline-block; + border: solid transparent; + border-width: 0 0 7px 7px; + border-bottom-color: #337ab7; + border-top-color: rgba(0, 0, 0, 0.2); + position: absolute; + bottom: 4px; + right: 4px; +} +.bootstrap-datetimepicker-widget table td.active, +.bootstrap-datetimepicker-widget table td.active:hover { + background-color: #337ab7; + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td.active.today:before { + border-bottom-color: #fff; +} +.bootstrap-datetimepicker-widget table td.disabled, +.bootstrap-datetimepicker-widget table td.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget table td span { + display: inline-block; + width: 54px; + height: 54px; + line-height: 54px; + margin: 2px 1.5px; + cursor: pointer; + border-radius: 4px; +} +.bootstrap-datetimepicker-widget table td span:hover { + background: #eeeeee; +} +.bootstrap-datetimepicker-widget table td span.active { + background-color: #337ab7; + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.bootstrap-datetimepicker-widget table td span.old { + color: #777777; +} +.bootstrap-datetimepicker-widget table td span.disabled, +.bootstrap-datetimepicker-widget table td span.disabled:hover { + background: none; + color: #777777; + cursor: not-allowed; +} +.bootstrap-datetimepicker-widget.usetwentyfour td.hour { + height: 27px; + line-height: 27px; +} +.bootstrap-datetimepicker-widget.wider { + width: 21em; +} +.bootstrap-datetimepicker-widget .datepicker-decades .decade { + line-height: 1.8em !important; +} +.input-group.date .input-group-addon { + cursor: pointer; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} diff --git a/public/admin/css/bootstrap-datetimepicker.min.css b/public/admin/css/bootstrap-datetimepicker.min.css new file mode 100644 index 0000000..1b22fb7 --- /dev/null +++ b/public/admin/css/bootstrap-datetimepicker.min.css @@ -0,0 +1,5 @@ +/*! + * Datetimepicker for Bootstrap 3 + * version : 4.17.43 + * https://github.com/Eonasdan/bootstrap-datetimepicker/ + */.bootstrap-datetimepicker-widget{list-style:none}.bootstrap-datetimepicker-widget.dropdown-menu{margin:2px 0;padding:4px;width:19em}@media (min-width:768px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:992px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:1200px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}.bootstrap-datetimepicker-widget.dropdown-menu:before,.bootstrap-datetimepicker-widget.dropdown-menu:after{content:'';display:inline-block;position:absolute}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before{border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,0.2);top:-7px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid white;top:-6px;left:8px}.bootstrap-datetimepicker-widget.dropdown-menu.top:before{border-left:7px solid transparent;border-right:7px solid transparent;border-top:7px solid #ccc;border-top-color:rgba(0,0,0,0.2);bottom:-7px;left:6px}.bootstrap-datetimepicker-widget.dropdown-menu.top:after{border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid white;bottom:-6px;left:7px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before{left:auto;right:6px}.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after{left:auto;right:7px}.bootstrap-datetimepicker-widget .list-unstyled{margin:0}.bootstrap-datetimepicker-widget a[data-action]{padding:6px 0}.bootstrap-datetimepicker-widget a[data-action]:active{box-shadow:none}.bootstrap-datetimepicker-widget .timepicker-hour,.bootstrap-datetimepicker-widget .timepicker-minute,.bootstrap-datetimepicker-widget .timepicker-second{width:54px;font-weight:bold;font-size:1.2em;margin:0}.bootstrap-datetimepicker-widget button[data-action]{padding:6px}.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Increment Hours"}.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Increment Minutes"}.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Decrement Hours"}.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Decrement Minutes"}.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Show Hours"}.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Show Minutes"}.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Toggle AM/PM"}.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Clear the picker"}.bootstrap-datetimepicker-widget .btn[data-action="today"]::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Set the date to today"}.bootstrap-datetimepicker-widget .picker-switch{text-align:center}.bootstrap-datetimepicker-widget .picker-switch::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Toggle Date and Time Screens"}.bootstrap-datetimepicker-widget .picker-switch td{padding:0;margin:0;height:auto;width:auto;line-height:inherit}.bootstrap-datetimepicker-widget .picker-switch td span{line-height:2.5;height:2.5em;width:100%}.bootstrap-datetimepicker-widget table{width:100%;margin:0}.bootstrap-datetimepicker-widget table td,.bootstrap-datetimepicker-widget table th{text-align:center;border-radius:4px}.bootstrap-datetimepicker-widget table th{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget table th.picker-switch{width:145px}.bootstrap-datetimepicker-widget table th.disabled,.bootstrap-datetimepicker-widget table th.disabled:hover{background:none;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget table th.prev::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Previous Month"}.bootstrap-datetimepicker-widget table th.next::after{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;content:"Next Month"}.bootstrap-datetimepicker-widget table thead tr:first-child th{cursor:pointer}.bootstrap-datetimepicker-widget table thead tr:first-child th:hover{background:#eee}.bootstrap-datetimepicker-widget table td{height:54px;line-height:54px;width:54px}.bootstrap-datetimepicker-widget table td.cw{font-size:.8em;height:20px;line-height:20px;color:#777}.bootstrap-datetimepicker-widget table td.day{height:20px;line-height:20px;width:20px}.bootstrap-datetimepicker-widget table td.day:hover,.bootstrap-datetimepicker-widget table td.hour:hover,.bootstrap-datetimepicker-widget table td.minute:hover,.bootstrap-datetimepicker-widget table td.second:hover{background:#eee;cursor:pointer}.bootstrap-datetimepicker-widget table td.old,.bootstrap-datetimepicker-widget table td.new{color:#777}.bootstrap-datetimepicker-widget table td.today{position:relative}.bootstrap-datetimepicker-widget table td.today:before{content:'';display:inline-block;border:solid transparent;border-width:0 0 7px 7px;border-bottom-color:#337ab7;border-top-color:rgba(0,0,0,0.2);position:absolute;bottom:4px;right:4px}.bootstrap-datetimepicker-widget table td.active,.bootstrap-datetimepicker-widget table td.active:hover{background-color:#337ab7;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.bootstrap-datetimepicker-widget table td.active.today:before{border-bottom-color:#fff}.bootstrap-datetimepicker-widget table td.disabled,.bootstrap-datetimepicker-widget table td.disabled:hover{background:none;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget table td span{display:inline-block;width:54px;height:54px;line-height:54px;margin:2px 1.5px;cursor:pointer;border-radius:4px}.bootstrap-datetimepicker-widget table td span:hover{background:#eee}.bootstrap-datetimepicker-widget table td span.active{background-color:#337ab7;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.bootstrap-datetimepicker-widget table td span.old{color:#777}.bootstrap-datetimepicker-widget table td span.disabled,.bootstrap-datetimepicker-widget table td span.disabled:hover{background:none;color:#777;cursor:not-allowed}.bootstrap-datetimepicker-widget.usetwentyfour td.hour{height:27px;line-height:27px}.bootstrap-datetimepicker-widget.wider{width:21em}.bootstrap-datetimepicker-widget .datepicker-decades .decade{line-height:1.8em !important}.input-group.date .input-group-addon{cursor:pointer}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0} \ No newline at end of file diff --git a/public/admin/index.ejs b/public/admin/index.ejs index d96fd59..f784c06 100644 --- a/public/admin/index.ejs +++ b/public/admin/index.ejs @@ -12,6 +12,8 @@ + + Petit Teton Apps @@ -24,6 +26,7 @@ + @@ -41,29 +44,68 @@ + - + - - - - +