assorted home page fixes/improvements
* link to home page from other static pages * home notice * moved to the top of the home page * configured via server API instead of application_config.js * WIP admin panel UI * more debugging info for unsupported decrees * lint compliance probably
This commit is contained in:
parent
5fd4b7a3cb
commit
a2731c44b0
8 changed files with 110 additions and 33 deletions
|
@ -74,6 +74,7 @@ define([
|
||||||
return select;
|
return select;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* // XXX remove ?
|
||||||
var footerCol = function (title, L, n) {
|
var footerCol = function (title, L, n) {
|
||||||
n = n || 3;
|
n = n || 3;
|
||||||
return h('div.col-sm-' + n, [
|
return h('div.col-sm-' + n, [
|
||||||
|
@ -87,6 +88,7 @@ define([
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
var footLink = function (ref, loc, text, icon) {
|
var footLink = function (ref, loc, text, icon) {
|
||||||
if (!ref) { return; }
|
if (!ref) { return; }
|
||||||
|
@ -243,6 +245,11 @@ define([
|
||||||
// $('#menuCollapse').slideDown();
|
// $('#menuCollapse').slideDown();
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
var isHome = ['/', '/index.html'].includes(window.location.pathname);
|
||||||
|
var homeLink = h('a.nav-item.nav-link' /* .navbar-brand */, { href: '/index.html' }, [
|
||||||
|
'Home page', // XXX replace with image or whatever
|
||||||
|
]);
|
||||||
|
|
||||||
return h('nav.navbar.navbar-expand-lg',
|
return h('nav.navbar.navbar-expand-lg',
|
||||||
// XXX DB add link back to index.html on other pages
|
// XXX DB add link back to index.html on other pages
|
||||||
// h('a.navbar-brand', { href: '/index.html'}, [
|
// h('a.navbar-brand', { href: '/index.html'}, [
|
||||||
|
@ -255,8 +262,7 @@ define([
|
||||||
// button, // XXX collapse button
|
// button, // XXX collapse button
|
||||||
// add .collapse.navbar-collapse.justify-content-end#menuCollapse to div below to enable collapse button
|
// add .collapse.navbar-collapse.justify-content-end#menuCollapse to div below to enable collapse button
|
||||||
[
|
[
|
||||||
// XXX remove about page
|
!isHome? homeLink: undefined,
|
||||||
// h('a.nav-item.nav-link', { href: '/what-is-cryptpad.html'}, Msg.about),
|
|
||||||
h('a.nav-item.nav-link', { href: '/features.html'}, Pages.areSubscriptionsAllowed()? Msg.pricing: Msg.features),
|
h('a.nav-item.nav-link', { href: '/features.html'}, Pages.areSubscriptionsAllowed()? Msg.pricing: Msg.features),
|
||||||
h('a.nav-item.nav-link', { href: 'https://docs.cryptpad.fr'},
|
h('a.nav-item.nav-link', { href: 'https://docs.cryptpad.fr'},
|
||||||
[h('i.fa.fa-book', {'aria-hidden':'true'}),Msg.docs_link]),
|
[h('i.fa.fa-book', {'aria-hidden':'true'}),Msg.docs_link]),
|
||||||
|
|
|
@ -109,7 +109,8 @@ define([
|
||||||
var fastLink = k => pageLink(Pages.customURLs[k], k);
|
var fastLink = k => pageLink(Pages.customURLs[k], k);
|
||||||
|
|
||||||
// XXX DB
|
// XXX DB
|
||||||
Msg.terms = "Terms of Service";
|
Msg.terms = Msg.footer_tos; //"Terms of Service"; // XXX
|
||||||
|
Msg.home_location = "Encrypted data is hosted in {0}"; // XXX
|
||||||
|
|
||||||
// XXX DB: this may be wrong, pasted over form pages.js
|
// XXX DB: this may be wrong, pasted over form pages.js
|
||||||
var imprintLink = fastLink('imprint');
|
var imprintLink = fastLink('imprint');
|
||||||
|
@ -121,10 +122,9 @@ define([
|
||||||
If the text is the key for the translation system then then the most appropriate translated text
|
If the text is the key for the translation system then then the most appropriate translated text
|
||||||
will be displayed. Otherwise, the direct text will be included as HTML.
|
will be displayed. Otherwise, the direct text will be included as HTML.
|
||||||
*/
|
*/
|
||||||
if (AppConfig.homeNotice) {
|
if (Pages.Instance.notice) {
|
||||||
notice = h('div.alert.alert-info', Pages.setHTML(h('span'), [
|
console.log(Pages.Instance.notice);
|
||||||
Msg[AppConfig.homeNotice] || AppConfig.homeNotice
|
notice = h('div.alert.alert-info', Pages.setHTML(h('span'), Pages.Instance.notice));
|
||||||
]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// instance title
|
// instance title
|
||||||
|
@ -134,15 +134,13 @@ define([
|
||||||
|
|
||||||
// instance location
|
// instance location
|
||||||
var locationBlock;
|
var locationBlock;
|
||||||
|
|
||||||
if (Pages.Instance.location) {
|
if (Pages.Instance.location) {
|
||||||
locationBlock = h('div.cp-instance-location', [
|
locationBlock = h('div.cp-instance-location', [
|
||||||
h('i.fa.fa-map-pin', {'aria-hidden': 'true'}),
|
h('i.fa.fa-map-pin', {'aria-hidden': 'true'}),
|
||||||
'Encrypted data is hosted in: ', // XXX translate
|
Msg._getKey('home_location', [ Pages.Instance.location ]),
|
||||||
Pages.Instance.location,
|
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
locationBlock = h('div', h('br')); // XXX
|
locationBlock = h('div', h('br'));
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg.home_morestorage = 'For more storage space, and to support the project:'; // XXX
|
Msg.home_morestorage = 'For more storage space, and to support the project:'; // XXX
|
||||||
|
@ -165,6 +163,7 @@ define([
|
||||||
return [
|
return [
|
||||||
h('div#cp-main', [
|
h('div#cp-main', [
|
||||||
Pages.infopageTopbar(),
|
Pages.infopageTopbar(),
|
||||||
|
notice,
|
||||||
h('div.container.cp-container', [
|
h('div.container.cp-container', [
|
||||||
h('div.row.cp-home-hero', [
|
h('div.row.cp-home-hero', [
|
||||||
h('div.cp-title.col-md-6', [
|
h('div.cp-title.col-md-6', [
|
||||||
|
@ -174,7 +173,7 @@ define([
|
||||||
alt: ''
|
alt: ''
|
||||||
}),
|
}),
|
||||||
instanceTitle,
|
instanceTitle,
|
||||||
UI.setHTML(h('span.tag-line'), Pages.Instance.description),
|
Pages.setHTML(h('span.tag-line'), Pages.Instance.description),
|
||||||
locationBlock,
|
locationBlock,
|
||||||
termsLink,
|
termsLink,
|
||||||
privacyLink,
|
privacyLink,
|
||||||
|
@ -199,7 +198,6 @@ define([
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
notice
|
|
||||||
]),
|
]),
|
||||||
Pages.infopageFooter(),
|
Pages.infopageFooter(),
|
||||||
]),
|
]),
|
||||||
|
|
|
@ -359,6 +359,7 @@ var instanceStatus = function (Env, Server, cb) {
|
||||||
instanceDescription: Env.instanceDescription,
|
instanceDescription: Env.instanceDescription,
|
||||||
instanceJurisdiction: Env.instanceJurisdiction,
|
instanceJurisdiction: Env.instanceJurisdiction,
|
||||||
instanceName: Env.instanceName,
|
instanceName: Env.instanceName,
|
||||||
|
instanceNotice: Env.instanceNotice,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -196,14 +196,45 @@ commands.SET_SUPPORT_MAILBOX = makeGenericSetter('supportMailbox', function (arg
|
||||||
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_PURPOSE', ["development"]]], console.log)
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_PURPOSE', ["development"]]], console.log)
|
||||||
commands.SET_INSTANCE_PURPOSE = makeGenericSetter('instancePurpose', args_isString);
|
commands.SET_INSTANCE_PURPOSE = makeGenericSetter('instancePurpose', args_isString);
|
||||||
|
|
||||||
|
var makeTranslation = function (attr) {
|
||||||
|
return function (Env, args) {
|
||||||
|
if (!Array.isArray(args)) { throw new Error("INVALID_ARGS"); }
|
||||||
|
var value = args[0];
|
||||||
|
var state = Env[attr];
|
||||||
|
|
||||||
|
if (typeof(value) === 'string') {
|
||||||
|
if (state.default === value) { return false; }
|
||||||
|
state.default = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (value && typeof(value) === 'object') {
|
||||||
|
var changed = false;
|
||||||
|
Object.keys(value).forEach(function (lang) {
|
||||||
|
if (state[lang] === value[lang]) { return; }
|
||||||
|
state[lang] = value[lang];
|
||||||
|
changed = true;
|
||||||
|
});
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_JURISDICTION', ['France']]], console.log)
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_JURISDICTION', ['France']]], console.log)
|
||||||
commands.SET_INSTANCE_JURISDICTION = makeGenericSetter('instanceJurisdiction', args_isString);
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_JURISDICTION', [{default:'France',de:'Frankreich'}]]], console.log)
|
||||||
|
commands.SET_INSTANCE_JURISDICTION = makeTranslation('instanceJurisdiction');
|
||||||
|
|
||||||
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_NAME', ['My Personal CryptPad']]], console.log)
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_NAME', ['My Personal CryptPad']]], console.log)
|
||||||
commands.SET_INSTANCE_NAME = makeGenericSetter('instanceName', args_isString);
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_NAME', [{default:'My Personal CryptPad', fr: "Mon CryptPad personnel"}]]], console.log)
|
||||||
|
commands.SET_INSTANCE_NAME = makeTranslation('instanceName');
|
||||||
|
|
||||||
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_DESCRIPTION', ['A personal instance, hosted for me and nobody else']]], console.log)
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_DESCRIPTION', ['A personal instance, hosted for me and nobody else']]], console.log)
|
||||||
commands.SET_INSTANCE_DESCRIPTION = makeGenericSetter('instanceDescription', args_isString);
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_DESCRIPTION', [{default:'A personal server, not intended for public usage', fr: 'Un serveur personnel, non destiné à un usage public'}]]], console.log)
|
||||||
|
commands.SET_INSTANCE_DESCRIPTION = makeTranslation('instanceDescription'); // XXX support translation
|
||||||
|
|
||||||
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_NOTICE', ['Our hosting costs have increased during the pandemic. Please consider donating!']]], console.log)
|
||||||
|
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_NOTICE', [{default:'Our hosting costs have increased during the pandemic. Please consider donating!',fr:'Nos coûts d'hébergement ont augmenté pendant la pandémie. Veuillez envisager de faire un don !']]], console.log)
|
||||||
|
commands.SET_INSTANCE_NOTICE = makeTranslation('instanceNotice');
|
||||||
|
|
||||||
// Maintenance: Empty string or an object with a start and end time
|
// Maintenance: Empty string or an object with a start and end time
|
||||||
var isNumber = function (value) {
|
var isNumber = function (value) {
|
||||||
|
@ -370,7 +401,7 @@ Decrees.load = function (Env, _cb) {
|
||||||
try {
|
try {
|
||||||
handler(void 0, JSON.parse(text));
|
handler(void 0, JSON.parse(text));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
handler(err);
|
handler(err, text);
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
|
|
|
@ -192,9 +192,10 @@ module.exports.create = function (config) {
|
||||||
provideAggregateStatistics: false,
|
provideAggregateStatistics: false,
|
||||||
updateAvailable: undefined,
|
updateAvailable: undefined,
|
||||||
|
|
||||||
instanceName: '',
|
instanceName: {},
|
||||||
instanceDescription: '',
|
instanceDescription: {},
|
||||||
instanceJurisdiction: '',
|
instanceJurisdiction: {},
|
||||||
|
instanceNotice: {},
|
||||||
|
|
||||||
myDomain: config.myDomain,
|
myDomain: config.myDomain,
|
||||||
mySubdomain: config.mySubdomain, // only exists for the accounts integration
|
mySubdomain: config.mySubdomain, // only exists for the accounts integration
|
||||||
|
|
13
server.js
13
server.js
|
@ -270,15 +270,10 @@ var define = function (obj) {
|
||||||
app.get('/api/instance', function (req, res) { // XXX use caching?
|
app.get('/api/instance', function (req, res) { // XXX use caching?
|
||||||
res.setHeader('Content-Type', 'text/javascript');
|
res.setHeader('Content-Type', 'text/javascript');
|
||||||
res.send(define({
|
res.send(define({
|
||||||
name: {
|
name: Env.instanceName,
|
||||||
default: Env.instanceName,
|
description: Env.instanceDescription,
|
||||||
},
|
location: Env.instanceJurisdiction,
|
||||||
description: {
|
notice: Env.instanceNotice,
|
||||||
default: Env.instanceDescription,
|
|
||||||
},
|
|
||||||
location: {
|
|
||||||
default: Env.instanceJurisdiction,
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
}
|
}
|
||||||
.cp-admin-setlimit-form,
|
.cp-admin-setlimit-form,
|
||||||
.cp-admin-setjurisdiction-form,
|
.cp-admin-setjurisdiction-form,
|
||||||
|
.cp-admin-setnotice-form, // XXX not great
|
||||||
.cp-admin-setdescription-form {
|
.cp-admin-setdescription-form {
|
||||||
+ button {
|
+ button {
|
||||||
margin-top: 5px !important;
|
margin-top: 5px !important;
|
||||||
|
|
|
@ -62,6 +62,7 @@ define([
|
||||||
'cp-admin-name',
|
'cp-admin-name',
|
||||||
'cp-admin-description',
|
'cp-admin-description',
|
||||||
'cp-admin-jurisdiction',
|
'cp-admin-jurisdiction',
|
||||||
|
'cp-admin-notice',
|
||||||
],
|
],
|
||||||
'quota': [ // Msg.admin_cat_quota
|
'quota': [ // Msg.admin_cat_quota
|
||||||
'cp-admin-defaultlimit',
|
'cp-admin-defaultlimit',
|
||||||
|
@ -429,7 +430,7 @@ define([
|
||||||
return $div;
|
return $div;
|
||||||
};
|
};
|
||||||
|
|
||||||
create['jurisdiction'] = function () {
|
create['jurisdiction'] = function () { // XXX make translateable
|
||||||
var key = 'jurisdiction';
|
var key = 'jurisdiction';
|
||||||
var $div = makeBlock(key, true); // Msg.admin_jurisdictionHint, Msg.admin_jurisdictionTitle, Msg.admin_jurisdictionButton
|
var $div = makeBlock(key, true); // Msg.admin_jurisdictionHint, Msg.admin_jurisdictionTitle, Msg.admin_jurisdictionButton
|
||||||
var $button = $div.find('button').addClass('cp-listing-action').text(Messages.settings_save);
|
var $button = $div.find('button').addClass('cp-listing-action').text(Messages.settings_save);
|
||||||
|
@ -468,6 +469,49 @@ define([
|
||||||
return $div;
|
return $div;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Messages.admin_noticeTitle = "admin_noticeTitle";
|
||||||
|
Messages.admin_noticeHint = "admin_noticeHint";
|
||||||
|
//Messages.admin_noticeButton = "admin_noticeButton";
|
||||||
|
|
||||||
|
create['notice'] = function () { // XXX add input, make translateable
|
||||||
|
var key = 'notice';
|
||||||
|
var $div = makeBlock(key, true);
|
||||||
|
|
||||||
|
var $button = $div.find('button').addClass('cp-listing-action').text(Messages.settings_save);
|
||||||
|
|
||||||
|
var input = h('input.cp-listing-info', {
|
||||||
|
type: 'text',
|
||||||
|
value: APP.instanceStatus.instanceNotice || '',
|
||||||
|
placeholder: Messages.owner_unknownUser || '',
|
||||||
|
});
|
||||||
|
var $input = $(input);
|
||||||
|
var innerDiv = h('div.cp-admin-setnotice-form', input);
|
||||||
|
var spinner = UI.makeSpinner($(innerDiv));
|
||||||
|
|
||||||
|
$button.click(function () {
|
||||||
|
spinner.spin();
|
||||||
|
$button.attr('disabled', 'disabled');
|
||||||
|
sFrameChan.query('Q_ADMIN_RPC', {
|
||||||
|
cmd: 'ADMIN_DECREE',
|
||||||
|
data: ['SET_INSTANCE_NOTICE', [$input.val().trim()]]
|
||||||
|
}, function (e, response) {
|
||||||
|
$button.removeAttr('disabled');
|
||||||
|
spinner.hide();
|
||||||
|
if (e || response.error) {
|
||||||
|
UI.warn(Messages.error);
|
||||||
|
$input.val('');
|
||||||
|
console.error(e, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UI.log(Messages._getKey('ui_saved', [Messages.admin_noticeTitle]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$button.before(innerDiv);
|
||||||
|
|
||||||
|
return $div;
|
||||||
|
};
|
||||||
|
|
||||||
create['instance-info-notice'] = function () {
|
create['instance-info-notice'] = function () {
|
||||||
return $(h('div.cp-admin-instance-info-notice.cp-sidebarlayout-element',
|
return $(h('div.cp-admin-instance-info-notice.cp-sidebarlayout-element',
|
||||||
h('div.alert.alert-info.cp-admin-bigger-alert', [
|
h('div.alert.alert-info.cp-admin-bigger-alert', [
|
||||||
|
@ -478,7 +522,7 @@ define([
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
create['name'] = function () {
|
create['name'] = function () { // XXX make translateable
|
||||||
var key = 'name';
|
var key = 'name';
|
||||||
var $div = makeBlock(key, true);
|
var $div = makeBlock(key, true);
|
||||||
// Msg.admin_nameHint, Msg.admin_nameTitle, Msg.admin_nameButton
|
// Msg.admin_nameHint, Msg.admin_nameTitle, Msg.admin_nameButton
|
||||||
|
@ -519,7 +563,7 @@ define([
|
||||||
return $div;
|
return $div;
|
||||||
};
|
};
|
||||||
|
|
||||||
create['description'] = function () {
|
create['description'] = function () { // XXX support translation
|
||||||
var key = 'description';
|
var key = 'description';
|
||||||
var $div = makeBlock(key, true); // Msg.admin_descriptionHint
|
var $div = makeBlock(key, true); // Msg.admin_descriptionHint
|
||||||
|
|
||||||
|
@ -1419,7 +1463,7 @@ define([
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
create['broadcast'] = function () {
|
create['broadcast'] = function () { // XXX
|
||||||
var key = 'broadcast';
|
var key = 'broadcast';
|
||||||
var $div = makeBlock(key); // Msg.admin_broadcastHint, admin_broadcastTitle
|
var $div = makeBlock(key); // Msg.admin_broadcastHint, admin_broadcastTitle
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue