app config screen

This commit is contained in:
zuzanna-maria 2024-05-21 00:13:55 +01:00
parent 2d4f0daa42
commit 987492ef3c
3 changed files with 407 additions and 96 deletions

View File

@ -0,0 +1,80 @@
define([
'jquery',
'/common/toolbar.js',
'/components/nthen/index.js',
'/common/sframe-common.js',
'/common/common-interface.js',
'/common/common-ui-elements.js',
'/common/common-util.js',
'/common/common-hash.js',
'/common/inner/sidebar-layout.js',
'/customize/messages.js',
'/common/common-signing-keys.js',
'/common/hyperscript.js',
'/common/clipboard.js',
'json.sortify',
'/customize/application_config.js',
'/api/config',
'/api/instance',
'/lib/datepicker/flatpickr.js',
'configscreen.js',
'/common/hyperscript.js',
'css!/lib/datepicker/flatpickr.min.css',
'css!/components/bootstrap/dist/css/bootstrap.min.css',
'css!/components/components-font-awesome/css/font-awesome.min.css',
'less!/admin/app-admin.less',
], function(
$,
Toolbar,
nThen,
SFCommon,
UI,
UIElements,
Util,
Hash,
Sidebar,
Messages,
Keys,
h,
Clipboard,
Sortify,
AppConfig,
ApiConfig,
Instance,
Flatpickr,
ConfigScreen
) {
var AppConfigScreen = {}
AppConfigScreen.addConfigScreen = function (config) {
var LOADING = 'cp-loading';
config = config || {};
var loadingText = config.loadingText;
var todo = function () {
var $loading = $('#' + LOADING);
// Show the loading screen
$loading.css('display', '');
$loading.removeClass('cp-loading-hidden');
$loading.removeClass('cp-loading-transparent');
};
if ($('#' + LOADING).length) {
todo();
} else {
ConfigScreen();
todo();
}
$('html').toggleClass('cp-loading-noscroll', true);
// Remove the inner placeholder (iframe)
$('#placeholder').remove();
};
return AppConfigScreen
});

228
www/install/configscreen.js Normal file
View File

@ -0,0 +1,228 @@
// SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
//
// SPDX-License-Identifier: AGPL-3.0-or-later
// bg #e7e7e7
// blue #0087FF
// text #3F4141
define([
'jquery',
'/common/toolbar.js',
'/components/nthen/index.js',
'/common/sframe-common.js',
'/common/common-interface.js',
'/common/common-ui-elements.js',
'/common/common-util.js',
'/common/common-hash.js',
'/common/inner/sidebar-layout.js',
'/customize/messages.js',
'/common/common-signing-keys.js',
'/common/hyperscript.js',
'/common/clipboard.js',
'json.sortify',
'/customize/application_config.js',
'/api/config',
'/api/instance',
'/lib/datepicker/flatpickr.js',
'/common/hyperscript.js',
'css!/lib/datepicker/flatpickr.min.css',
'/customize/messages.js',
'/customize/messages.js',
'less!/customize/src/less2/include/loading.less'
], function ($,
Toolbar,
nThen,
SFCommon,
UI,
UIElements,
Util,
Hash,
Sidebar,
Messages,
Keys,
h,
Clipboard,
Sortify,
AppConfig,
ApiConfig,
Instance,
Flatpickr,
Messages) {
//XXX
Messages.admin_appSelection = 'App configuration saved'
Messages.admin_appsTitle = "Choose your applications"
Messages.admin_appsHint = "Choose which apps are available to users on your instance."
Messages.admin_cat_apps = "Apps"
var APP = window.APP = {};
var Nacl = window.nacl;
var common;
var sFrameChan;
var andThen = function (common, $container) {
const sidebar = Sidebar.create(common, 'admin', $container);
var categories = {
'apps': { // Msg.admin_cat_apps
icon: 'fa fa-cog',
content: [
'apps',
]
},
};
const blocks = sidebar.blocks;
const flushCache = (cb) => {
cb = cb || function () {};
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'FLUSH_CACHE',
}, cb);
};
sidebar.addItem('apps', function (cb) {
const grid = blocks.block([], 'cp-admin-customize-apps-grid');
const allApps = ['pad', 'code', 'kanban', 'slide', 'sheet', 'form', 'whiteboard', 'diagram'];
const availableApps = []
function select(app) {
if (availableApps.indexOf(app) === -1) {
availableApps.push(app);
$(`#${app}-block`).attr('class', 'active-app')
} else {
availableApps.splice(availableApps.indexOf(app), 1)
$(`#${app}-block`).attr('class', 'inactive-app')
}
}
allApps.forEach(app => {
let appBlock = h('div', {class: 'inactive-app', id: `${app}-block`}, app)
$(appBlock).addClass('cp-app-drive-element-grid')
$(grid).append(appBlock);
$(appBlock).on('click', () => select(app))
});
var save = blocks.activeButton('primary', '', Messages.settings_save, function (done) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['DISABLE_APPS', availableApps]
}, function (e, response) {
if (e || response.error) {
UI.warn(Messages.error);
$input.val('');
console.error(e, response);
done(false);
return;
}
flushCache();
done(true);
UI.log(Messages._getKey('ui_saved', [Messages.admin_appSelection]));
});
});
let form = blocks.form([
grid
], blocks.nav([save]));
cb(form);
});
sidebar.makeLeftside(categories);
};
var updateStatus = APP.updateStatus = function (cb) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'INSTANCE_STATUS',
}, function (e, data) {
if (e) { console.error(e); return void cb(e); }
if (!Array.isArray(data)) { return void cb('EINVAL'); }
APP.instanceStatus = data[0];
console.log("Status", APP.instanceStatus);
cb();
});
};
var createToolbar = function () {
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle', 'notifications'];
var configTb = {
displayed: displayed,
sfCommon: common,
$container: APP.$toolbar,
pageTitle: Messages.adminPage || 'Admin',
metadataMgr: common.getMetadataMgr(),
};
APP.toolbar = Toolbar.create(configTb);
APP.toolbar.$rightside.hide();
};
nThen(function(waitFor) {
// $(waitFor(UI.addLoadingScreen));
SFCommon.create(waitFor(function(c) { APP.common = common = c; }));
}).nThen(function(waitFor) {
APP.$container = $('#cp-sidebarlayout-container');
APP.$toolbar = $('#cp-toolbar');
sFrameChan = common.getSframeChannel();
sFrameChan.onReady(waitFor());
})
.nThen(function (waitFor) {
if (!common.isAdmin()) { return; }
updateStatus(waitFor());
})
.nThen(function( /*waitFor*/ ) {
common.setTabTitle(Messages.adminPage || 'Administration');
createToolbar();
APP.supportModule = common.makeUniversal('support');
// // Content
andThen(common, APP.$container);
// UI.removeLoadingScreen();
});
var urlArgs = window.location.href.replace(/^.*\?([^\?]*)$/, function (all, x) { return x; });
var elem = document.createElement('div');
elem.setAttribute('id', 'cp-loading');
elem.innerHTML = [
'<div class="cp-loading-logo">',
'<img class="cp-loading-cryptofist" src="/api/logo?' + urlArgs + '" alt="' + Messages.label_logo + '">',
'</div>',
'<div class="cp-loading-container">',
'<div class="cp-loading-spinner-container">',
'<span class="cp-spinner"></span>',
'</div>',
'<div class="cp-loading-progress">',
'<div class="cp-loading-progress-list"></div>',
'<div class="cp-loading-progress-container"></div>',
'</div>',
'<p id="cp-loading-message"></p>',
'</div>'
].join('');
var built = false;
return function () {
built = true;
var intr;
var append = function () {
if (!document.body) { return; }
clearInterval(intr);
document.body.appendChild(elem);
};
intr = setInterval(append, 100);
append();
};
});

View File

@ -16,9 +16,10 @@ define([
'/common/hyperscript.js',
'/customize/pages.js',
'/common/rpc.js',
'appconfigscreen.js',
'css!/components/components-font-awesome/css/font-awesome.min.css',
], function ($, Login, Cryptpad, /*Test,*/ Cred, UI, Util, Realtime, Constants, Feedback, LocalStore, h, Pages, Rpc) {
], function ($, Login, Cryptpad, /*Test,*/ Cred, UI, Util, Realtime, Constants, Feedback, LocalStore, h, Pages, Rpc, AppConfigScreen) {
if (window.top !== window) { return; }
var Messages = Cryptpad.Messages;
$(function () {
@ -56,116 +57,118 @@ define([
}
var registerClick = function () {
var uname = $uname.val().trim();
// trim whitespace surrounding the username since it is otherwise included in key derivation
// most people won't realize that its presence is significant
$uname.val(uname);
var passwd = $passwd.val();
var confirmPassword = $confirm.val();
AppConfigScreen.addConfigScreen()
// var uname = $uname.val().trim();
// // trim whitespace surrounding the username since it is otherwise included in key derivation
// // most people won't realize that its presence is significant
// $uname.val(uname);
if (!token) { token = $token.val().trim(); }
// var passwd = $passwd.val();
// var confirmPassword = $confirm.val();
var shouldImport = false;
var doesAccept;
try {
// if this throws there's either a horrible bug (which someone will report)
// or the instance admins did not configure a terms page.
doesAccept = true;
} catch (err) {
console.error(err);
}
// if (!token) { token = $token.val().trim(); }
if (Cred.isEmail(uname) && !I_REALLY_WANT_TO_USE_MY_EMAIL_FOR_MY_USERNAME) {
var emailWarning = [
Messages.register_emailWarning0,
br(), br(),
Messages.register_emailWarning1,
br(), br(),
Messages.register_emailWarning2,
br(), br(),
Messages.register_emailWarning3,
];
// var shouldImport = false;
// var doesAccept;
// try {
// // if this throws there's either a horrible bug (which someone will report)
// // or the instance admins did not configure a terms page.
// doesAccept = true;
// } catch (err) {
// console.error(err);
// }
Feedback.send("EMAIL_USERNAME_WARNING", true);
// if (Cred.isEmail(uname) && !I_REALLY_WANT_TO_USE_MY_EMAIL_FOR_MY_USERNAME) {
// var emailWarning = [
// Messages.register_emailWarning0,
// br(), br(),
// Messages.register_emailWarning1,
// br(), br(),
// Messages.register_emailWarning2,
// br(), br(),
// Messages.register_emailWarning3,
// ];
return void UI.confirm(emailWarning, function (yes) {
if (!yes) { return; }
I_REALLY_WANT_TO_USE_MY_EMAIL_FOR_MY_USERNAME = true;
registerClick();
});
}
// Feedback.send("EMAIL_USERNAME_WARNING", true);
/* basic validation */
if (!Cred.isLongEnoughPassword(passwd)) {
var warning = Messages._getKey('register_passwordTooShort', [
Cred.MINIMUM_PASSWORD_LENGTH
]);
return void UI.alert(warning);
}
// return void UI.confirm(emailWarning, function (yes) {
// if (!yes) { return; }
// I_REALLY_WANT_TO_USE_MY_EMAIL_FOR_MY_USERNAME = true;
// registerClick();
// });
// }
if (passwd !== confirmPassword) { // do their passwords match?
return void UI.alert(Messages.register_passwordsDontMatch);
}
// /* basic validation */
// if (!Cred.isLongEnoughPassword(passwd)) {
// var warning = Messages._getKey('register_passwordTooShort', [
// Cred.MINIMUM_PASSWORD_LENGTH
// ]);
// return void UI.alert(warning);
// }
if (Pages.customURLs.terms && !doesAccept) { // do they accept the terms of service? (if they exist)
return void UI.alert(Messages.register_mustAcceptTerms);
}
// if (passwd !== confirmPassword) { // do their passwords match?
// return void UI.alert(Messages.register_passwordsDontMatch);
// }
setTimeout(function () {
var span = h('span', [
h('h2', [
h('i.fa.fa-warning'),
' ',
Messages.register_warning,
]),
Messages.register_warning_note
]);
// if (Pages.customURLs.terms && !doesAccept) { // do they accept the terms of service? (if they exist)
// return void UI.alert(Messages.register_mustAcceptTerms);
// }
UI.confirm(span,
function (yes) {
if (!yes) { return; }
// setTimeout(function () {
// var span = h('span', [
// h('h2', [
// h('i.fa.fa-warning'),
// ' ',
// Messages.register_warning,
// ]),
// Messages.register_warning_note
// ]);
Login.loginOrRegisterUI({
uname,
passwd,
isRegister: true,
onOTP: UI.getOTPScreen,
shouldImport,
cb: function (data) {
var proxy = data.proxy;
if (!proxy || !proxy.edPublic) { UI.alert(Messages.error); return true; }
// UI.confirm(span,
// function (yes) {
// if (!yes) { return; }
Rpc.createAnonymous(data.network, function (e, call) {
if (e) { UI.alert(Messages.error); return console.error(e); }
var anon_rpc = call;
// Login.loginOrRegisterUI({
// uname,
// passwd,
// isRegister: true,
// onOTP: UI.getOTPScreen,
// shouldImport,
// cb: function (data) {
// var proxy = data.proxy;
// if (!proxy || !proxy.edPublic) { UI.alert(Messages.error); return true; }
anon_rpc.send('ADD_FIRST_ADMIN', {
token: token,
edPublic: proxy.edPublic
}, function (e) {
if (e) { UI.alert(Messages.error); return console.error(e); }
window.location.href = '/drive/';
});
});
// Rpc.createAnonymous(data.network, function (e, call) {
// if (e) { UI.alert(Messages.error); return console.error(e); }
// var anon_rpc = call;
return true;
}
});
}, {
ok: Messages.register_writtenPassword,
cancel: Messages.register_cancel,
/* If we're certain that we aren't using these "*Class" APIs
anywhere else then we can deprecate them and make this a
custom modal in common-interface (or here). */
cancelClass: 'btn.btn-cancel.btn-register',
okClass: 'btn.btn-danger.btn-register',
reverseOrder: true,
done: function ($dialog) {
$dialog.find('> div').addClass('half');
},
});
}, 150);
// anon_rpc.send('ADD_FIRST_ADMIN', {
// token: token,
// edPublic: proxy.edPublic
// }, function (e) {
// if (e) { UI.alert(Messages.error); return console.error(e); }
// window.location.href = '/drive/';
// });
// });
// return true;
// }
// });
// }, {
// ok: Messages.register_writtenPassword,
// cancel: Messages.register_cancel,
// /* If we're certain that we aren't using these "*Class" APIs
// anywhere else then we can deprecate them and make this a
// custom modal in common-interface (or here). */
// cancelClass: 'btn.btn-cancel.btn-register',
// okClass: 'btn.btn-danger.btn-register',
// reverseOrder: true,
// done: function ($dialog) {
// $dialog.find('> div').addClass('half');
// },
// });
// }, 150);
};
$register.click(registerClick);