Merge branch 'staging' into soon

pull/1/head
ansuz 4 years ago
commit db5b825cc3

@ -78,7 +78,7 @@
}
&.cp-support-list-closed {
.cp-support-list-actions {
display: block !important;
display: flex !important;
.cp-support-answer, .cp-support-close {
display: none;
}

14
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "cryptpad",
"version": "3.24.0",
"version": "3.25.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -181,16 +181,16 @@
"optional": true
},
"chainpad-crypto": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/chainpad-crypto/-/chainpad-crypto-0.2.4.tgz",
"integrity": "sha512-fWbVyeAv35vf/dkkQaefASlJcEfpEvfRI23Mtn+/TBBry7+LYNuJMXJiovVY35pfyw2+trKh1Py5Asg9vrmaVg==",
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/chainpad-crypto/-/chainpad-crypto-0.2.5.tgz",
"integrity": "sha512-K9vRsAspuX+uU1goXPz0CawpLIaOHq+1JP3WfDLqaz67LbCX/MLIUt9aMcSeIJcwZ9uMpqnbMGRktyVPoz6MCA==",
"requires": {
"tweetnacl": "git://github.com/dchest/tweetnacl-js.git#v0.12.2"
"tweetnacl": "git+https://github.com/dchest/tweetnacl-js.git#v0.12.2"
},
"dependencies": {
"tweetnacl": {
"version": "git://github.com/dchest/tweetnacl-js.git#8a21381d696acdc4e99c9f706f1ad23285795f79",
"from": "git://github.com/dchest/tweetnacl-js.git#v0.12.2"
"version": "git+https://github.com/dchest/tweetnacl-js.git#8a21381d696acdc4e99c9f706f1ad23285795f79",
"from": "git+https://github.com/dchest/tweetnacl-js.git#v0.12.2"
}
}
},

@ -1,11 +1,11 @@
{
"name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server",
"version": "3.24.0",
"version": "3.25.0",
"license": "AGPL-3.0+",
"repository": {
"type": "git",
"url": "git://github.com/xwiki-labs/cryptpad.git"
"url": "git+https://github.com/xwiki-labs/cryptpad.git"
},
"funding": {
"type": "opencollective",
@ -13,7 +13,7 @@
},
"dependencies": {
"@mcrowe/minibloom": "^0.2.0",
"chainpad-crypto": "^0.2.2",
"chainpad-crypto": "^0.2.5",
"chainpad-server": "^4.0.9",
"express": "~4.16.0",
"fs-extra": "^7.0.0",

@ -65,14 +65,62 @@
.cp-support-container {
display: flex;
flex-flow: column;
flex-wrap: wrap;
.cp-support-column {
min-width: 700px;
flex: 1 0 50%;
h1 {
display: flex;
align-items: center;
button {
margin-left: 50px !important;
}
}
.cp-support-count {
margin-left: 10px;
}
&.cp-support-column-collapsed {
.cp-support-list-ticket {
display: none;
}
}
}
}
.cp-support-list-actions {
margin: 10px 0px 10px 2px;
}
.cp-support-list-ticket {
h2 {
font-size: 1.5rem;
display: flex;
justify-content: space-between;
align-items: top;
.cp-support-title-buttons {
flex-shrink: 0;
}
}
.cp-support-collapsed {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
color: #666;
.cp-support-ispremium {
padding: 0 5px;
color: @colortheme_cp-red;
background-color: lighten(@colortheme_cp-red, 25%);
}
}
}
.cp-support-list-ticket:not(.cp-support-list-closed) {
.cp-support-list-actions {
.cp-button-confirm, .cp-support-close {
order: 20;
margin-left: auto !important;
}
}
.cp-support-list-message {
&:last-child:not(.cp-support-fromadmin) {
color: @colortheme_cp-red;
@ -92,6 +140,28 @@
}
}
}
.cp-support-list-ticket:not(.cp-support-open) {
span:first-child {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
& > :not(h2):not(.cp-support-collapsed) {
display: none;
}
.cp-support-collapse {
display: none;
}
cursor: pointer;
}
.cp-support-list-ticket.cp-support-open {
.cp-support-collapsed {
display: none;
}
.cp-support-expand {
display: none;
}
}
.cp-support-fromadmin {
color: @colortheme_logo-2;

@ -552,7 +552,53 @@ define([
var $div = $(h('div.cp-support-container')).appendTo($container);
var catContainer = h('div.cp-dropdown-container');
$div.append(catContainer);
Messages.admin_support_premium = "Premium tickets:"; // XXX
Messages.admin_support_normal = "Unanswered tickets:";
Messages.admin_support_answered = "Answered tickets:";
Messages.admin_support_closed = "Closed tickets:";
Messages.admin_support_open = "Show";
Messages.admin_support_collapse = "Collapse";
Messages.admin_support_first = "Created on: ";
Messages.admin_support_last = "Updated on: ";
var col1 = h('div.cp-support-column', h('h1', [
h('span', Messages.admin_support_premium),
h('span.cp-support-count'),
h('button.btn.cp-support-column-button', Messages.admin_support_collapse)
]));
var col2 = h('div.cp-support-column', h('h1', [
h('span', Messages.admin_support_normal),
h('span.cp-support-count'),
h('button.btn.cp-support-column-button', Messages.admin_support_collapse)
]));
var col3 = h('div.cp-support-column', h('h1', [
h('span', Messages.admin_support_answered),
h('span.cp-support-count'),
h('button.btn.cp-support-column-button', Messages.admin_support_collapse)
]));
var col4 = h('div.cp-support-column', h('h1', [
h('span', Messages.admin_support_closed),
h('span.cp-support-count'),
h('button.btn.cp-support-column-button', Messages.admin_support_collapse)
]));
var $col1 = $(col1), $col2 = $(col2), $col3 = $(col3), $col4 = $(col4);
$div.append([
//catContainer
col1,
col2,
col3,
col4
]);
$div.find('.cp-support-column-button').click(function () {
var $col = $(this).closest('.cp-support-column');
$col.toggleClass('cp-support-column-collapsed');
if ($col.hasClass('cp-support-column-collapsed')) {
$(this).text(Messages.admin_support_open);
$(this).toggleClass('btn-primary');
} else {
$(this).text(Messages.admin_support_collapse);
$(this).toggleClass('btn-primary');
}
});
var category = 'all';
var $drop = APP.support.makeCategoryDropdown(catContainer, function (key) {
category = key;
@ -572,37 +618,128 @@ define([
var hashesById = {};
var reorder = function () {
var order = Object.keys(hashesById);
order.sort(function (id1, id2) {
var t1 = hashesById[id1];
var t2 = hashesById[id2];
if (!Array.isArray(t1)) { return 1; }
if (!Array.isArray(t2)) { return -1; }
var lastMsg1 = t1[t1.length - 1];
var lastMsg2 = t2[t2.length - 1];
var time1 = Util.find(lastMsg1, ['content', 'msg', 'content', 'time']);
var time2 = Util.find(lastMsg2, ['content', 'msg', 'content', 'time']);
var authorEd1 = Util.find(lastMsg1, ['content', 'msg', 'content', 'sender', 'edPublic']);
var authorEd2 = Util.find(lastMsg2, ['content', 'msg', 'content', 'sender', 'edPublic']);
var admin1 = ApiConfig.adminKeys.indexOf(authorEd1) !== -1;
var admin2 = ApiConfig.adminKeys.indexOf(authorEd2) !== -1;
// If one is answered and not the other, put the unanswered first
if (admin1 && !admin2) { return 1; }
if (!admin1 && admin2) { return -1; }
// Otherwise, sort them by time
return time2 - time1;
var getTicketData = function (id) {
var t = hashesById[id];
if (!Array.isArray(t) || !t.length) { return; }
var ed = Util.find(t[0], ['content', 'msg', 'content', 'sender', 'edPublic']);
// If one of their ticket was sent as a premium user, mark them as premium
var premium = t.some(function (msg) {
var _ed = Util.find(msg, ['content', 'msg', 'content', 'sender', 'edPublic']);
if (ed !== _ed) { return; }
return Util.find(t[0], ['content', 'msg', 'content', 'sender', 'plan']);
});
var lastMsg = t[t.length - 1];
var lastMsgEd = Util.find(lastMsg, ['content', 'msg', 'content', 'sender', 'edPublic']);
return {
lastMsg: lastMsg,
time: Util.find(lastMsg, ['content', 'msg', 'content', 'time']),
lastMsgEd: lastMsgEd,
lastAdmin: lastMsgEd !== ed && ApiConfig.adminKeys.indexOf(lastMsgEd) !== -1,
premium: premium,
authorEd: ed,
closed: Util.find(lastMsg, ['content', 'msg', 'type']) === 'CLOSE'
};
};
var addClickHandler = function ($ticket) {
$ticket.on('click', function () {
$ticket.toggleClass('cp-support-open', true);
$ticket.off('click');
});
order.forEach(function (id, i) {
$div.find('[data-id="'+id+'"]').css('order', i);
};
var makeOpenButton = function ($ticket) {
var button = h('button.btn.btn-primary.cp-support-expand', Messages.admin_support_open);
var collapse = h('button.btn.cp-support-collapse', Messages.admin_support_collapse);
$(button).click(function () {
$ticket.toggleClass('cp-support-open', true);
});
addClickHandler($ticket);
$(collapse).click(function (e) {
$ticket.toggleClass('cp-support-open', false);
e.stopPropagation();
setTimeout(function () {
addClickHandler($ticket);
});
});
$ticket.find('.cp-support-title-buttons').prepend([button, collapse]);
$ticket.append(h('div.cp-support-collapsed'));
};
var updateTicketDetails = function ($ticket, isPremium) {
var $first = $ticket.find('.cp-support-message-from').first();
var user = $first.find('span').first().html();
var time = $first.find('.cp-support-message-time').text();
var last = $ticket.find('.cp-support-message-from').last().find('.cp-support-message-time').text();
var $c = $ticket.find('.cp-support-collapsed');
var txtClass = isPremium ? ".cp-support-ispremium" : "";
$c.html('').append([
UI.setHTML(h('span'+ txtClass), user),
h('span', [
h('b', Messages.admin_support_first),
h('span', time)
]),
h('span', [
h('b', Messages.admin_support_last),
h('span', last)
])
]);
};
var sort = function (id1, id2) {
var t1 = getTicketData(id1);
var t2 = getTicketData(id2);
if (!t1) { return 1; }
if (!t2) { return -1; }
/*
// If one is answered and not the other, put the unanswered first
if (t1.lastAdmin && !t2.lastAdmin) { return 1; }
if (!t1.lastAdmin && t2.lastAdmin) { return -1; }
*/
// Otherwise, sort them by time
return t1.time - t2.time;
};
var _reorder = function () {
var orderAnswered = Object.keys(hashesById).filter(function (id) {
var d = getTicketData(id);
return d && d.lastAdmin && !d.closed;
}).sort(sort);
var orderPremium = Object.keys(hashesById).filter(function (id) {
var d = getTicketData(id);
return d && d.premium && !d.lastAdmin && !d.closed;
}).sort(sort);
var orderNormal = Object.keys(hashesById).filter(function (id) {
var d = getTicketData(id);
return d && !d.premium && !d.lastAdmin && !d.closed;
}).sort(sort);
var orderClosed = Object.keys(hashesById).filter(function (id) {
var d = getTicketData(id);
return d && d.closed;
}).sort(sort);
var cols = [$col1, $col2, $col3, $col4];
[orderPremium, orderNormal, orderAnswered, orderClosed].forEach(function (list, j) {
list.forEach(function (id, i) {
var $t = $div.find('[data-id="'+id+'"]');
var d = getTicketData(id);
$t.css('order', i).appendTo(cols[j]);
updateTicketDetails($t, d.premium);
});
if (!list.length) {
cols[j].hide();
} else {
cols[j].show();
cols[j].find('.cp-support-count').text(list.length);
}
});
};
var reorder = Util.throttle(_reorder, 150);
var to = Util.throttle(function () {
var $ticket = $div.find('.cp-support-list-ticket[data-id="'+linkedId+'"]');
$ticket.addClass('cp-support-open');
$ticket[0].scrollIntoView();
linkedId = undefined;
}, 100);
}, 200);
// Register to the "support" mailbox
common.mailbox.subscribe(['supportadmin'], {
@ -630,6 +767,7 @@ define([
if (!$ticket.length) { return; }
$ticket.addClass('cp-support-list-closed');
$ticket.append(APP.support.makeCloseMessage(content, hash));
reorder();
return;
}
if (msg.type !== 'TICKET') { return; }
@ -650,13 +788,19 @@ define([
}));
});
}).nThen(function () {
if (!error) { return void $ticket.remove(); }
if (!error) {
$ticket.remove();
delete hashesById[id];
reorder();
return;
}
// if deletion failed then reactivate the button and warn
hideButton.removeAttribute('disabled');
// and show a generic error message
UI.alert(Messages.error);
});
});
makeOpenButton($ticket);
if (category !== 'all' && $ticket.attr('data-cat') !== category) {
$ticket.hide();
}

@ -774,7 +774,8 @@ define([
$(originalBtn).show();
};
$button.click(function () {
$button.click(function (e) {
e.stopPropagation();
done(true);
});
@ -792,7 +793,8 @@ define([
to = setTimeout(todo, INTERVAL);
};
$(originalBtn).addClass('cp-button-confirm-placeholder').click(function () {
$(originalBtn).addClass('cp-button-confirm-placeholder').click(function (e) {
e.stopPropagation();
// If we have a validation function, continue only if it's true
if (config.validate && !config.validate()) { return; }
i = 1;

@ -1631,7 +1631,7 @@ define([
Store.leavePad(null, data, function () {});
};
var conf = {
//Cache: Cache, // XXX re-enable cache usage
Cache: Cache, // XXX re-enable cache usage
onCacheStart: function () {
postMessage(clientId, "PAD_CACHE");
},
@ -2686,7 +2686,7 @@ define([
readOnly: false,
validateKey: secret.keys.validateKey || undefined,
crypto: Crypto.createEncryptor(secret.keys),
//Cache: Cache, // XXX re-enable cache usage
Cache: Cache, // XXX re-enable cache usage
userName: 'fs',
logLevel: 1,
ChainPad: ChainPad,

@ -175,7 +175,7 @@ define([
ChainPad: ChainPad,
classic: true,
network: network,
//Cache: Cache, // XXX re-enable cache usage
Cache: Cache, // XXX re-enable cache usage
metadata: {
validateKey: secret.keys.validateKey || undefined,
owners: owners

@ -427,7 +427,7 @@ define([
channel: secret.channel,
crypto: crypto,
ChainPad: ChainPad,
//Cache: Cache, // XXX re-enable cache usage
Cache: Cache, // XXX re-enable cache usage
metadata: {
validateKey: secret.keys.validateKey || undefined,
},

@ -230,7 +230,7 @@ define([
var form = h('div.cp-support-form-container', content);
$(cancel).click(function () {
$(form).closest('.cp-support-list-ticket').find('.cp-support-list-actions').show();
$(form).closest('.cp-support-list-ticket').find('.cp-support-list-actions').css('display', '');
$(form).remove();
});
@ -257,8 +257,9 @@ define([
var url;
if (ctx.isAdmin) {
ticketCategory = Messages['support_cat_'+(content.category || 'all')] + ' - ';
url = h('button.btn.btn-primary.fa.fa-clipboard');
$(url).click(function () {
url = h('button.btn.fa.fa-clipboard');
$(url).click(function (e) {
e.stopPropagation();
var link = privateData.origin + privateData.pathname + '#' + 'support-' + content.id;
var success = Clipboard.copy(link);
if (success) { UI.log(Messages.shareSuccess); }
@ -269,7 +270,10 @@ define([
'data-cat': content.category,
'data-id': content.id
}, [
h('h2', [ticketCategory, ticketTitle, url]),
h('h2', [
h('span', [ticketCategory, ticketTitle]),
h('span.cp-support-title-buttons',url)
]),
actions
]));
@ -303,7 +307,7 @@ define([
var form = makeForm(ctx, function () {
var sent = sendForm(ctx, content.id, form, content.sender);
if (sent) {
$(actions).show();
$(actions).css('display', '');
$(form).remove();
}
}, content.title);

Loading…
Cancel
Save