Merge branch 'BerkeleyTrue-fix/theme-flash' into staging
This commit is contained in:
@ -64,7 +64,6 @@ body.top-and-bottom-margins {
|
||||
}
|
||||
|
||||
body.no-top-and-bottom-margins {
|
||||
display: none;
|
||||
margin: 75px 20px 0px 20px;
|
||||
}
|
||||
|
||||
|
@ -165,6 +165,7 @@ main.setMapShare = function setMapShare(id) {
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
const { Observable } = window.Rx;
|
||||
var CSRF_HEADER = 'X-CSRF-Token';
|
||||
|
||||
var setCSRFToken = function(securityToken) {
|
||||
@ -548,51 +549,68 @@ $(document).ready(function() {
|
||||
// keyboard shortcuts: open map
|
||||
window.Mousetrap.bind('g m', toggleMap);
|
||||
|
||||
// Night Mode
|
||||
function changeMode() {
|
||||
var newValue = false;
|
||||
try {
|
||||
newValue = !JSON.parse(localStorage.getItem('nightMode'));
|
||||
} catch (e) {
|
||||
console.error('Error parsing value form local storage:', 'nightMode', e);
|
||||
}
|
||||
localStorage.setItem('nightMode', String(newValue));
|
||||
toggleNightMode(newValue);
|
||||
function addAlert(message = '', type = 'alert-info') {
|
||||
return $('.flashMessage').append($(`
|
||||
<div class='alert ${type}'>
|
||||
<button class='close' type='button', data-dismiss='alert'>
|
||||
<span class='ion-close-circled' />
|
||||
</Button>
|
||||
<div>${message}</div>
|
||||
</div>
|
||||
`));
|
||||
}
|
||||
|
||||
function toggleNightMode(nightModeEnabled) {
|
||||
var iframe = document.getElementById('map-aside-frame');
|
||||
if (iframe) {
|
||||
iframe.src = iframe.src;
|
||||
function toggleNightMode() {
|
||||
if (!main.userId) {
|
||||
return addAlert('You must be logged in to use our themes.');
|
||||
}
|
||||
var body = $('body');
|
||||
body.hide();
|
||||
if (nightModeEnabled) {
|
||||
body.addClass('night');
|
||||
const iframe$ = document.getElementById('map-aside-frame');
|
||||
const body$ = $('body');
|
||||
if (iframe$) {
|
||||
iframe$.src = iframe$.src;
|
||||
}
|
||||
body$.hide();
|
||||
let updateThemeTo;
|
||||
if (body$.hasClass('night')) {
|
||||
body$.removeClass('night');
|
||||
updateThemeTo = 'default';
|
||||
} else {
|
||||
body.removeClass('night');
|
||||
body$.addClass('night');
|
||||
updateThemeTo = 'night';
|
||||
}
|
||||
body.fadeIn('100');
|
||||
}
|
||||
|
||||
if (typeof localStorage.getItem('nightMode') !== 'undefined') {
|
||||
var oldVal = false;
|
||||
body$.fadeIn('100');
|
||||
const options = {
|
||||
url: `/api/users/${main.userId}/update-theme`,
|
||||
type: 'POST',
|
||||
data: { theme: updateThemeTo },
|
||||
dataType: 'json'
|
||||
};
|
||||
return $.ajax(options)
|
||||
.success(() => console.log('theme updated successfully'))
|
||||
.fail(err => {
|
||||
let message;
|
||||
try {
|
||||
oldVal = JSON.parse(localStorage.getItem('nightMode'));
|
||||
} catch (e) {
|
||||
console.error('Error parsing value form local storage:', 'nightMode', e);
|
||||
message = JSON.parse(err.responseText).error.message;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
toggleNightMode(oldVal);
|
||||
$('.nightMode-btn').on('click', function() {
|
||||
changeMode();
|
||||
if (!message) {
|
||||
return null;
|
||||
}
|
||||
return addAlert(message);
|
||||
});
|
||||
} else {
|
||||
localStorage.setItem('nightMode', 'false');
|
||||
toggleNightMode('false');
|
||||
}
|
||||
|
||||
Observable.merge(
|
||||
Observable.fromEvent($('#night-mode'), 'click'),
|
||||
Observable.create(observer => {
|
||||
window.Mousetrap.bind('g t n', () => observer.onNext());
|
||||
})
|
||||
)
|
||||
.debounce(500)
|
||||
.subscribe(toggleNightMode, err => console.error(err));
|
||||
|
||||
// Hot Keys
|
||||
window.Mousetrap.bind('g t n', changeMode);
|
||||
window.Mousetrap.bind('g n n', () => {
|
||||
// Next Challenge
|
||||
window.location = '/challenges/next-challenge';
|
||||
|
@ -486,6 +486,91 @@ module.exports = function(User) {
|
||||
}
|
||||
);
|
||||
|
||||
User.prototype.updateEmail = function updateEmail(email) {
|
||||
if (this.email && this.email === email) {
|
||||
return Promise.reject(new Error(
|
||||
`${email} is already associated with this account.`
|
||||
));
|
||||
}
|
||||
return User.doesExist(null, email)
|
||||
.then(exists => {
|
||||
if (exists) {
|
||||
return Promise.reject(
|
||||
new Error(`${email} is already associated with another account.`)
|
||||
);
|
||||
}
|
||||
return this.update$({ email }).toPromise();
|
||||
});
|
||||
};
|
||||
|
||||
User.remoteMethod(
|
||||
'updateEmail',
|
||||
{
|
||||
isStatic: false,
|
||||
description: 'updates the email of the user object',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'email',
|
||||
type: 'string',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
returns: [
|
||||
{
|
||||
arg: 'status',
|
||||
type: 'object'
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: '/update-email',
|
||||
verb: 'POST'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
User.themes = {
|
||||
night: true,
|
||||
default: true
|
||||
};
|
||||
User.prototype.updateTheme = function updateTheme(theme) {
|
||||
if (!this.constructor.themes[theme]) {
|
||||
const err = new Error(
|
||||
'Theme is not valid.'
|
||||
);
|
||||
err.messageType = 'info';
|
||||
err.userMessage = err.message;
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return this.update$({ theme })
|
||||
.map({ updatedTo: theme })
|
||||
.toPromise();
|
||||
};
|
||||
|
||||
User.remoteMethod(
|
||||
'updateTheme',
|
||||
{
|
||||
isStatic: false,
|
||||
description: 'updates the users chosen theme',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'theme',
|
||||
type: 'string',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
returns: [
|
||||
{
|
||||
arg: 'status',
|
||||
type: 'object'
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: '/update-theme',
|
||||
verb: 'POST'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// user.updateTo$(updateData: Object) => Observable[Number]
|
||||
User.prototype.update$ = function update$(updateData) {
|
||||
const id = this.getId();
|
||||
|
@ -188,6 +188,10 @@
|
||||
},
|
||||
"timezone": {
|
||||
"type": "string"
|
||||
},
|
||||
"theme": {
|
||||
"type": "string",
|
||||
"default": "default"
|
||||
}
|
||||
},
|
||||
"validations": [],
|
||||
@ -242,6 +246,13 @@
|
||||
"principalId": "$owner",
|
||||
"permission": "ALLOW",
|
||||
"property": "updateEmail"
|
||||
},
|
||||
{
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$owner",
|
||||
"permission": "ALLOW",
|
||||
"property": "updateTheme"
|
||||
}
|
||||
],
|
||||
"methods": []
|
||||
|
@ -6,6 +6,10 @@ export default function globalLocals() {
|
||||
if (req.csrfToken) {
|
||||
res.expose({ token: res.locals._csrf }, 'csrf');
|
||||
}
|
||||
res.locals.theme = req.user && req.user.theme ||
|
||||
req.cookies.theme ||
|
||||
'default';
|
||||
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ export function ifNoUserRedirectTo(url, message, type = 'errors') {
|
||||
}
|
||||
|
||||
req.flash(type, {
|
||||
msg: message || `You must be signed to go to ${path}`
|
||||
msg: message || `You must be signed in to access ${path}`
|
||||
});
|
||||
|
||||
return res.redirect(url);
|
||||
|
@ -5,7 +5,7 @@ block content
|
||||
h2.text-center Actions
|
||||
.row
|
||||
.col-xs-12
|
||||
a.btn.btn-lg.btn-block.btn-primary.btn-link-social(class = "nightMode-btn") Night Mode
|
||||
a#night-mode.btn.btn-lg.btn-block.btn-primary.btn-link-social Night Mode
|
||||
.row
|
||||
.col-xs-12
|
||||
if (!user.isGithubCool)
|
||||
|
@ -8,7 +8,7 @@ html(lang='en')
|
||||
include partials/scripts
|
||||
block content
|
||||
else
|
||||
body.no-top-and-bottom-margins
|
||||
body.no-top-and-bottom-margins(class=theme !== 'default' ? theme : '')
|
||||
include partials/scripts
|
||||
include partials/navbar
|
||||
include partials/flash
|
||||
|
@ -122,3 +122,4 @@ block content
|
||||
p.challenge-title.disabled.text-primary.ion-locked.padded-ionic-icon.negative-15(name="Mock Interview #2") Mock Interview #2
|
||||
p.challenge-title.disabled.text-primary.ion-locked.padded-ionic-icon.negative-15(name="Mock Interview #3") Mock Interview #3
|
||||
.spacer
|
||||
include ../partials/flash
|
||||
|
@ -1,6 +1,6 @@
|
||||
.container
|
||||
.row.flashMessage.negative-30
|
||||
.col-xs-12
|
||||
.col-xs-12.col-sm-8.col-sm-offset-2.col-md-6.col-md-offset-3
|
||||
if (messages.errors || messages.error)
|
||||
.alert.alert-danger.fade.in
|
||||
button.close(type='button', data-dismiss='alert')
|
||||
|
@ -7,5 +7,11 @@ script.
|
||||
ga('require', 'displayfeatures');
|
||||
ga('send', 'pageview');
|
||||
// Leave the below lines alone!
|
||||
script.
|
||||
(function(global) {
|
||||
global.main = global.main || {};
|
||||
global.main.isLoggedIn = !{JSON.stringify(!!user)};
|
||||
global.main.userId = !{JSON.stringify(user && user.id || false)};
|
||||
}(window))
|
||||
script(src=rev('/js', 'vendor-main.js'))
|
||||
script(src=rev('/js', 'main.js'))
|
||||
|
Reference in New Issue
Block a user