mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-14 11:05:41 +05:00
New support: add search and fix UI issues
This commit is contained in:
parent
b943930948
commit
a4bdc64520
@ -133,6 +133,26 @@
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
.cp-sidebar-input-block {
|
||||
display: inline-flex;
|
||||
width: @sidebar_button-width;
|
||||
max-width: 100%;
|
||||
input {
|
||||
flex: 1;
|
||||
//border-radius: 0.25em 0 0 0.25em;
|
||||
border: 1px solid @cryptpad_color_grey_500;
|
||||
border-right: 0px;
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
}
|
||||
button {
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-left: 0px;
|
||||
height: 40px;
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cp-sidebarlayout-description {
|
||||
|
||||
@ -99,9 +99,6 @@ define([
|
||||
],
|
||||
'support': [ // Msg.admin_cat_support
|
||||
'cp-admin-support-new',
|
||||
'cp-admin-support-list',
|
||||
'cp-admin-support-init',
|
||||
'cp-admin-support-priv',
|
||||
],
|
||||
'broadcast': [ // Msg.admin_cat_broadcast
|
||||
'cp-admin-maintenance',
|
||||
@ -2623,301 +2620,6 @@ Example
|
||||
return $div;
|
||||
};
|
||||
|
||||
var supportKey = ApiConfig.supportMailbox;
|
||||
var checkAdminKey = function (priv) {
|
||||
if (!supportKey) { return; }
|
||||
return Hash.checkBoxKeyPair(priv, supportKey);
|
||||
};
|
||||
|
||||
create['support-list'] = function () {
|
||||
if (!supportKey || !APP.privateKey || !checkAdminKey(APP.privateKey)) { return; }
|
||||
// XXX NO NEED ANYMORE
|
||||
return;
|
||||
var $container = makeBlock('support-list'); // Msg.admin_supportListHint, .admin_supportListTitle
|
||||
var $div = $(h('div.cp-support-container')).appendTo($container);
|
||||
|
||||
var catContainer = h('div.cp-dropdown-container');
|
||||
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;
|
||||
if (key === 'all') {
|
||||
$div.find('.cp-support-list-ticket').show();
|
||||
return;
|
||||
}
|
||||
$div.find('.cp-support-list-ticket').hide();
|
||||
$div.find('.cp-support-list-ticket[data-cat="'+key+'"]').show();
|
||||
}, true);
|
||||
$drop.setValue('all');
|
||||
|
||||
var metadataMgr = common.getMetadataMgr();
|
||||
var privateData = metadataMgr.getPrivateData();
|
||||
var cat = privateData.category || '';
|
||||
var linkedId = cat.indexOf('-') !== -1 && cat.slice(8);
|
||||
|
||||
var hashesById = {};
|
||||
|
||||
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(msg, ['content', 'msg', 'content', 'sender', 'plan']) ||
|
||||
Util.find(msg, ['content', 'msg', 'content', 'sender', 'quota', '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');
|
||||
});
|
||||
};
|
||||
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 = [];
|
||||
var orderPremium = [];
|
||||
var orderNormal = [];
|
||||
var orderClosed = [];
|
||||
|
||||
Object.keys(hashesById).forEach(function (id) {
|
||||
var d = getTicketData(id);
|
||||
if (!d) { return; }
|
||||
if (d.closed) {
|
||||
return void orderClosed.push(id);
|
||||
}
|
||||
if (d.lastAdmin /* && !d.closed */) {
|
||||
return void orderAnswered.push(id);
|
||||
}
|
||||
if (d.premium /* && !d.lastAdmin && !d.closed */) {
|
||||
return void orderPremium.push(id);
|
||||
}
|
||||
orderNormal.push(id);
|
||||
//if (!d.premium && !d.lastAdmin && !d.closed) { return void orderNormal.push(id); }
|
||||
});
|
||||
|
||||
var cols = [$col1, $col2, $col3, $col4];
|
||||
[orderPremium, orderNormal, orderAnswered, orderClosed].forEach(function (list, j) {
|
||||
list.sort(sort);
|
||||
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);
|
||||
});
|
||||
var len;
|
||||
try {
|
||||
len = cols[j].find('div.cp-support-list-ticket').length;
|
||||
} catch (err) {
|
||||
UI.warn(Messages.error);
|
||||
return void console.error(err);
|
||||
}
|
||||
if (!len) {
|
||||
cols[j].hide();
|
||||
} else {
|
||||
cols[j].show();
|
||||
cols[j].find('.cp-support-count').text(len);
|
||||
}
|
||||
});
|
||||
};
|
||||
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;
|
||||
}, 200);
|
||||
|
||||
// Register to the "support" mailbox
|
||||
common.mailbox.subscribe(['supportadmin'], {
|
||||
onMessage: function (data) {
|
||||
/*
|
||||
Get ID of the ticket
|
||||
If we already have a div for this ID
|
||||
Push the message to the end of the ticket
|
||||
If it's a new ticket ID
|
||||
Make a new div for this ID
|
||||
*/
|
||||
var msg = data.content.msg;
|
||||
var hash = data.content.hash;
|
||||
var content = msg.content;
|
||||
var id = content.id;
|
||||
var $ticket = $div.find('.cp-support-list-ticket[data-id="'+id+'"]');
|
||||
|
||||
hashesById[id] = hashesById[id] || [];
|
||||
if (hashesById[id].indexOf(hash) === -1) {
|
||||
hashesById[id].push(data);
|
||||
}
|
||||
|
||||
if (msg.type === 'CLOSE') {
|
||||
// A ticket has been closed by the admins...
|
||||
if (!$ticket.length) { return; }
|
||||
$ticket.addClass('cp-support-list-closed');
|
||||
$ticket.append(APP.support.makeCloseMessage(content, hash));
|
||||
reorder();
|
||||
return;
|
||||
}
|
||||
if (msg.type !== 'TICKET') { return; }
|
||||
$ticket.removeClass('cp-support-list-closed');
|
||||
|
||||
if (!$ticket.length) {
|
||||
$ticket = APP.support.makeTicket($div, content, function (hideButton) {
|
||||
// the ticket will still be displayed until the worker confirms its deletion
|
||||
// so make it unclickable in the meantime
|
||||
hideButton.setAttribute('disabled', true);
|
||||
var error = false;
|
||||
nThen(function (w) {
|
||||
hashesById[id].forEach(function (d) {
|
||||
common.mailbox.dismiss(d, w(function (err) {
|
||||
if (err) {
|
||||
error = true;
|
||||
console.error(err);
|
||||
}
|
||||
}));
|
||||
});
|
||||
}).nThen(function () {
|
||||
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();
|
||||
}
|
||||
}
|
||||
$ticket.append(APP.support.makeMessage(content, hash));
|
||||
reorder();
|
||||
|
||||
if (linkedId) { to(); }
|
||||
}
|
||||
});
|
||||
return $container;
|
||||
};
|
||||
|
||||
create['support-priv'] = function () {
|
||||
if (!supportKey || !APP.privateKey || !checkAdminKey(APP.privateKey)) { return; }
|
||||
|
||||
var $div = makeBlock('support-priv', true); // Msg.admin_supportPrivHint, .admin_supportPrivTitle, .admin_supportPrivButton
|
||||
var $button = $div.find('button').click(function () {
|
||||
$button.remove();
|
||||
var $selectable = $(UI.dialog.selectable(APP.privateKey)).css({ 'max-width': '28em' });
|
||||
$div.append($selectable);
|
||||
});
|
||||
return $div;
|
||||
};
|
||||
|
||||
// XXX
|
||||
Messages.admin_supportNewHint = "Create or update the current support keys.";
|
||||
Messages.admin_supportNewTitle = "Initialize support";
|
||||
@ -3183,48 +2885,6 @@ Example
|
||||
refresh();
|
||||
return $block;
|
||||
};
|
||||
create['support-init'] = function () {
|
||||
var $div = makeBlock('support-init'); // Msg.admin_supportInitHint, .admin_supportInitTitle
|
||||
if (!supportKey) {
|
||||
(function () {
|
||||
return; // XXX old support can't be created anymore
|
||||
})();
|
||||
return $div;
|
||||
}
|
||||
if (!APP.privateKey || !checkAdminKey(APP.privateKey)) {
|
||||
$div.append(h('p', Messages.admin_supportInitPrivate));
|
||||
|
||||
var error = h('div.cp-admin-support-error');
|
||||
var input = h('input.cp-admin-add-private-key');
|
||||
var button = h('button.btn.btn-primary', Messages.admin_supportAddKey);
|
||||
|
||||
if (APP.privateKey && !checkAdminKey(APP.privateKey)) {
|
||||
$(error).text(Messages.admin_supportAddError);
|
||||
}
|
||||
|
||||
$div.append(h('div', [
|
||||
error,
|
||||
input,
|
||||
button
|
||||
]));
|
||||
|
||||
$(button).click(function () {
|
||||
var key = $(input).val();
|
||||
if (!checkAdminKey(key)) {
|
||||
$(input).val('');
|
||||
return void $(error).text(Messages.admin_supportAddError);
|
||||
}
|
||||
sFrameChan.query("Q_ADMIN_MAILBOX", key, function () {
|
||||
APP.privateKey = key;
|
||||
$('.cp-admin-support-init').hide();
|
||||
APP.$rightside.append(create['support-list']());
|
||||
APP.$rightside.append(create['support-priv']());
|
||||
});
|
||||
});
|
||||
return $div;
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
var getApi = function (cb) {
|
||||
return function () {
|
||||
|
||||
@ -34,13 +34,13 @@ define([
|
||||
const items = {};
|
||||
|
||||
let blocks = sidebar.blocks = {};
|
||||
blocks.labelledInput = (label, input) => {
|
||||
blocks.labelledInput = (label, input, inputBlock) => {
|
||||
let uid = Util.uid();
|
||||
let id = `cp-${app}-item-${uid}`;
|
||||
input.setAttribute('id', id);
|
||||
return [
|
||||
h('label', { for: id }, label),
|
||||
input,
|
||||
inputBlock || input,
|
||||
];
|
||||
};
|
||||
blocks.button = (type, icon, text) => {
|
||||
@ -63,6 +63,16 @@ define([
|
||||
blocks.input = (attr) => {
|
||||
return h('input', attr);
|
||||
};
|
||||
blocks.inputButton = (input, button, opts) => {
|
||||
if (opts.onEnterDelegate) {
|
||||
$(input).on('keypress', e => {
|
||||
if (e.which === 13) {
|
||||
$(button).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
return h('div.cp-sidebar-input-block', [input, button]);
|
||||
};
|
||||
blocks.text = (value) => {
|
||||
return h('span', value);
|
||||
};
|
||||
|
||||
@ -647,6 +647,45 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
var searchAdmin = (ctx, data, cId, cb) => {
|
||||
if (!ctx.adminRdyEvt) { return void cb({ error: 'EFORBIDDEN' }); }
|
||||
let tags = data.tags || [];
|
||||
let text = (data.text || '').toLowerCase();
|
||||
console.error(tags, text);
|
||||
ctx.adminRdyEvt.reg(() => {
|
||||
let doc = ctx.adminDoc.proxy;
|
||||
let t = doc.tickets;
|
||||
|
||||
let all = {};
|
||||
let add = (id, data, category) => {
|
||||
let clone = Util.clone(data);
|
||||
clone.category = category;
|
||||
all[id] = clone;
|
||||
};
|
||||
['active', 'pending', 'closed'].some(cat => {
|
||||
let tickets = t[cat];
|
||||
return Object.keys(tickets).some(id => {
|
||||
let ticket = tickets[id];
|
||||
// Check if this ticket uses at least one selected tag
|
||||
let hasTag = !tags.length || (ticket.tags || []).some(tag => {
|
||||
return tags.includes(tag);
|
||||
});
|
||||
if (!hasTag) { return; }
|
||||
// Filter by searched text within these tags
|
||||
let id64 = Util.hexToBase64(id).slice(0,10);
|
||||
if (text === id64) { // If ticket ID found, stop search and return result
|
||||
all = {};
|
||||
add(id, ticket, cat);
|
||||
return true;
|
||||
}
|
||||
let hasText = !text || ticket.title.toLowerCase().includes(text);
|
||||
if (!hasText) { return; }
|
||||
add(id, ticket, cat);
|
||||
});
|
||||
});
|
||||
cb({ tickets: all });
|
||||
});
|
||||
};
|
||||
var setTagsAdmin = (ctx, data, cId, cb) => {
|
||||
if (!ctx.adminRdyEvt) { return void cb({ error: 'EFORBIDDEN' }); }
|
||||
ctx.adminRdyEvt.reg(() => {
|
||||
@ -1284,6 +1323,9 @@ define([
|
||||
if (cmd === 'USE_RECORDED') {
|
||||
return void useRecorded(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'SEARCH_ADMIN') {
|
||||
return void searchAdmin(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'FILTER_TAGS_ADMIN') {
|
||||
return void filterTagsAdmin(ctx, data, clientId, cb);
|
||||
}
|
||||
|
||||
@ -78,5 +78,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.cp-support-search-container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +55,9 @@ define([
|
||||
|
||||
// XXX
|
||||
Messages.support_pending = "Pending tickets:";
|
||||
Messages.support_pending_tag = "Pending";
|
||||
Messages.support_active_tag = "Active";
|
||||
Messages.support_closed_tag = "Closed";
|
||||
/*
|
||||
Messages.support_activeListTitle = "Active tickets";
|
||||
Messages.support_pendingListTitle = "Pending tickets";
|
||||
@ -89,6 +92,8 @@ define([
|
||||
Messages.support_legacyDump = "Export all";
|
||||
Messages.support_legacyClear = "Delete from my account";
|
||||
|
||||
Messages.support_searchLabel = "Search (title or ticketId)";
|
||||
|
||||
var andThen = function (common, $container, linkedTicket) {
|
||||
const sidebar = Sidebar.create(common, 'support', $container);
|
||||
const blocks = sidebar.blocks;
|
||||
@ -96,6 +101,42 @@ define([
|
||||
APP.allTags = [];
|
||||
APP.openTicketCategory = Util.mkEvent();
|
||||
|
||||
var sortTicket = tickets => (c1, c2) => {
|
||||
return tickets[c2].time - tickets[c1].time;
|
||||
};
|
||||
const onShowTicket = function (ticket, channel, data, done) {
|
||||
APP.module.execCommand('LOAD_TICKET_ADMIN', {
|
||||
channel: channel,
|
||||
curvePublic: data.authorKey,
|
||||
supportKey: data.supportKey
|
||||
}, function (obj) {
|
||||
if (!Array.isArray(obj)) {
|
||||
console.error(obj && obj.error);
|
||||
done(false);
|
||||
return void UI.warn(Messages.error);
|
||||
}
|
||||
var $ticket = $(ticket);
|
||||
obj.forEach(function (msg) {
|
||||
// Only add notifications channel if this is coming from the other user
|
||||
if (!data.notifications && msg.sender.drive) {
|
||||
data.notifications = Util.find(msg, ['sender', 'notifications']);
|
||||
}
|
||||
if (msg.close) {
|
||||
$ticket.addClass('cp-support-list-closed');
|
||||
return $ticket.append(APP.support.makeCloseMessage(msg));
|
||||
}
|
||||
if (msg.legacy && msg.messages) {
|
||||
msg.messages.forEach(c => {
|
||||
$ticket.append(APP.support.makeMessage(c));
|
||||
});
|
||||
return;
|
||||
}
|
||||
$ticket.append(APP.support.makeMessage(msg));
|
||||
});
|
||||
done(true);
|
||||
});
|
||||
};
|
||||
|
||||
// Support panel functions
|
||||
let open = [];
|
||||
let refreshAll = function () {};
|
||||
@ -154,40 +195,12 @@ define([
|
||||
col1 = col2 = col3 = col5;
|
||||
}
|
||||
$container.append([col1, col2, col3]);
|
||||
var sortTicket = function (c1, c2) {
|
||||
return tickets[c2].time - tickets[c1].time;
|
||||
};
|
||||
|
||||
const onShow = function (ticket, channel, data, done) {
|
||||
APP.module.execCommand('LOAD_TICKET_ADMIN', {
|
||||
channel: channel,
|
||||
curvePublic: data.authorKey,
|
||||
supportKey: data.supportKey
|
||||
}, function (obj) {
|
||||
if (!Array.isArray(obj)) {
|
||||
console.error(obj && obj.error);
|
||||
done();
|
||||
return void UI.warn(Messages.error);
|
||||
onShowTicket(ticket, channel, data, (success) => {
|
||||
if (success) {
|
||||
if (!open.includes(channel)) { open.push(channel); }
|
||||
}
|
||||
var $ticket = $(ticket);
|
||||
obj.forEach(function (msg) {
|
||||
// Only add notifications channel if this is coming from the other user
|
||||
if (!data.notifications && msg.sender.drive) {
|
||||
data.notifications = Util.find(msg, ['sender', 'notifications']);
|
||||
}
|
||||
if (msg.close) {
|
||||
$ticket.addClass('cp-support-list-closed');
|
||||
return $ticket.append(APP.support.makeCloseMessage(msg));
|
||||
}
|
||||
if (msg.legacy && msg.messages) {
|
||||
msg.messages.forEach(c => {
|
||||
$ticket.append(APP.support.makeMessage(c));
|
||||
});
|
||||
return;
|
||||
}
|
||||
$ticket.append(APP.support.makeMessage(msg));
|
||||
});
|
||||
if (!open.includes(channel)) { open.push(channel); }
|
||||
done();
|
||||
});
|
||||
};
|
||||
@ -272,7 +285,7 @@ define([
|
||||
// Show tickets, reload the previously open ones and cal back
|
||||
// once everything is loaded
|
||||
let n = nThen;
|
||||
Object.keys(tickets).sort(sortTicket).forEach(function (channel) {
|
||||
Object.keys(tickets).sort(sortTicket(tickets)).forEach(function (channel) {
|
||||
// Update allTags
|
||||
var d = tickets[channel];
|
||||
(d.tags || []).forEach(tag => {
|
||||
@ -386,12 +399,30 @@ define([
|
||||
'closed-list'
|
||||
]
|
||||
},
|
||||
'search': {
|
||||
icon: undefined,
|
||||
content: [
|
||||
'filter',
|
||||
'search'
|
||||
],
|
||||
onOpen: () => {
|
||||
APP.searchAutoRefresh = true;
|
||||
setTimeout(() => {
|
||||
$('.cp-support-search-input').focus();
|
||||
});
|
||||
}
|
||||
},
|
||||
'settings': {
|
||||
icon: undefined,
|
||||
content: [
|
||||
'notifications',
|
||||
'recorded'
|
||||
]
|
||||
],
|
||||
onOpen: () => {
|
||||
setTimeout(() => {
|
||||
$('.cp-support-recorded-id').focus();
|
||||
});
|
||||
}
|
||||
},
|
||||
'ticket': {
|
||||
icon: undefined,
|
||||
@ -400,6 +431,9 @@ define([
|
||||
],
|
||||
onOpen: () => {
|
||||
APP.openTicketCategory.fire();
|
||||
setTimeout(() => {
|
||||
$('.cp-support-newticket-paste').focus();
|
||||
});
|
||||
}
|
||||
},
|
||||
'legacy': {
|
||||
@ -450,6 +484,81 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
sidebar.addItem('search', cb => {
|
||||
|
||||
let inputSearch = blocks.input({type:'text', class: 'cp-support-search-input'});
|
||||
let button = blocks.button('primary', 'fa-search');
|
||||
let inputBlock = blocks.inputButton(inputSearch, button, { onEnterDelegate: true });
|
||||
let searchBlock = blocks.labelledInput(Messages.support_searchLabel,
|
||||
inputSearch, inputBlock);
|
||||
|
||||
let list = blocks.box([], 'cp-support-container');
|
||||
let container = blocks.box([searchBlock, list], 'cp-support-search-container');
|
||||
let $list = $(list);
|
||||
let searchText = '';
|
||||
APP.searchAutoRefresh = false;
|
||||
|
||||
let redraw = (_cb) => {
|
||||
let cb = _cb || function () {};
|
||||
$list.empty();
|
||||
let tags = APP.filterTags || [];
|
||||
let text = searchText;
|
||||
if (!text.length && !tags.length) { return void cb(); }
|
||||
APP.module.execCommand('SEARCH_ADMIN', { text, tags }, function (obj) {
|
||||
cb();
|
||||
if (obj && obj.error) {
|
||||
console.error(obj && obj.error);
|
||||
return void UI.warn(Messages.error);
|
||||
}
|
||||
$list.empty();
|
||||
let tickets = obj.tickets || {};
|
||||
|
||||
const onShow = onShowTicket;
|
||||
const onHide = function (ticket, channel, data, done) {
|
||||
$(ticket).find('.cp-support-list-message').remove();
|
||||
done();
|
||||
};
|
||||
const onTag = () => {};
|
||||
onTag.readOnly = true;
|
||||
onTag.getAllTags = () => [];
|
||||
Object.keys(tickets).sort(sortTicket(tickets)).forEach(id => {
|
||||
let content = tickets[id];
|
||||
content.tags = content.tags || [];
|
||||
|
||||
let catTag = Messages[`support_${content.category}_tag`];
|
||||
if (catTag) {
|
||||
// Msg.support_active_tag.support_pending_tag.support_closed_tag
|
||||
content.tags.unshift(catTag.toUpperCase());
|
||||
}
|
||||
|
||||
var ticket = APP.support.makeTicket({
|
||||
id,
|
||||
content,
|
||||
onTag, onShow, onHide
|
||||
});
|
||||
$list.append(ticket);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
let $input = $(inputSearch);
|
||||
let $button = $(button);
|
||||
Util.onClickEnter($button, function () {
|
||||
$button.prop('disabled', 'disabled');
|
||||
searchText = $input.val().trim();
|
||||
redraw(() => {
|
||||
APP.searchAutoRefresh = true;
|
||||
$button.prop('disabled', false);
|
||||
});
|
||||
});
|
||||
|
||||
events.REFRESH_FILTER.reg(() => {
|
||||
if (!APP.searchAutoRefresh) { return; }
|
||||
redraw();
|
||||
});
|
||||
cb(container);
|
||||
}, { noTitle: true, noHint: true });
|
||||
|
||||
sidebar.addItem('filter', cb => {
|
||||
let container = blocks.box([], 'cp-support-filter-container');
|
||||
let $container = $(container);
|
||||
@ -532,7 +641,8 @@ define([
|
||||
Messages.kanban_delete
|
||||
], []);
|
||||
let labelledList = blocks.labelledInput(Messages.support_recordedList, list);
|
||||
let inputId = blocks.input({type:'text', maxlength: 20 });
|
||||
let inputId = blocks.input({type:'text', class: 'cp-support-recorded-id',
|
||||
maxlength: 20 });
|
||||
let inputContent = blocks.textArea();
|
||||
let labelId = blocks.labelledInput(Messages.support_recordedId, inputId);
|
||||
let labelContent = blocks.labelledInput(Messages.support_recordedContent, inputContent);
|
||||
@ -637,6 +747,7 @@ define([
|
||||
let reset = blocks.button('danger-alt', 'fa-times', Messages.form_reset);
|
||||
|
||||
let paste = blocks.textArea({
|
||||
class: 'cp-support-newticket-paste',
|
||||
placeholder: Messages.support_pasteUserData
|
||||
});
|
||||
let inputs = h('div.cp-moderation-userdata-inputs', [ labelName, labelChan, labelKey ]);
|
||||
@ -817,6 +928,7 @@ Attachments:${JSON.stringify(msg.attachments, 0, 2)}`;
|
||||
});
|
||||
};
|
||||
if (!$ticket.length) {
|
||||
content.category = 'closed'; // Consider ticket closed
|
||||
$ticket = APP.support.makeTicket({id, content, onMove});
|
||||
$div.append($ticket);
|
||||
}
|
||||
|
||||
@ -421,6 +421,7 @@ define([
|
||||
if (!err) { UI.log(Messages.shareSuccess); }
|
||||
});
|
||||
});
|
||||
if (content.category === 'closed') { url = undefined; }
|
||||
|
||||
|
||||
// Load & open ticket
|
||||
@ -448,6 +449,7 @@ define([
|
||||
});
|
||||
};
|
||||
Util.onClickEnter($show, adminOpen);
|
||||
if (!onShow) { show = undefined; }
|
||||
|
||||
// Move active/pending
|
||||
let move;
|
||||
@ -465,6 +467,7 @@ define([
|
||||
tag = h('button.btn.btn-secondary.fa.fa-tags', {
|
||||
title: Messages.fm_tagsName
|
||||
});
|
||||
if (onTag.readOnly) { tag = undefined; }
|
||||
tagsContainer = h('div');
|
||||
tagsList = h('div.cp-tags-list');
|
||||
let $list = $(tagsList);
|
||||
@ -475,6 +478,7 @@ define([
|
||||
});
|
||||
};
|
||||
redrawTags(content.tags);
|
||||
console.error(content.tags);
|
||||
|
||||
let $tags = $(tagsContainer).hide();
|
||||
let input = UI.dialog.textInput({id: `cp-${Util.uid()}`});
|
||||
@ -538,6 +542,7 @@ define([
|
||||
$(close).remove();
|
||||
onClose(ticket, id, content);
|
||||
});
|
||||
if (!onClose) { $(close).remove(); }
|
||||
|
||||
UI.confirmButton(remove, {
|
||||
classes: 'btn-danger'
|
||||
@ -564,7 +569,8 @@ define([
|
||||
$ticket.append(newForm);
|
||||
};
|
||||
if (form) { addForm(); }
|
||||
$(answer).click(addForm);
|
||||
Util.onClickEnter($(answer), addForm);
|
||||
if (!onReply) { $(answer).remove(); }
|
||||
|
||||
return ticket;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user