Changed Appreciation to Jr High Summer; Fixed sorting of internships such that changes get properly sorted; Added a proper date on news & notices on the home page using the page's update timestamp.

This commit is contained in:
Wynne Crisman
2019-01-07 16:53:54 -08:00
parent 0593c2421a
commit cac2ad9c41
21 changed files with 160 additions and 109 deletions

View File

@@ -204,7 +204,7 @@ h3
@import "../imports/ui/Fellowships.import.styl" @import "../imports/ui/Fellowships.import.styl"
@import "../imports/ui/News&Notices.import.styl" @import "../imports/ui/News&Notices.import.styl"
@import "../imports/ui/PhotoGallery.import.styl" @import "../imports/ui/PhotoGallery.import.styl"
@import "../imports/ui/Appreciation.import.styl" @import "../imports/ui/JrHighSummer.import.styl"
@import "../imports/ui/Support.import.styl" @import "../imports/ui/Support.import.styl"
@import "../imports/ui/CurrentBoard.import.styl" @import "../imports/ui/CurrentBoard.import.styl"

View File

@@ -46,7 +46,7 @@ if(Meteor.isServer) {
//Verify the currently logged in user has authority to manage users. //Verify the currently logged in user has authority to manage users.
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_MANAGE])) { if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_MANAGE])) {
//Verify the user name isn't already used with a different ID. //Verify the user name isn't already used with a different ID.
if(Meteor.collections.Users.findOne({username: user.username, _id: {$ne: user._id}}) == undefined) { if(Meteor.collections.Users.findOne({username: user.username, _id: {$ne: user._id}}) === undefined) {
//Update the user. Note: I am using direct mongo modification, versus attempting to go through the Accounts and Roles objects. This could cause problems in the future if these packages change their data structures. //Update the user. Note: I am using direct mongo modification, versus attempting to go through the Accounts and Roles objects. This could cause problems in the future if these packages change their data structures.
Meteor.collections.Users.update(user._id, {$set: {username: user.username, emails: user.emails, roles: user.roles}}); Meteor.collections.Users.update(user._id, {$set: {username: user.username, emails: user.emails, roles: user.roles}});
} }

View File

@@ -1,6 +1,7 @@
import { AccountsTemplates } from 'meteor/useraccounts:core'; import { AccountsTemplates } from 'meteor/useraccounts:core';
AccountsTemplates.configure({ AccountsTemplates.configure({
enablePasswordChange: true, //Allow the user to change their password via the login UI.
forbidClientAccountCreation: true, //Turn off client side account creation. The app is expected to have a feature that will do this. forbidClientAccountCreation: true, //Turn off client side account creation. The app is expected to have a feature that will do this.
showForgotPasswordLink: true, showForgotPasswordLink: true,
defaultTemplate: 'OverrideAtForm', defaultTemplate: 'OverrideAtForm',
@@ -11,7 +12,11 @@ AccountsTemplates.configure({
// defaultLayout: 'Body', // defaultLayout: 'Body',
// defaultContentRegion: 'content', // defaultContentRegion: 'content',
// defaultLayoutRegions: {} // defaultLayoutRegions: {}
homeRoutePath: '/Admin/InternshipJobs', //The path where the user is taken after logging in successfully. homeRoutePath: '/Admin/Internships', //The path where the user is taken after logging in successfully. Unfortunately this is also used for the path when logging out, so we must override that function with an onLogoutHook.
onLogoutHook: function() {
FlowRouter.go("/");
},
texts: { texts: {
title: { title: {
signIn: "" signIn: ""

View File

@@ -27,6 +27,10 @@ AccountsTemplates.configureRoute('forgotPwd', {
name: 'ForgotPwd', name: 'ForgotPwd',
path: '/ForgotPwd' path: '/ForgotPwd'
}); });
AccountsTemplates.configureRoute('changePwd', {
name: 'ChangePwd',
path: '/ChangePwd'
});
pri.route("/Admin/Internships", { pri.route("/Admin/Internships", {
name: "InternshipsEditor", name: "InternshipsEditor",
@@ -56,8 +60,8 @@ pri.route("/Admin/UserManagement", {
BlazeLayout.render("Admin", {content: "UserManagement"}); BlazeLayout.render("Admin", {content: "UserManagement"});
} }
}); });
pri.route("/Admin/Appreciation", { pri.route("/Admin/JrHighSummer", {
name: "AppreciationEditor", name: "JrHighSummerEditor",
action: function(params, queryParams) { action: function(params, queryParams) {
require("/imports/ui/Admin/PageEditor.js"); require("/imports/ui/Admin/PageEditor.js");
BlazeLayout.render("Admin", {content: "PageEditor"}); BlazeLayout.render("Admin", {content: "PageEditor"});
@@ -187,8 +191,8 @@ pub.route("/PhotoGallery", {
BlazeLayout.render("Public", {content: "PhotoGallery"}); BlazeLayout.render("Public", {content: "PhotoGallery"});
} }
}); });
pub.route("/Appreciation", { pub.route("/JrHighSummer", {
name: 'Appreciation', name: 'JrHighSummer',
action: function(params, queryParams) { action: function(params, queryParams) {
require("/imports/ui/EditablePage.js"); require("/imports/ui/EditablePage.js");
BlazeLayout.render("Public", {content: "EditablePage"}); BlazeLayout.render("Public", {content: "EditablePage"});

View File

@@ -1,6 +1,32 @@
Accounts.emailTemplates.from = "Do Not Reply <administrator@declarativeengineering.com>"; Accounts.emailTemplates.from = "Do Not Reply <no-reply@andersonvalleyeducation.org>";
Accounts.emailTemplates.siteName = "Petit Teton App"; Accounts.emailTemplates.siteName = "Anderson Valley Education Foundation";
Accounts.emailTemplates.resetPassword.txt = function(user, url) {
let result;
result = "Hello,\n\
\n\
To reset your password, simply click the link below\n\
\n\
" + url.replace("#/reset-password","ResetPwd") + "\n\
\n\
Thank you,\n\
\tAnderson Valley Education Foundation";
return result;
};
Accounts.emailTemplates.resetPassword.html = function(user, url) {
let result;
result = "<p>Hello,</p>\
<p>To reset your password, simply click the link below</p>\
<a href='" + url.replace("#/reset-password","ResetPwd") + "'>Reset Link</a>\
<p>Thank you,<br/>\
<span style='text-indent: 20px'>Anderson Valley Education Foundation</span></p>";
return result;
};
// Accounts.emailTemplates.verifyEmail.subject = function (user) { // Accounts.emailTemplates.verifyEmail.subject = function (user) {
// return "Welcome to My Site! Please verify your email"; // return "Welcome to My Site! Please verify your email";
// }; // };

View File

@@ -10,12 +10,13 @@ Tracker.autorun(function() {
}); });
Template.InternshipEditor.onCreated(function() { Template.InternshipEditor.onCreated(function() {
this.internships = Meteor.collections.Internship.find({}, {sort: {name: 1}}); //this.internships = Meteor.collections.Internship.find({}, {sort: {name: 1}});
Session.set(PREFIX + 'selectedInternship', null); Session.set(PREFIX + 'selectedInternship', null);
}); });
Template.InternshipEditor.helpers({ Template.InternshipEditor.helpers({
internships: function() { internships: function() {
return Template.instance().internships; //return Template.instance().internships;
return Meteor.collections.Internship.find({}, {sort: {name: 1}});
}, },
selectedInternship: function() { selectedInternship: function() {
return Session.get(PREFIX + "selectedInternship"); return Session.get(PREFIX + "selectedInternship");
@@ -107,7 +108,8 @@ Template.InternshipHtmlEditor.onCreated(function() {
let template = this; let template = this;
//Only ask the user if they want to update their changes if they actually have changes that have not yet been saved. //Only ask the user if they want to update their changes if they actually have changes that have not yet been saved.
if(data !== template.currentHtml) { //Note: This is only useful if the user was editing an internship. If the user was looking at the list then template.currentHtml will be undefined.
if(template.currentHtml && data !== template.currentHtml) {
const changedData = data; const changedData = data;
//Ensure this does not get run twice. //Ensure this does not get run twice.

View File

@@ -6,7 +6,7 @@ let currentHtml = "";
let currentPath = ""; let currentPath = "";
let routeData = { let routeData = {
AppreciationEditor: {title: "Appreciation", name: "Appreciation"}, JrHighSummerEditor: {title: "Jr High Summer", name: "JrHighSummer"},
NewsEditor: {title: "News", name: "News"}, NewsEditor: {title: "News", name: "News"},
DatesEditor: {title: "Dates", name: "Dates"}, DatesEditor: {title: "Dates", name: "Dates"},
BoardEditor: {title: "Current Board", name: "Board"}, BoardEditor: {title: "Current Board", name: "Board"},

View File

@@ -144,7 +144,6 @@ Template.UserEditor.events({
let roles = []; let roles = [];
user.username = template.$('input[name="username"]').val(); user.username = template.$('input[name="username"]').val();
user.email = template.$('input[name="email"]').val();
let roleSpans = template.$('.role.selected'); let roleSpans = template.$('.role.selected');
for(let i = 0; i < roleSpans.length; i++) { for(let i = 0; i < roleSpans.length; i++) {
@@ -154,6 +153,7 @@ Template.UserEditor.events({
user.roles = roles; user.roles = roles;
if(Session.get(PREFIX + 'displayNewUser')) { if(Session.get(PREFIX + 'displayNewUser')) {
user.email = template.$('input[name="email"]').val();
Meteor.call('insertUser', user, function(error, result) { Meteor.call('insertUser', user, function(error, result) {
if(error) { if(error) {
sAlert.error(error); sAlert.error(error);
@@ -166,6 +166,7 @@ Template.UserEditor.events({
}); });
} }
else { else {
user.emails = [{address: template.$('input[name="email"]').val(), verified: true}]; //Since this is through the admin console we will assume the address is verified.
user._id = this._id; user._id = this._id;
Meteor.call("updateUser", user, function(error, result) { Meteor.call("updateUser", user, function(error, result) {
if(error) sAlert.error(error); if(error) sAlert.error(error);

View File

@@ -1,5 +0,0 @@
<template name="Appreciation">
<div id="appreciation" class="textView">
{{{appreciationHTML}}}
</div>
</template>

View File

@@ -1,21 +0,0 @@
#appreciationView
display: block
#appreciation p, #appreciationEditor p
font-family: Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif
font-size: 16px
margin: 16px 0
#appreciation h2, #appreciationEditor h2
font-family: "Arial Black", "Arial Bold", Gadget, sans-serif
font-size: 19px
text-transform: uppercase
background-color: #EEE
font-weight: bold
padding-left: 40px
#appreciation h4, #appreciationEditor h4
font-family: "Century Gothic", CenturyGothic, AppleGothic, sans-serif
font-size: 16px
font-weight: 800
clear: left

View File

@@ -1,14 +0,0 @@
import './Appreciation.html';
Tracker.autorun(function() {
Meteor.subscribe("pages");
});
Template.Appreciation.helpers({
appreciationHTML: function() {
let doc = Meteor.collections.Pages.findOne({name: 'Appreciation'});
return doc === undefined ? "" : doc.html;
}
});

View File

@@ -1,7 +1,7 @@
import './EditablePage.html'; import './EditablePage.html';
let routeData = { let routeData = {
Appreciation: {name: "Appreciation"}, JrHighSummer: {name: "JrHighSummer"},
News: {name: "News"}, News: {name: "News"},
ImportantDates: {name: "Dates"}, ImportantDates: {name: "Dates"},
CurrentBoard: {name: "Board"} CurrentBoard: {name: "Board"}

View File

@@ -24,7 +24,7 @@
<a class="menuTile newsMenu" href="{{pathFor 'News'}}"> <a class="menuTile newsMenu" href="{{pathFor 'News'}}">
<div class="menuHeaderBackground"></div> <div class="menuHeaderBackground"></div>
<div class="menuHeader">News &amp; Notices</div> <div class="menuHeader">News &amp; Notices</div>
<div id="newsHeaderTimestampDiv" class="menuHeaderTimestamp">03/13/18</div> <div id="newsHeaderTimestampDiv" class="menuHeaderTimestamp">{{newsDate}}</div> <!--03/13/18-->
<!--<a style="display: none" href="#!/news">news</a>--> <!--<a style="display: none" href="#!/news">news</a>-->
</a> </a>
<a class="menuTile photoGalleryMenu" href="{{pathFor 'PhotoGallery'}}"> <a class="menuTile photoGalleryMenu" href="{{pathFor 'PhotoGallery'}}">
@@ -32,11 +32,9 @@
<div class="menuHeader">Photo Gallery</div> <div class="menuHeader">Photo Gallery</div>
<!--<a style="display: none" href="#!/gallery">gallery</a>--> <!--<a style="display: none" href="#!/gallery">gallery</a>-->
</a> </a>
<a class="menuTile appreciationMenu" href="{{pathFor 'Appreciation'}}"> <a class="menuTile jrHighSummerMenu" href="{{pathFor 'JrHighSummer'}}">
<div class="menuHeaderBackground"></div> <div class="menuHeaderBackground"></div>
<div class="menuHeader">Appreciation</div> <div class="menuHeader">Jr High Summer</div>
<div id="appreciationHeaderTimestampDiv" class="menuHeaderTimestamp">11/13/17</div>
<!--<a style="display: none" href="#!/appreciation">appreciation</a>-->
</a> </a>
<a class="menuTile howCanYouHelpMenu" href="{{pathFor 'HowCanYouHelp'}}"> <a class="menuTile howCanYouHelpMenu" href="{{pathFor 'HowCanYouHelp'}}">
<div class="menuHeaderBackground"></div> <div class="menuHeaderBackground"></div>

View File

@@ -90,7 +90,7 @@
left: 245px left: 245px
top: 160px top: 160px
background-image: url('./images/buckeye_seed_v2.jpg') background-image: url('./images/buckeye_seed_v2.jpg')
.appreciationMenu .jrHighSummerMenu
left: 490px left: 490px
top: 160px top: 160px
background-image: url('./images/bay_seed_v2.jpg') background-image: url('./images/bay_seed_v2.jpg')

View File

@@ -1,6 +1,10 @@
import './Home.html'; import './Home.html';
Tracker.autorun(function() {
Meteor.subscribe("pages");
});
Template.Home.events({ Template.Home.events({
'mouseenter .menuTile': function (event, template) { 'mouseenter .menuTile': function (event, template) {
event.preventDefault(); event.preventDefault();
@@ -11,3 +15,11 @@ Template.Home.events({
$(event.target).find(".menuHeaderBackground").hide(); $(event.target).find(".menuHeaderBackground").hide();
} }
}); });
Template.Home.helpers({
newsDate: function() {
let news = Meteor.collections.Pages.findOne({name: "News"});
let date = news ? news.updatedAt : undefined;
return date ? moment(date).format("MM / DD / YY") : "";
}
});

View File

@@ -7,11 +7,12 @@ Tracker.autorun(function() {
}); });
Template.InternshipJobs.onCreated(function() { Template.InternshipJobs.onCreated(function() {
this.internships = Meteor.collections.Internship.find({}, {sort: {name: 1}}); //this.internships = Meteor.collections.Internship.find({}, {sort: {name: 1}});
}); });
Template.InternshipJobs.helpers({ Template.InternshipJobs.helpers({
internships: function() { internships: function() {
return Template.instance().internships; //return Template.instance().internships;
return Meteor.collections.Internship.find({}, {sort: {name: 1}});
} }
}); });
Template.InternshipJobs.events({ Template.InternshipJobs.events({

View File

@@ -0,0 +1,5 @@
<template name="JrHighSummer">
<div id="jrHighSummer" class="textView">
{{{html}}}
</div>
</template>

21
imports/ui/JrHighSummer.import.styl vendored Normal file
View File

@@ -0,0 +1,21 @@
#jrHighSummer
display: block
p
font-family: Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif
font-size: 16px
margin: 16px 0
h2
font-family: "Arial Black", "Arial Bold", Gadget, sans-serif
font-size: 19px
text-transform: uppercase
background-color: #EEE
font-weight: bold
padding-left: 40px
h4
font-family: "Century Gothic", CenturyGothic, AppleGothic, sans-serif
font-size: 16px
font-weight: 800
clear: left

View File

@@ -0,0 +1,14 @@
import './JrHighSummer.html';
Tracker.autorun(function() {
Meteor.subscribe("pages");
});
Template.JrHighSummer.helpers({
html: function() {
let doc = Meteor.collections.Pages.findOne({name: 'JrHighSummer'});
return doc === undefined ? "" : doc.html;
}
});

View File

@@ -30,9 +30,9 @@
Important Dates Important Dates
</a> </a>
</li> </li>
<li class="{{isActiveRoute 'AppreciationEditor'}}"> <li class="{{isActiveRoute 'JrHighSummerEditor'}}">
<a href="{{pathFor 'AppreciationEditor'}}"> <a href="{{pathFor 'JrHighSummerEditor'}}">
Appreciation Jr High Summer
</a> </a>
</li> </li>
<li class="{{isActiveRoute 'BoardEditor'}}"> <li class="{{isActiveRoute 'BoardEditor'}}">

View File

@@ -4,7 +4,8 @@ import '/imports/startup/both';
import '/imports/api'; import '/imports/api';
import '/imports/startup/server/postStartup/version.js'; //Run this right after the api - relies on the API to upgrade the app database & data to the current version. import '/imports/startup/server/postStartup/version.js'; //Run this right after the api - relies on the API to upgrade the app database & data to the current version.
import { Picker } from 'meteor/meteorhacks:picker'; import { Picker } from 'meteor/meteorhacks:picker';
import {SSR, Template} from "meteor/meteorhacks:ssr"; //import {SSR, Template} from "meteor/meteorhacks:ssr";
// let PropertiesReader = require('properties-reader'); // let PropertiesReader = require('properties-reader');
// let props = PropertiesReader('release.properties'); // let props = PropertiesReader('release.properties');
@@ -14,6 +15,7 @@ import {SSR, Template} from "meteor/meteorhacks:ssr";
// // console.log("Loaded email settings from properties file."); // // console.log("Loaded email settings from properties file.");
// } // }
//Note: This is set in a development environment, or at runtime via the Nginx config file for the app (if using phusion passenger, it would be: `passenger_env_var MAIL_URL smtp://no-reply%40my-domain.com:my_password@secure.emailsrvr.com`).
if (!process.env.MAIL_URL) { if (!process.env.MAIL_URL) {
process.env.MAIL_URL = Meteor.settings.MAIL_URL; process.env.MAIL_URL = Meteor.settings.MAIL_URL;
} }
@@ -30,30 +32,30 @@ if(process.env.MONGO_URL) {
else console.log(msg); else console.log(msg);
} }
const SeoRouter = Picker.filter((request, response) => { //const SeoRouter = Picker.filter((request, response) => {
let botAgents = [ // let botAgents = [
/^facebookexternalhit/i, // Facebook // /^facebookexternalhit/i, // Facebook
/^linkedinbot/i, // LinkedIn // /^linkedinbot/i, // LinkedIn
/^twitterbot/i, // Twitter // /^twitterbot/i, // Twitter
/^slackbot-linkexpanding/i // Slack // /^slackbot-linkexpanding/i // Slack
]; // ];
//
return /_escaped_fragment_/.test(request.url) || botAgents.some(i => i.test(request.headers['user-agent'])); // return /_escaped_fragment_/.test(request.url) || botAgents.some(i => i.test(request.headers['user-agent']));
}); //});
const path = require('path'); //const path = require('path');
const fs = require('fs'); //const fs = require('fs');
let templateMap = JSON.parse(Assets.getText('template-index')); //let templateMap = JSON.parse(Assets.getText('template-index'));
let templateNames = Object.keys(templateMap); //let templateNames = Object.keys(templateMap);
templateNames.forEach(function(key) { //templateNames.forEach(function(key) {
//console.log(key); // //console.log(key);
//console.log(templateMap[key]); // //console.log(templateMap[key]);
//console.log("------------------------------------------------------------------------------------------------"); // //console.log("------------------------------------------------------------------------------------------------");
SSR.compileTemplate(key, templateMap[key]); // SSR.compileTemplate(key, templateMap[key]);
}); //});
//console.log(Meteor.rootPath); //console.log(Meteor.rootPath);
@@ -91,25 +93,25 @@ templateNames.forEach(function(key) {
//SSR.compileTemplate('home', Assets.getText('/imports/ui/Home.html')); //SSR.compileTemplate('home', Assets.getText('/imports/ui/Home.html'));
// //
//SSR.compileTemplate('currentBoard', Assets.getText('/imports/ui/CurrentBoard.html')); //SSR.compileTemplate('currentBoard', Assets.getText('/imports/ui/CurrentBoard.html'));
Template.CurrentBoard.helpers({ //Template.CurrentBoard.helpers({
currentBoardHTML: () => { // currentBoardHTML: () => {
//Template.instance().data // //Template.instance().data
let doc = Meteor.collections.Pages.findOne({name: 'Board'}); // let doc = Meteor.collections.Pages.findOne({name: 'Board'});
//
return doc === undefined ? "" : doc.html; // return doc === undefined ? "" : doc.html;
} // }
}); //});
//
SeoRouter.route('/', (params, request, response) => { //SeoRouter.route('/', (params, request, response) => {
let html = SSR.render('public', {content: 'home'}); // let html = SSR.render('public', {content: 'home'});
//
response.setHeader('Content-Type', 'text/html;charset=utf-8'); // response.setHeader('Content-Type', 'text/html;charset=utf-8');
response.end(html); // response.end(html);
}); //});
//
SeoRouter.route('/CurrentBoard', (params, request, response) => { //SeoRouter.route('/CurrentBoard', (params, request, response) => {
let html = SSR.render('public', {content: 'currentBoard'}); // let html = SSR.render('public', {content: 'currentBoard'});
//
response.setHeader('Content-Type', 'text/html;charset=utf-8'); // response.setHeader('Content-Type', 'text/html;charset=utf-8');
response.end(html); // response.end(html);
}); //});