mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-14 11:05:41 +05:00
Merge branch 'staging' into roster
This commit is contained in:
commit
f31ebfe7ec
@ -136,8 +136,9 @@ define(req, function(AppConfig, Default, Language) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Messages.team_autoTrim = "Removing unused history... Please wait."; // XXX
|
||||
Messages.admin_mfa_confirm_enable = "Are you sure you want to enable Multi-Factor Authentication?"; // XXX
|
||||
Messages.admin_mfa_confirm_disable = "Are you sure you want to disable Multi-Factor Authentication?"; // XXX
|
||||
|
||||
return Messages;
|
||||
|
||||
|
||||
@ -953,6 +953,9 @@
|
||||
li, li .fa, li .cptools {
|
||||
cursor: pointer;
|
||||
border-radius: @variables_radius;
|
||||
&:focus {
|
||||
outline: @cryptpad_color_brand solid 2px;
|
||||
}
|
||||
}
|
||||
&> p {
|
||||
display: flex;
|
||||
|
||||
@ -33,8 +33,8 @@
|
||||
color: @cp_drive-fg;
|
||||
}
|
||||
&.cp-icons-element-selected {
|
||||
background: @cp_drive-icon-hover;
|
||||
color: @cp_drive-fg;
|
||||
outline: @cryptpad_color_brand solid 2px;
|
||||
}
|
||||
.fa, .cptools {
|
||||
display: block;
|
||||
|
||||
@ -28,6 +28,37 @@
|
||||
max-height: 250px;
|
||||
}
|
||||
}
|
||||
#cp-sidebarlayout-container {
|
||||
#cp-sidebarlayout-rightside {
|
||||
.cp-sidebarlayout-element[data-item] {
|
||||
div#cp-admin-table-container {
|
||||
overflow-x: auto;
|
||||
.cp-sidebar-table#cp-admin-table {
|
||||
tr {
|
||||
display: flex;
|
||||
}
|
||||
th, td {
|
||||
flex: 1;
|
||||
word-wrap: break-word;
|
||||
white-space: normal;
|
||||
min-width: 13rem;
|
||||
margin-right: 0px;
|
||||
}
|
||||
@media (max-width: @browser_media-not-small) {
|
||||
width: 100%;
|
||||
tr {
|
||||
width: 100%;
|
||||
}
|
||||
th, td {
|
||||
margin-right: 0;
|
||||
min-width: 7rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.cp-admin-color-current {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
@ -578,23 +578,38 @@ define([
|
||||
return APP.instanceStatus.enforceMFA;
|
||||
},
|
||||
query: function (val, setState) {
|
||||
sFrameChan.query('Q_ADMIN_RPC', {
|
||||
cmd: 'ADMIN_DECREE',
|
||||
data: ['ENFORCE_MFA', [val]]
|
||||
}, function (e, response) {
|
||||
if (e || response.error) {
|
||||
UI.warn(Messages.error);
|
||||
console.error(e, response);
|
||||
}
|
||||
APP.updateStatus(function () {
|
||||
setState(APP.instanceStatus.enforceMFA);
|
||||
flushCache();
|
||||
var isChecked = APP.instanceStatus.enforceMFA;
|
||||
function showConfirmation(isChecked, setState) {
|
||||
const confirmationContent = isChecked ? Messages.admin_mfa_confirm_disable : Messages.admin_mfa_confirm_enable;
|
||||
UI.confirm(confirmationContent, function (confirmed) {
|
||||
if (!confirmed) {
|
||||
// User canceled their changes, restore the checkbox value
|
||||
setState(isChecked);
|
||||
return;
|
||||
}
|
||||
// User confirmed their changes, call the command and update the state
|
||||
sFrameChan.query('Q_ADMIN_RPC', {
|
||||
cmd: 'ADMIN_DECREE',
|
||||
data: ['ENFORCE_MFA', [val]]
|
||||
}, function (e, response) {
|
||||
if (e || response.error) {
|
||||
UI.warn(Messages.error);
|
||||
console.error(e, response);
|
||||
} else {
|
||||
APP.updateStatus(function () {
|
||||
setState(APP.instanceStatus.enforceMFA);
|
||||
flushCache();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
showConfirmation(isChecked, setState);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
var getInstanceString = function (attr) {
|
||||
var val = APP.instanceStatus[attr];
|
||||
var type = typeof(val);
|
||||
@ -1101,6 +1116,9 @@ define([
|
||||
""
|
||||
];
|
||||
var list = blocks.table(header, []);
|
||||
list.setAttribute('id', 'cp-admin-table');
|
||||
let div = blocks.block([list]);
|
||||
div.setAttribute('id', 'cp-admin-table-container');
|
||||
|
||||
var nav = blocks.nav([button, refreshButton]);
|
||||
var form = blocks.form([
|
||||
@ -1201,7 +1219,7 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
cb([form, list]);
|
||||
cb([form, div]);
|
||||
});
|
||||
|
||||
var getBlockId = (val) => {
|
||||
@ -1413,6 +1431,9 @@ define([
|
||||
""
|
||||
];
|
||||
var list = blocks.table(header, []);
|
||||
list.setAttribute('id', 'cp-admin-table');
|
||||
let div = blocks.block([list]);
|
||||
div.setAttribute('id', 'cp-admin-table-container');
|
||||
|
||||
var nav = blocks.nav([button, refreshButton]);
|
||||
|
||||
@ -1581,7 +1602,7 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
cb([form, list]);
|
||||
cb([form, div]);
|
||||
});
|
||||
|
||||
// Msg.admin_defaultlimitHint, .admin_defaultlimitTitle
|
||||
@ -1741,6 +1762,9 @@ define([
|
||||
Messages.admin_note
|
||||
];
|
||||
var table = blocks.table(header, []);
|
||||
table.setAttribute('id', 'cp-admin-table');
|
||||
let div = blocks.block([table]);
|
||||
div.setAttribute('id', 'cp-admin-table-container');
|
||||
let $table = $(table).hide();
|
||||
|
||||
APP.refreshLimits = function () {
|
||||
@ -1798,7 +1822,7 @@ define([
|
||||
});
|
||||
};
|
||||
APP.refreshLimits();
|
||||
cb(table);
|
||||
cb(div);
|
||||
});
|
||||
|
||||
// Msg.admin_accountMetadataHint.admin_accountMetadataTitle
|
||||
@ -3594,6 +3618,9 @@ define([
|
||||
];
|
||||
|
||||
var table = blocks.table(header, []);
|
||||
table.setAttribute('id', 'cp-admin-table');
|
||||
let div = blocks.block([table]);
|
||||
div.setAttribute('id', 'cp-admin-table-container');
|
||||
|
||||
const onRefresh = function () {
|
||||
sFrameChan.query('Q_ADMIN_RPC', {
|
||||
@ -3626,7 +3653,7 @@ define([
|
||||
onRefresh();
|
||||
onRefreshPerformance.reg(onRefresh);
|
||||
|
||||
cb(table);
|
||||
cb(div);
|
||||
});
|
||||
|
||||
|
||||
|
||||
@ -157,6 +157,11 @@
|
||||
border-radius: @variables_radius_L;
|
||||
}
|
||||
.tui-full-calendar-popup-container {
|
||||
.tui-full-calendar-section-allday{
|
||||
&:focus {
|
||||
outline: @cryptpad_color_brand solid 2px;
|
||||
}
|
||||
}
|
||||
min-width: 100%;
|
||||
background: @cp_flatpickr-bg;
|
||||
color: @cryptpad_text_col;
|
||||
@ -208,6 +213,9 @@
|
||||
text-overflow: ellipsis;
|
||||
font: @colortheme_app-font;
|
||||
padding: 0 10px;
|
||||
&:focus{
|
||||
outline: @cryptpad_color_brand solid 2px;
|
||||
}
|
||||
}
|
||||
input { flex: 1; }
|
||||
}
|
||||
@ -403,6 +411,11 @@
|
||||
& > input {
|
||||
height: 40px;
|
||||
}
|
||||
.tui-full-calendar-content{
|
||||
&:focus{
|
||||
outline: @cryptpad_color_brand solid 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
// margin-bottom: 20px;
|
||||
input {
|
||||
|
||||
@ -2063,6 +2063,15 @@ APP.recurrenceRule = {
|
||||
editor.setOption('readOnly', false);
|
||||
editor.setOption('autoRefresh', true);
|
||||
editor.setOption('gutters', []);
|
||||
editor.on('keydown', function (editor, e) {
|
||||
if (e.which === 27) {
|
||||
let $next = $(e.target).closest('.tui-full-calendar-popup-section').next();
|
||||
if ($next.length) {
|
||||
$next.find('#tui-full-calendar-schedule-start-date').focus();
|
||||
}
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
cm.configureTheme(common, function () {});
|
||||
editor.setValue(oldEventBody);
|
||||
|
||||
@ -2147,6 +2156,13 @@ APP.recurrenceRule = {
|
||||
$el.find('input').attr('autocomplete', 'off');
|
||||
$el.find('.tui-full-calendar-dropdown-button').addClass('btn btn-secondary');
|
||||
$el.find('.tui-full-calendar-popup-close').addClass('btn btn-cancel fa fa-times cp-calendar-close').empty();
|
||||
$el.find('.tui-full-calendar-section-allday').attr('tabindex', 0);
|
||||
$el.find('.cp-calendar-close').attr('tabindex',-1);
|
||||
$el.find('.tui-full-calendar-section-allday').keydown(function (e) {
|
||||
if (e.which === 13) {
|
||||
$(this).click();
|
||||
}
|
||||
});
|
||||
|
||||
var $container = $el.closest('.tui-full-calendar-floating-layer');
|
||||
$container.addClass('cp-calendar-popup-flex');
|
||||
@ -2209,6 +2225,7 @@ APP.recurrenceRule = {
|
||||
setFormat(allDay);
|
||||
});
|
||||
});
|
||||
UI.addTabListener(el);
|
||||
};
|
||||
var onCalendarEditPopup = function (el) {
|
||||
var $el = $(el);
|
||||
@ -2244,6 +2261,7 @@ APP.recurrenceRule = {
|
||||
var data = ev.schedule || {};
|
||||
var id = data.id;
|
||||
|
||||
UI.addTabListener(el);
|
||||
if (!id) { return; }
|
||||
if (id.indexOf('|') === -1) { return; } // Original event ID doesn't contain |
|
||||
|
||||
|
||||
@ -164,12 +164,12 @@ define([
|
||||
|
||||
dialog.okButton = function (content, classString) {
|
||||
var sel = typeof(classString) === 'string'? 'button.ok.' + classString:'button.btn.ok.primary';
|
||||
return h(sel, { tabindex: '2', }, content || Messages.okButton);
|
||||
return h(sel, content || Messages.okButton);
|
||||
};
|
||||
|
||||
dialog.cancelButton = function (content, classString) {
|
||||
var sel = typeof(classString) === 'string'? 'button.' + classString:'button.btn.cancel';
|
||||
return h(sel, { tabindex: '1'}, content || Messages.cancelButton);
|
||||
return h(sel, content || Messages.cancelButton);
|
||||
};
|
||||
|
||||
dialog.message = function (text) {
|
||||
@ -577,7 +577,7 @@ define([
|
||||
return frame;
|
||||
};
|
||||
|
||||
let addTabListener = frame => {
|
||||
let addTabListener = UI.addTabListener = frame => {
|
||||
// find focusable elements
|
||||
let modalElements = $(frame).find('a, button, input, [tabindex]:not([tabindex="-1"]), textarea').filter(':visible').filter(':not(:disabled)');
|
||||
|
||||
@ -670,6 +670,7 @@ define([
|
||||
$modal: $blockContainer,
|
||||
show: function () {
|
||||
$blockContainer.css('display', 'flex');
|
||||
addTabListener($blockContainer);
|
||||
},
|
||||
hide: hide
|
||||
};
|
||||
@ -719,6 +720,7 @@ define([
|
||||
Notifier.notify();
|
||||
});
|
||||
|
||||
addTabListener(frame);
|
||||
return {
|
||||
element: frame,
|
||||
delete: close
|
||||
@ -770,7 +772,7 @@ define([
|
||||
|
||||
document.body.appendChild(frame);
|
||||
setTimeout(function () {
|
||||
$(input).select().focus();
|
||||
addTabListener(frame);
|
||||
Notifier.notify();
|
||||
});
|
||||
};
|
||||
|
||||
@ -3559,7 +3559,7 @@ define([
|
||||
$(link).click(function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var obj = { pw: msg.content.password || '' };
|
||||
var obj = { pw: msg.content.password || '', f: 1 };
|
||||
common.openURL(Hash.getNewPadURL(msg.content.href, obj));
|
||||
});
|
||||
|
||||
@ -3615,7 +3615,7 @@ define([
|
||||
|
||||
// Add the pad to your drive
|
||||
// This command will also add your mailbox to the metadata log
|
||||
// The callback is called when the pad is stored, independantly of the metadata command
|
||||
// The callback is called when the pad is stored, independently of the metadata command
|
||||
if (data.calendar) {
|
||||
var calendarModule = common.makeUniversal('calendar');
|
||||
var calendarData = data.calendar;
|
||||
|
||||
@ -2619,7 +2619,8 @@ define([
|
||||
disableCache: localStorage['CRYPTPAD_STORE|disableCache'],
|
||||
driveEvents: !rdyCfg.noDrive, //rdyCfg.driveEvents // Boolean
|
||||
lastVisit: Number(localStorage.lastVisit) || undefined,
|
||||
blockId: blockId
|
||||
blockId: blockId,
|
||||
blockHash: blockHash
|
||||
};
|
||||
common.userHash = userHash || LocalStore.getUserHash();
|
||||
|
||||
|
||||
@ -129,6 +129,7 @@ define([
|
||||
var obj = {
|
||||
p: msg.content.isTemplate ? ['template'] : undefined,
|
||||
t: teamNotification || undefined,
|
||||
f: 1,
|
||||
pw: msg.content.password || ''
|
||||
};
|
||||
common.openURL(Hash.getNewPadURL(msg.content.href, obj));
|
||||
|
||||
@ -8,7 +8,8 @@ define([
|
||||
'/common/common-hash.js',
|
||||
'/common/common-util.js',
|
||||
'/components/chainpad-crypto/crypto.js',
|
||||
], function (ApiConfig, Messaging, Hash, Util, Crypto) {
|
||||
'/common/outer/login-block.js',
|
||||
], function (ApiConfig, Messaging, Hash, Util, Crypto, Block) {
|
||||
|
||||
// Random timeout between 10 and 30 times your sync time (lag + chainpad sync)
|
||||
var getRandomTimeout = function (ctx) {
|
||||
@ -237,6 +238,14 @@ define([
|
||||
cb(true);
|
||||
};
|
||||
|
||||
// Encrypt the password under the right key before sending it via URL hash
|
||||
var encryptPassword = function(ctx, password) {
|
||||
let uHash = ctx.store.data.blockHash;
|
||||
let uSecret = Block.parseBlockHash(uHash);
|
||||
let key = uSecret.keys.symmetric;
|
||||
return Crypto.encrypt(password, key);
|
||||
};
|
||||
|
||||
// Hide duplicates when receiving a SHARE_PAD notification:
|
||||
// Keep only one notification per channel: the stronger and more recent one
|
||||
var channels = {};
|
||||
@ -265,8 +274,7 @@ define([
|
||||
}
|
||||
|
||||
if (content.password) {
|
||||
var key = ctx.store.driveSecret.keys.cryptKey;
|
||||
content.password = Crypto.encrypt(content.password, key);
|
||||
content.password = encryptPassword(ctx, content.password);
|
||||
}
|
||||
|
||||
// Update the data
|
||||
@ -384,8 +392,8 @@ define([
|
||||
var channel = content.channel || content.teamChannel;
|
||||
|
||||
if (content.password) {
|
||||
var key = ctx.store.driveSecret.keys.cryptKey;
|
||||
content.password = Crypto.encrypt(content.password, key);
|
||||
content.pw = content.password;
|
||||
content.password = encryptPassword(ctx, content.password);
|
||||
}
|
||||
|
||||
if (addOwners[channel]) { return void cb(true); }
|
||||
|
||||
@ -1083,7 +1083,7 @@ define([
|
||||
Cryptpad.addSharedFolder(null, secret, cb);
|
||||
} else {
|
||||
var _data = {
|
||||
password: data.password,
|
||||
password: data.pw || data.password,
|
||||
href: data.href,
|
||||
channel: data.channel,
|
||||
title: data.title,
|
||||
@ -1359,7 +1359,7 @@ define([
|
||||
var viewH = Utils.Hash.getViewHashFromKeys(_secret);
|
||||
var href = Utils.Hash.hashToHref(editH, parsed.type);
|
||||
var roHref = Utils.Hash.hashToHref(viewH, parsed.type);
|
||||
Cryptpad.setPadAttribute('password', password, w(), parsed.getUrl());
|
||||
Cryptpad.setPadAttribute('password', pw, w(), parsed.getUrl());
|
||||
Cryptpad.setPadAttribute('channel', chan, w(), parsed.getUrl());
|
||||
Cryptpad.setPadAttribute('href', href, w(), parsed.getUrl());
|
||||
Cryptpad.setPadAttribute('roHref', roHref, w(), parsed.getUrl());
|
||||
|
||||
@ -1011,7 +1011,6 @@
|
||||
min-width: 300px;
|
||||
width: 300px;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
word-break: break-word;
|
||||
background: @cp_form-bg1;
|
||||
z-index: 2;
|
||||
|
||||
@ -516,7 +516,7 @@ define([
|
||||
created++;
|
||||
}
|
||||
if (team.empty) {
|
||||
var createTeamDiv = h('div.cp-team-list-team.empty'+createCls,{
|
||||
var createTeamDiv = h('li.cp-team-list-team.empty'+createCls,{
|
||||
tabindex: '0'
|
||||
}, [
|
||||
h('span.cp-team-list-name.empty', Messages.team_listSlot),
|
||||
@ -533,7 +533,7 @@ define([
|
||||
return;
|
||||
}
|
||||
var avatar = h('span.cp-avatar');
|
||||
var teamDiv = h('div.cp-team-list-team',{
|
||||
var teamDiv = h('li.cp-team-list-team',{
|
||||
tabindex: '0'
|
||||
}, [
|
||||
h('span.cp-team-list-avatar', avatar),
|
||||
@ -553,7 +553,7 @@ define([
|
||||
}
|
||||
});
|
||||
});
|
||||
content.push(h('div.cp-team-list-container', list));
|
||||
content.push(h('ul.cp-team-list-container', list));
|
||||
cb(content);
|
||||
});
|
||||
return content;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user