Added holiday picker
Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
parent
63e44c5ad3
commit
182606db20
@ -304,6 +304,15 @@
|
|||||||
#requestAccess #createButton {
|
#requestAccess #createButton {
|
||||||
margin-top: 1.5em;
|
margin-top: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#holiday > div:first-child {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#holiday [tabindex]:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<app-location route="{{route}}"></app-location>
|
<app-location route="{{route}}"></app-location>
|
||||||
@ -314,12 +323,18 @@
|
|||||||
<!--paper-tab tab="time"><paper-icon-button icon="date-range"></paper-icon-button></paper-tab-->
|
<!--paper-tab tab="time"><paper-icon-button icon="date-range"></paper-icon-button></paper-tab-->
|
||||||
<paper-tab tab="memories"><paper-icon-button icon="today"></paper-icon-button></paper-tab>
|
<paper-tab tab="memories"><paper-icon-button icon="today"></paper-icon-button></paper-tab>
|
||||||
<paper-tab tab="albums"><paper-icon-button icon="folder"></paper-icon-button></paper-tab>
|
<paper-tab tab="albums"><paper-icon-button icon="folder"></paper-icon-button></paper-tab>
|
||||||
<paper-tab tab="thanksgiving"><paper-icon-button icon="maps:local-dining"></paper-icon-button></paper-tab>
|
<paper-tab tab="holiday"><paper-icon-button icon="redeem"></paper-icon-button></paper-tab>
|
||||||
<paper-tab hidden$="[[!user.maintainer]]" tab="duplicates"><paper-icon-button icon="compare-arrows"></paper-icon-button></paper-tab>
|
<paper-tab hidden$="[[!user.maintainer]]" tab="duplicates"><paper-icon-button icon="compare-arrows"></paper-icon-button></paper-tab>
|
||||||
<paper-tab hidden$="[[!user.maintainer]]" tab="trash"><paper-icon-button icon="delete"></paper-icon-button></paper-tab>
|
<paper-tab hidden$="[[!user.maintainer]]" tab="trash"><paper-icon-button icon="delete"></paper-icon-button></paper-tab>
|
||||||
</paper-tabs>
|
</paper-tabs>
|
||||||
<iron-pages id="pages" attr-for-selected="id" selected="[[mode]]" fallback-selection="loading">
|
<iron-pages id="pages" attr-for-selected="id" selected="[[mode]]" fallback-selection="loading">
|
||||||
<div id="loading"></div>
|
<div id="loading"></div>
|
||||||
|
<div id="holiday" class="flex layout vertical">
|
||||||
|
<div>Holidays</div>
|
||||||
|
<template is="dom-repeat" items="[[holidays]]">
|
||||||
|
<div tabindex="0" on-tap="loadHoliday">[[item]]</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
<div id="time"><div>... time slider ...</div></div>
|
<div id="time"><div>... time slider ...</div></div>
|
||||||
<div id="memories" class="flex layout vertical center">
|
<div id="memories" class="flex layout vertical center">
|
||||||
<div class="memory-buttons layout self-stretch horizontal around-justified">
|
<div class="memory-buttons layout self-stretch horizontal around-justified">
|
||||||
@ -386,7 +401,7 @@
|
|||||||
<div tabindex="0" on-tap="loadPath">[[item.name]] /</div>
|
<div tabindex="0" on-tap="loadPath">[[item.name]] /</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div mode="thanksgiving">Thanksgiving!</div>
|
<div mode="holiday">[[holidayTitle]]</div>
|
||||||
<div mode="time">time</div>
|
<div mode="time">time</div>
|
||||||
<div mode="memories">Photos taken on <b on-tap="drawerToggle">[[memoryDate]]</b></div>
|
<div mode="memories">Photos taken on <b on-tap="drawerToggle">[[memoryDate]]</b></div>
|
||||||
</iron-pages>
|
</iron-pages>
|
||||||
@ -551,6 +566,10 @@
|
|||||||
date: {
|
date: {
|
||||||
type: String,
|
type: String,
|
||||||
value: window.moment().format("YYYY-MM-DD")
|
value: window.moment().format("YYYY-MM-DD")
|
||||||
|
},
|
||||||
|
holiday: {
|
||||||
|
type: String,
|
||||||
|
value: "Christmas"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -846,6 +865,12 @@
|
|||||||
"iron-resize" : "onResize"
|
"iron-resize" : "onResize"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadHoliday: function(event) {
|
||||||
|
this.holiday = event.model.item;
|
||||||
|
this.resetPhotos();
|
||||||
|
this._loadPhotos();
|
||||||
|
},
|
||||||
|
|
||||||
loadPath: function(event) {
|
loadPath: function(event) {
|
||||||
this._pathLoad(event.model.item.path);
|
this._pathLoad(event.model.item.path);
|
||||||
},
|
},
|
||||||
@ -1695,8 +1720,8 @@
|
|||||||
path = "";
|
path = "";
|
||||||
} else if (mode == "memories") {
|
} else if (mode == "memories") {
|
||||||
path = "memories/" + (this.date.replace(this.year + "-", "") || "");
|
path = "memories/" + (this.date.replace(this.year + "-", "") || "");
|
||||||
} else if (mode == "thanksgiving") {
|
} else if (mode == "holiday") {
|
||||||
path = "thanksgiving/";
|
path = "holiday/" + this.holiday;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var username = this.user ? this.user.username : "";
|
var username = this.user ? this.user.username : "";
|
||||||
@ -1711,7 +1736,7 @@
|
|||||||
if ((username != (this.user ? this.user.username : "")) ||
|
if ((username != (this.user ? this.user.username : "")) ||
|
||||||
(mode != this.mode) ||
|
(mode != this.mode) ||
|
||||||
((mode == "albums") && (path != (this.path || ""))) ||
|
((mode == "albums") && (path != (this.path || ""))) ||
|
||||||
((mode == "thanksgiving") && (path != ("thanksgiving/"))) ||
|
((mode == "holiday") && (path != ("holiday/" + this.holiday))) ||
|
||||||
((mode == "memories") && (path != ("memories/" + (this.date.replace(this.year + "-", "") || ""))))) {
|
((mode == "memories") && (path != ("memories/" + (this.date.replace(this.year + "-", "") || ""))))) {
|
||||||
console.log("Skipping results for old query. Triggering re-fetch of photos for new path or mode.");
|
console.log("Skipping results for old query. Triggering re-fetch of photos for new path or mode.");
|
||||||
this._loadPhotos();
|
this._loadPhotos();
|
||||||
@ -1750,6 +1775,9 @@
|
|||||||
this._loadPhotos(results.cursor, true, this.limit * 2);
|
this._loadPhotos(results.cursor, true, this.limit * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.mode == "holiday") {
|
||||||
|
this.holidayTitle = results.holiday;
|
||||||
|
}
|
||||||
}.bind(this, path));
|
}.bind(this, path));
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1903,6 +1931,30 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadHolidays: function() {
|
||||||
|
window.fetch("api/v1/holidays", function(error, xhr) {
|
||||||
|
if (error) {
|
||||||
|
console.error(JSON.stringify(error, null, 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var results;
|
||||||
|
try {
|
||||||
|
results = JSON.parse(xhr.responseText);
|
||||||
|
} catch (___) {
|
||||||
|
this.$.toast.text = "Unable to parse holidays.";
|
||||||
|
this.$.toast.setAttribute("error", true);
|
||||||
|
this.$.toast.updateStyles();
|
||||||
|
this.$.toast.show();
|
||||||
|
console.log(xhr.responseText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.holiday = results.next;
|
||||||
|
this.holidays = results.holidays;
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
userChanged: function(user) {
|
userChanged: function(user) {
|
||||||
if (!this.firstRequest) {
|
if (!this.firstRequest) {
|
||||||
this.mode = "loading";
|
this.mode = "loading";
|
||||||
@ -1923,6 +1975,7 @@
|
|||||||
if (!user.restriction) {
|
if (!user.restriction) {
|
||||||
this.loginStatus = null;
|
this.loginStatus = null;
|
||||||
this.mode = "memories";
|
this.mode = "memories";
|
||||||
|
this.loadHolidays();
|
||||||
this.setActions();
|
this.setActions();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
"ldapauth-fork": "^4.0.2",
|
"ldapauth-fork": "^4.0.2",
|
||||||
"mariasql": "^0.2.6",
|
"mariasql": "^0.2.6",
|
||||||
"moment": "^2.22.2",
|
"moment": "^2.22.2",
|
||||||
|
"moment-holiday": "^1.5.1",
|
||||||
"morgan": "^1.9.0",
|
"morgan": "^1.9.0",
|
||||||
"mustache": "^3.0.0",
|
"mustache": "^3.0.0",
|
||||||
"nodemailer": "^4.6.8",
|
"nodemailer": "^4.6.8",
|
||||||
|
@ -263,6 +263,7 @@ app.use(basePath, express.static(picturesPath, { index: false }));
|
|||||||
app.use(basePath + "api/v1/photos", require("./routes/photos"));
|
app.use(basePath + "api/v1/photos", require("./routes/photos"));
|
||||||
app.use(basePath + "api/v1/days", require("./routes/days"));
|
app.use(basePath + "api/v1/days", require("./routes/days"));
|
||||||
app.use(basePath + "api/v1/albums", require("./routes/albums"));
|
app.use(basePath + "api/v1/albums", require("./routes/albums"));
|
||||||
|
app.use(basePath + "api/v1/holidays", require("./routes/holidays"));
|
||||||
app.use(basePath + "api/v1/scan", require("./routes/scan")(scanner));
|
app.use(basePath + "api/v1/scan", require("./routes/scan")(scanner));
|
||||||
|
|
||||||
/* Declare the "catch all" index route last; the final route is a 404 dynamic router */
|
/* Declare the "catch all" index route last; the final route is a 404 dynamic router */
|
||||||
|
108
server/lib/pascha.js
Normal file
108
server/lib/pascha.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
//! moment-holiday.js locale configuration
|
||||||
|
//! locale : pascha Related Holidays
|
||||||
|
//! author : Kodie Grantham : https://github.com/kodie
|
||||||
|
|
||||||
|
//(function() {
|
||||||
|
// var moment = (typeof require !== 'undefined' && require !== null) && !require.amd ? require('moment') : this.moment;
|
||||||
|
function init(moment) {
|
||||||
|
// moment.holidays.pascha = {
|
||||||
|
moment.modifyHolidays.add({
|
||||||
|
"Lent": {
|
||||||
|
date: 'pascha-46|pascha-3'
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
"Holy Monday": {
|
||||||
|
date: 'pascha-6',
|
||||||
|
keywords_y: ['great', 'monday']
|
||||||
|
},
|
||||||
|
"Holy Tuesday": {
|
||||||
|
date: 'pascha-5',
|
||||||
|
keywords_y: ['great', 'tuesday']
|
||||||
|
},
|
||||||
|
"Holy Wednesday": {
|
||||||
|
date: 'pascha-4',
|
||||||
|
keywords_y: ['great', 'wednesday']
|
||||||
|
},
|
||||||
|
"Holy Thursday": {
|
||||||
|
date: 'pascha-3',
|
||||||
|
keywords_y: ['great', 'thursday']
|
||||||
|
},
|
||||||
|
"Holy Friday": {
|
||||||
|
date: 'pascha-2',
|
||||||
|
keywords_y: ['great', 'friday']
|
||||||
|
},
|
||||||
|
"Holy Saturday": {
|
||||||
|
date: 'pascha-1',
|
||||||
|
keywords_y: ['holy', 'saturday']
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
"Pascha Sunday": {
|
||||||
|
date: 'pascha',
|
||||||
|
keywords_y: ['pascha'],
|
||||||
|
keywords: ['sunday']
|
||||||
|
},
|
||||||
|
"Bright Week": {
|
||||||
|
date: 'pascha+1|pascha+6'
|
||||||
|
},
|
||||||
|
"Pentecost Sunday": {
|
||||||
|
date: 'pascha+49',
|
||||||
|
keywords_y: ['pentecost'],
|
||||||
|
keywords: ['sunday']
|
||||||
|
},
|
||||||
|
//};
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates Easter in the Gregorian/Western (Catholic and Protestant) calendar
|
||||||
|
* based on the algorithm by Oudin (1940) from http://www.tondering.dk/claus/cal/easter.php
|
||||||
|
* @returns {array} [int month, int day]
|
||||||
|
*/
|
||||||
|
var pascha = function(year) {
|
||||||
|
var f = Math.floor,
|
||||||
|
// Golden Number - 1
|
||||||
|
G = year % 19,
|
||||||
|
C = f(year / 100),
|
||||||
|
// related to Epact
|
||||||
|
H = (C - f(C / 4) - f((8 * C + 13)/25) + 19 * G + 15) % 30,
|
||||||
|
// number of days from 21 March to the Paschal full moon
|
||||||
|
I = H - f(H/28) * (1 - f(29/(H + 1)) * f((21-G)/11)),
|
||||||
|
// weekday for the Paschal full moon
|
||||||
|
J = (year + f(year / 4) + I + 2 - C + f(C / 4)) % 7,
|
||||||
|
// number of days from 21 March to the Sunday on or before the Paschal full moon
|
||||||
|
L = I - J,
|
||||||
|
month = 3 + f((L + 40)/44),
|
||||||
|
day = L + 28 - 31 * f(month / 4);
|
||||||
|
|
||||||
|
return moment([year, (month - 1),day]);
|
||||||
|
}
|
||||||
|
|
||||||
|
moment.modifyHolidays.extendParser(function(m, date){
|
||||||
|
if (~date.indexOf('pascha')) {
|
||||||
|
var dates = date.split('|');
|
||||||
|
var ds = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < dates.length; i++) {
|
||||||
|
if (dates[i].substring(0, 6) === 'pascha') {
|
||||||
|
var e = pascha(m.year());
|
||||||
|
|
||||||
|
if (dates[i].charAt(6) === '-') { e.subtract(dates[i].substring(7), 'days'); }
|
||||||
|
if (dates[i].charAt(6) === '+') { e.add(dates[i].substring(7), 'days'); }
|
||||||
|
|
||||||
|
if (dates.length === 1) { return e; }
|
||||||
|
ds.push(e.format('M/D'));
|
||||||
|
} else {
|
||||||
|
ds.push(dates[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds.length) { return ds.join('|'); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Pascha initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = init;
|
||||||
|
|
||||||
|
// if ((typeof module !== 'undefined' && module !== null ? module.exports : void 0) != null) { module.exports = moment; }
|
||||||
|
//}).call(this);
|
49
server/routes/holidays.js
Normal file
49
server/routes/holidays.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const express = require("express"),
|
||||||
|
moment = require("moment-holiday");
|
||||||
|
|
||||||
|
require("../lib/pascha.js")(moment);
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
/* Remove the western Easter dates, except for Easter itself */
|
||||||
|
[ 'Good Friday' ].forEach(function(holiday) {
|
||||||
|
moment.modifyHolidays.remove(holiday);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/", function(req, res/*, next*/) {
|
||||||
|
let holidays = [], skip = {};
|
||||||
|
|
||||||
|
|
||||||
|
moment("2000-01-01", "YYYY-MM-DD").holidaysBetween("2000-12-31").forEach(function(holiday) {
|
||||||
|
/* Dates with multiple holidays will return an array of items */
|
||||||
|
let names = holiday.isHoliday();
|
||||||
|
if (!Array.isArray(names)) {
|
||||||
|
names = [ names ];
|
||||||
|
}
|
||||||
|
names.forEach(function(name) {
|
||||||
|
if (name in skip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this holiday already exists, remove it from the holidays list
|
||||||
|
* as we only want single day events returned, and add to the 'skip'
|
||||||
|
* list */
|
||||||
|
let index = holidays.indexOf(name);
|
||||||
|
if (index != -1) {
|
||||||
|
holidays.splice(index, 1);
|
||||||
|
skip[name] = true;
|
||||||
|
} else {
|
||||||
|
holidays.push(name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
holidays: holidays,
|
||||||
|
next: moment().nextHoliday().isHoliday()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -3,11 +3,13 @@
|
|||||||
const express = require("express"),
|
const express = require("express"),
|
||||||
fs = require("fs"),
|
fs = require("fs"),
|
||||||
config = require("config"),
|
config = require("config"),
|
||||||
moment = require("moment"),
|
moment = require("moment-holiday"),
|
||||||
crypto = require("crypto"),
|
crypto = require("crypto"),
|
||||||
util = require("util"),
|
util = require("util"),
|
||||||
Promise = require("bluebird");
|
Promise = require("bluebird");
|
||||||
|
|
||||||
|
require("../lib/pascha.js")(moment);
|
||||||
|
|
||||||
const execFile = util.promisify(require("child_process").execFile);
|
const execFile = util.promisify(require("child_process").execFile);
|
||||||
|
|
||||||
let photoDB;
|
let photoDB;
|
||||||
@ -538,56 +540,40 @@ router.delete("/:id?", function(req, res/*, next*/) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/thanksgiving", function(req, res/*, next*/) {
|
router.get("/holiday/:holiday", function(req, res/*, next*/) {
|
||||||
let thanksgiving = [
|
let startYear = 1990,
|
||||||
"1995-11-23",
|
dayIsHoliday = "",
|
||||||
"1996-11-28",
|
holidayName;
|
||||||
"1997-11-27",
|
|
||||||
"1998-11-26",
|
|
||||||
"1999-11-25",
|
|
||||||
"2000-11-23",
|
|
||||||
"2001-11-22",
|
|
||||||
"2002-11-28",
|
|
||||||
"2003-11-27",
|
|
||||||
"2004-11-25",
|
|
||||||
"2005-11-24",
|
|
||||||
"2006-11-23",
|
|
||||||
"2007-11-22",
|
|
||||||
"2008-11-27",
|
|
||||||
"2009-11-26",
|
|
||||||
"2010-11-25",
|
|
||||||
"2011-11-24",
|
|
||||||
"2012-11-22",
|
|
||||||
"2013-11-28",
|
|
||||||
"2014-11-27",
|
|
||||||
"2015-11-26",
|
|
||||||
"2016-11-24",
|
|
||||||
"2017-11-23",
|
|
||||||
"2018-11-22",
|
|
||||||
"2019-11-28",
|
|
||||||
"2020-11-26"
|
|
||||||
];
|
|
||||||
|
|
||||||
let dayIsThanksgiving = "";
|
let lookup = moment().holidays([req.params.holiday]);
|
||||||
thanksgiving.forEach(function(date) {
|
if (!lookup) {
|
||||||
let comparison = "strftime('%Y-%m-%d',taken)='" + date + "'";
|
return res.status(404).send(req.params.holiday + " holiday not found.");
|
||||||
if (!dayIsThanksgiving) {
|
}
|
||||||
dayIsThanksgiving = comparison;
|
holidayName = Object.getOwnPropertyNames(lookup)[0];
|
||||||
} else {
|
|
||||||
dayIsThanksgiving += " OR " + comparison;
|
for (let year = startYear; year <= moment().year(); year++) {
|
||||||
|
let holiday = moment(year + "-01-01", "YYYY-MM-DD").holiday(req.params.holiday);
|
||||||
|
if (!holiday) {
|
||||||
|
/* 'Leap Year' doesn't exist every year... */
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
let comparison = "strftime('%Y-%m-%d',taken)='" + holiday.format("YYYY-MM-DD") + "'"
|
||||||
|
if (!dayIsHoliday) {
|
||||||
|
dayIsHoliday = comparison;
|
||||||
|
} else {
|
||||||
|
dayIsHoliday += " OR " + comparison;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let query = "SELECT photos.*,albums.path AS path FROM photos " +
|
let query = "SELECT photos.*,albums.path AS path FROM photos " +
|
||||||
"INNER JOIN albums ON (albums.id=photos.albumId) " +
|
"INNER JOIN albums ON (albums.id=photos.albumId) " +
|
||||||
"WHERE (photos.duplicate=0 AND photos.deleted=0 AND photos.scanned NOT NULL AND (" + dayIsThanksgiving + ")) " +
|
"WHERE (photos.duplicate=0 AND photos.deleted=0 AND photos.scanned NOT NULL AND (" + dayIsHoliday + ")) " +
|
||||||
"ORDER BY strftime('%Y-%m-%d', taken) DESC,id DESC";
|
"ORDER BY strftime('%Y-%m-%d', taken) DESC,id DESC";
|
||||||
|
|
||||||
return photoDB.sequelize.query(query, {
|
return photoDB.sequelize.query(query, {
|
||||||
type: photoDB.Sequelize.QueryTypes.SELECT
|
type: photoDB.Sequelize.QueryTypes.SELECT
|
||||||
}).then(function(photos) {
|
}).then(function(photos) {
|
||||||
console.log(query);
|
|
||||||
console.log(JSON.stringify(photos));
|
|
||||||
photos.forEach(function(photo) {
|
photos.forEach(function(photo) {
|
||||||
for (var key in photo) {
|
for (var key in photo) {
|
||||||
if (photo[key] instanceof Date) {
|
if (photo[key] instanceof Date) {
|
||||||
@ -597,6 +583,7 @@ router.get("/thanksgiving", function(req, res/*, next*/) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
|
holiday: holidayName,
|
||||||
items: photos
|
items: photos
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user