Add custom limits UI in the admin panel

pull/1/head
yflory 4 years ago committed by ansuz
parent 51e1b9b043
commit a5693af2e9

@ -19,6 +19,48 @@
display: flex; display: flex;
flex-flow: column; flex-flow: column;
.cp-admin-setlimit-form {
label {
font-weight: normal !important;
}
input {
max-width: 400px;
}
nav {
display: flex;
margin-top: 5px;
}
}
.cp-admin-getlimits {
code {
cursor: pointer;
}
ul.cp-compact {
.cp-admin-limit {
display: flex;
align-items: center;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
ul {
display: inline;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
li {
display: inline-block;
&.limit {
width: 130px;
}
&.plan {
width: 140px;
}
}
}
}
}
}
.cp-support-container { .cp-support-container {
display: flex; display: flex;
flex-flow: column; flex-flow: column;

@ -10,6 +10,7 @@ define([
'/common/common-interface.js', '/common/common-interface.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-hash.js', '/common/common-hash.js',
'/common/common-signing-keys.js',
'/support/ui.js', '/support/ui.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
@ -27,10 +28,13 @@ define([
UI, UI,
Util, Util,
Hash, Hash,
Keys,
Support Support
) )
{ {
var APP = {}; var APP = {
'instanceStatus': {}
};
var common; var common;
var sFrameChan; var sFrameChan;
@ -38,7 +42,13 @@ define([
var categories = { var categories = {
'general': [ 'general': [
'cp-admin-flush-cache', 'cp-admin-flush-cache',
'cp-admin-update-limit' 'cp-admin-update-limit',
'cp-admin-registration'
],
'quota': [
'cp-admin-defaultlimit',
'cp-admin-setlimit',
'cp-admin-getlimits',
], ],
'stats': [ 'stats': [
'cp-admin-active-sessions', 'cp-admin-active-sessions',
@ -97,6 +107,215 @@ define([
}); });
return $div; return $div;
}; };
Messages.admin_registrationHint = "Restrict registration..."; // XXX
Messages.admin_registrationTitle = "Restrict registration"; // XXX
Messages.admin_registrationButton = "Restrict"; // XXX
Messages.admin_registrationAllow = "Allow"; // XXX
create['registration'] = function () {
var key = 'registration';
var $div = makeBlock(key, true);
var $button = $div.find('button');
var state = APP.instanceStatus.restrictRegistration;
if (state) {
$button.text(Messages.admin_registrationAllow);
} else {
$button.removeClass('btn-primary').addClass('btn-danger');
}
var called = false;
$div.find('button').click(function () {
called = true;
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['RESTRICT_REGISTRATION', [!state]]
}, function (e) {
if (e) { UI.warn(Messages.error); console.error(e); }
APP.updateStatus(function () {
called = false;
state = APP.instanceStatus.restrictRegistration;
if (state) {
console.log($button);
$button.text(Messages.admin_registrationAllow);
$button.addClass('btn-primary').removeClass('btn-danger');
} else {
$button.text(Messages.admin_registrationButton);
$button.removeClass('btn-primary').addClass('btn-danger');
}
});
});
});
return $div;
};
var getPrettySize = function (bytes) {
var unit = Util.magnitudeOfBytes(bytes);
var value = unit === 'GB' ? Util.bytesToGigabytes(bytes) : Util.bytesToMegabytes(bytes);
return unit === 'GB' ? Messages._getKey('formattedGB', [value])
: Messages._getKey('formattedMB', [value])
};
Messages.admin_defaultlimitTitle = "Storage limit"; // XXX
Messages.admin_defaultlimitHint = "Maximum storage limit per user drive and team drive when no custom rule is applied"; // XXX
Messages.admin_limit = "Limit: {0}";
create['defaultlimit'] = function () {
var key = 'defaultlimit';
var $div = makeBlock(key);
var _limit = APP.instanceStatus.defaultStorageLimit;
var limit = getPrettySize(_limit);
$div.append(h('div', [
h('span', Messages._getKey('admin_limit', [limit]))
]));
return $div;
};
Messages.admin_getlimitsHint = "List all the custom storage limits applied to your instance."; // XXX
Messages.admin_getlimitsTitle = "Custom limits"; // XXX
Messages.admin_limitPlan = "Plan: {0}";
Messages.admin_limitNote = "Note: {0}";
create['getlimits'] = function () {
var key = 'getlimits';
var $div = makeBlock(key);
APP.refreshLimits = function () {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'GET_LIMITS',
}, function (e, data) {
if (e) { return; }
if (!Array.isArray(data) || !data[0]) { return; }
$div.find('.cp-admin-all-limits').remove();
var obj = data[0];
if (obj && (obj.message || obj.location)) {
delete obj.message;
delete obj.location;
}
var list = Object.keys(obj).sort(function (a, b) {
return obj[a].limit > obj[b].limit;
});
var addClass = "";
if (list.length > 10) { addClass = ".cp-compact"; }
var content = list.map(function (key) {
var user = obj[key];
var limit = getPrettySize(user.limit);
var title = Messages._getKey('admin_limit', [limit]) + ', ' +
Messages._getKey('admin_limitPlan', [user.plan]) + ', ' +
Messages._getKey('admin_limitNote', [user.note]);
var keyEl = h('code.cp-limit-key', key);
$(keyEl).click(function () {
$('.cp-admin-setlimit-form').find('.cp-setlimit-key').val(key);
});
return h('li.cp-admin-limit', {
title: addClass ? title : ''
}, [
keyEl,
h('ul.cp-limit-data', [
h('li.limit', Messages._getKey('admin_limit', [limit])),
//h('li.plan', Messages._getKey('admin_limitPlan', [user.plan])),
h('li.note', Messages._getKey('admin_limitNote', [user.note]))
])
]);
});
$div.append(h('ul.cp-admin-all-limits'+addClass, content));
});
};
APP.refreshLimits();
return $div;
};
Messages.admin_setlimitHint = "Get the public key of a user and give them a custom storage limit. You can update an existing limit or remove the custom limit."; // XXX
Messages.admin_setlimitTitle = "Apply a custom limit"; // XXX
Messages.admin_setlimitButton = "Set limit"; // XXX
Messages.admin_limitUser = "User's public key"; // XXX
Messages.admin_limitMB = "Limit (in MB)"; // XXX
Messages.admin_limitSetNote = "Custom Note"; // XXX
Messages.admin_invalKey = "Invalid public key";
Messages.admin_invalLimit = "Invalid limit value";
create['setlimit'] = function () {
var key = 'setlimit';
var $div = makeBlock(key);
var user = h('input.cp-setlimit-key');
var $key = $(user);
var limit = h('input', {type: 'number', min: 0, value: 0});
var note = h('input');
var remove = h('button.btn.btn-danger', Messages.fc_remove);
var set = h('button.btn.btn-primary', Messages.admin_setlimitButton);
var form = h('div.cp-admin-setlimit-form', [
h('label', Messages.admin_limitUser),
user,
h('label', Messages.admin_limitMB),
limit,
h('label', Messages.admin_limitSetNote),
note,
h('nav', [set, remove])
]);
var getValues = function () {
var key = $key.val();
var _limit = parseInt($(limit).val());
var _note = $(note).val();
if (key.length !== 44) {
try {
var u = Keys.parseUser(key);
if (!u.domain || !u.user || !u.pubkey) {
return void UI.warn(Messages.admin_invalKey);
}
} catch (e) {
return void UI.warn(Messages.admin_invalKey);
}
}
if (isNaN(_limit) || _limit < 0) {
return void UI.warn(Messages.admin_invalLimit);
}
return {
key: key,
data: {
limit: _limit * 1024 * 1024,
note: _note,
plan: 'custom'
}
};
};
UI.confirmButton(remove, {
classes: 'btn-danger',
validate: function () {
var obj = getValues();
if (!obj || !obj.key) { return false; }
return true;
}
}, function () {
var obj = getValues();
var data = [obj.key];
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['RM_QUOTA', data]
}, function (e) {
if (e) { UI.warn(Messages.error); console.error(e); }
APP.refreshLimits();
$key.val('');
});
});
$(set).click(function () {
var obj = getValues();
if (!obj || !obj.key) { return; }
var data = [obj.key, obj.data];
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['SET_QUOTA', data]
}, function (e) {
if (e) { UI.warn(Messages.error); console.error(e); }
APP.refreshLimits();
$key.val('');
});
});
$div.append(form);
return $div;
};
create['active-sessions'] = function () { create['active-sessions'] = function () {
var key = 'active-sessions'; var key = 'active-sessions';
var $div = makeBlock(key); var $div = makeBlock(key);
@ -409,6 +628,18 @@ define([
APP.toolbar.$rightside.hide(); APP.toolbar.$rightside.hide();
}; };
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();
});
};
nThen(function (waitFor) { nThen(function (waitFor) {
$(waitFor(UI.addLoadingScreen)); $(waitFor(UI.addLoadingScreen));
SFCommon.create(waitFor(function (c) { APP.common = common = c; })); SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
@ -419,6 +650,8 @@ define([
APP.$rightside = $('<div>', {id: 'cp-sidebarlayout-rightside'}).appendTo(APP.$container); APP.$rightside = $('<div>', {id: 'cp-sidebarlayout-rightside'}).appendTo(APP.$container);
sFrameChan = common.getSframeChannel(); sFrameChan = common.getSframeChannel();
sFrameChan.onReady(waitFor()); sFrameChan.onReady(waitFor());
}).nThen(function (waitFor) {
updateStatus(waitFor());
}).nThen(function (/*waitFor*/) { }).nThen(function (/*waitFor*/) {
createToolbar(); createToolbar();
var metadataMgr = common.getMetadataMgr(); var metadataMgr = common.getMetadataMgr();
@ -435,6 +668,7 @@ define([
APP.readOnly = privateData.readOnly; APP.readOnly = privateData.readOnly;
APP.support = Support.create(common, true); APP.support = Support.create(common, true);
// Content // Content
var $rightside = APP.$rightside; var $rightside = APP.$rightside;
var addItem = function (cssClass) { var addItem = function (cssClass) {

@ -717,6 +717,8 @@ define([
}; };
$(originalBtn).addClass('cp-button-confirm-placeholder').click(function () { $(originalBtn).addClass('cp-button-confirm-placeholder').click(function () {
// If we have a validation function, continue only if it's true
if (config.validate && !config.validate()) { return; }
i = 1; i = 1;
to = setTimeout(todo, INTERVAL); to = setTimeout(todo, INTERVAL);
$(originalBtn).hide().after(content); $(originalBtn).hide().after(content);

@ -1203,7 +1203,7 @@ define([
Util.bytesToMegabytes(limit); Util.bytesToMegabytes(limit);
var $limit = $('<span>', {'class': 'cp-limit-bar'}).appendTo($container); var $limit = $('<span>', {'class': 'cp-limit-bar'}).appendTo($container);
var quota = usage/limit; var quota = limit === 0 ? 1 : usage/limit;
var $usage = $('<span>', {'class': 'cp-limit-usage'}).css('width', quota*100+'%'); var $usage = $('<span>', {'class': 'cp-limit-usage'}).css('width', quota*100+'%');
var $buttons = $(h('span.cp-limit-buttons')).appendTo($container); var $buttons = $(h('span.cp-limit-buttons')).appendTo($container);

Loading…
Cancel
Save