client/settings: add accountless settings
This commit is contained in:
parent
f5272bb5f3
commit
21c15f4cb9
|
@ -25,6 +25,13 @@ form .input li:first-child {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
form .hint {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
margin-bottom: 0;
|
||||||
|
color: var(--inactive-link-color);
|
||||||
|
font-size: 80%;
|
||||||
|
line-height: 120%;
|
||||||
|
}
|
||||||
|
|
||||||
form.tabular ul {
|
form.tabular ul {
|
||||||
display: table;
|
display: table;
|
||||||
|
|
|
@ -130,6 +130,7 @@ nav.text-nav ul li.active a {
|
||||||
#top-nav ul li[data-name=register],
|
#top-nav ul li[data-name=register],
|
||||||
#top-nav ul li[data-name=login],
|
#top-nav ul li[data-name=login],
|
||||||
#top-nav ul li[data-name=logout],
|
#top-nav ul li[data-name=logout],
|
||||||
|
#top-nav ul li[data-name=settings],
|
||||||
#top-nav ul li[data-name=help] {
|
#top-nav ul li[data-name=help] {
|
||||||
float: none;
|
float: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,14 +26,6 @@
|
||||||
#user-registration .info p:first-child {
|
#user-registration .info p:first-child {
|
||||||
margin: 0 0 0.5em 0;
|
margin: 0 0 0.5em 0;
|
||||||
}
|
}
|
||||||
#user .hint,
|
|
||||||
#user-registration .hint {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
margin-bottom: 0;
|
|
||||||
color: var(--inactive-link-color);
|
|
||||||
font-size: 80%;
|
|
||||||
line-height: 120%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#login .buttons a {
|
#login .buttons a {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<div class='content-wrapper' id='settings'>
|
||||||
|
<form>
|
||||||
|
<strong>Browsing settings</strong>
|
||||||
|
<p>These settings are saved to the browser's local storage and are not coupled to the user account, so they don't apply to other devices or browsers alike.</p>
|
||||||
|
<div class='input'>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
{{checkbox text='Endless scroll' id='endless-scroll' name='endless-scroll' checked=this.browsingSettings.endlessScroll}}
|
||||||
|
<p class='hint'>Rather than using a paged navigation, smoothly scroll through the content.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class='messages'></div>
|
||||||
|
<div class='buttons'>
|
||||||
|
<input type='submit' value='Save settings'/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -0,0 +1,53 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const page = require('page');
|
||||||
|
const events = require('../events.js');
|
||||||
|
const topNavController = require('../controllers/top_nav_controller.js');
|
||||||
|
const SettingsView = require('../views/settings_view.js');
|
||||||
|
|
||||||
|
class SettingsController {
|
||||||
|
constructor() {
|
||||||
|
this.settingsView = new SettingsView();
|
||||||
|
}
|
||||||
|
|
||||||
|
registerRoutes() {
|
||||||
|
page('/settings', (ctx, next) => { this.settingsRoute(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
settingsRoute() {
|
||||||
|
topNavController.activate('settings');
|
||||||
|
this.settingsView.render({
|
||||||
|
getSettings: () => this.getSettings(),
|
||||||
|
saveSettings: newSettings => this.saveSettings(newSettings),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
saveSettings(browsingSettings) {
|
||||||
|
localStorage.setItem('settings', JSON.stringify(browsingSettings));
|
||||||
|
events.notify(events.Success, 'Settings saved');
|
||||||
|
}
|
||||||
|
|
||||||
|
getSettings(settings) {
|
||||||
|
const defaultSettings = {
|
||||||
|
endlessScroll: false,
|
||||||
|
};
|
||||||
|
let ret = {};
|
||||||
|
let userSettings = localStorage.getItem('settings');
|
||||||
|
if (userSettings) {
|
||||||
|
userSettings = JSON.parse(userSettings);
|
||||||
|
}
|
||||||
|
if (!userSettings) {
|
||||||
|
userSettings = {};
|
||||||
|
}
|
||||||
|
for (let key of Object.keys(defaultSettings)) {
|
||||||
|
if (key in userSettings) {
|
||||||
|
ret[key] = userSettings[key];
|
||||||
|
} else {
|
||||||
|
ret[key] = defaultSettings[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = new SettingsController();
|
|
@ -31,6 +31,8 @@ class TopNavController {
|
||||||
'login': new NavigationItem('L', 'Log in', '/login'),
|
'login': new NavigationItem('L', 'Log in', '/login'),
|
||||||
'logout': new NavigationItem('O', 'Logout', '/logout'),
|
'logout': new NavigationItem('O', 'Logout', '/logout'),
|
||||||
'help': new NavigationItem('E', 'Help', '/help'),
|
'help': new NavigationItem('E', 'Help', '/help'),
|
||||||
|
'settings': new NavigationItem(
|
||||||
|
null, '<i class=\'fa fa-cog\'></i>', '/settings'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const rerender = () => {
|
const rerender = () => {
|
||||||
|
|
|
@ -10,6 +10,7 @@ controllers.push(require('./controllers/help_controller.js'));
|
||||||
controllers.push(require('./controllers/comments_controller.js'));
|
controllers.push(require('./controllers/comments_controller.js'));
|
||||||
controllers.push(require('./controllers/history_controller.js'));
|
controllers.push(require('./controllers/history_controller.js'));
|
||||||
controllers.push(require('./controllers/tags_controller.js'));
|
controllers.push(require('./controllers/tags_controller.js'));
|
||||||
|
controllers.push(require('./controllers/settings_controller.js'));
|
||||||
|
|
||||||
controllers.push(require('./controllers/home_controller.js'));
|
controllers.push(require('./controllers/home_controller.js'));
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,8 @@ handlebars.registerHelper('checkbox', function(options) {
|
||||||
name: options.hash.name,
|
name: options.hash.name,
|
||||||
value: options.hash.value,
|
value: options.hash.value,
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
|
checked: options.hash.checked !== undefined ?
|
||||||
|
options.hash.checked : false,
|
||||||
required: options.hash.required,
|
required: options.hash.required,
|
||||||
}),
|
}),
|
||||||
views.makeNonVoidElement('label', {
|
views.makeNonVoidElement('label', {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const views = require('../util/views.js');
|
||||||
|
|
||||||
|
class SettingsView {
|
||||||
|
constructor() {
|
||||||
|
this.template = views.getTemplate('settings');
|
||||||
|
}
|
||||||
|
|
||||||
|
render(ctx) {
|
||||||
|
const target = document.getElementById('content-holder');
|
||||||
|
const source = this.template({browsingSettings: ctx.getSettings()});
|
||||||
|
|
||||||
|
const form = source.querySelector('form');
|
||||||
|
views.decorateValidator(form);
|
||||||
|
|
||||||
|
form.addEventListener('submit', e => {
|
||||||
|
e.preventDefault();
|
||||||
|
views.clearMessages(source);
|
||||||
|
ctx.saveSettings({
|
||||||
|
endlessScroll: form.querySelector('#endless-scroll').checked,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
views.listenToMessages(target);
|
||||||
|
views.showView(target, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SettingsView;
|
Loading…
Reference in New Issue