mirror of https://github.com/xwiki-labs/cryptpad
New support: add tags to tickets
This commit is contained in:
parent
c10176585a
commit
ec5bfc236f
|
@ -5,10 +5,12 @@
|
|||
*/
|
||||
|
||||
@import (reference) "./colortheme-all.less";
|
||||
@import (reference) './tokenfield.less';
|
||||
.support_main () {
|
||||
@ticket-bg: @cp_support-bg;
|
||||
@msg-bg: @cp_support-msg-bg;
|
||||
@fromme-bg: @cp_support-header-bg;
|
||||
.tokenfield_main();
|
||||
.cp-support-form-container {
|
||||
div {
|
||||
margin-bottom: 10px;
|
||||
|
|
|
@ -398,6 +398,7 @@ define([
|
|||
editKeyStr: seed
|
||||
}
|
||||
});
|
||||
console.error(hash);
|
||||
loadAdminDoc(ctx, hash, waitFor());
|
||||
}).nThen(() => {
|
||||
console.log('Support admin loaded');
|
||||
|
@ -646,6 +647,23 @@ define([
|
|||
});
|
||||
};
|
||||
|
||||
var setTagsAdmin = (ctx, data, cId, cb) => {
|
||||
if (!ctx.adminRdyEvt) { return void cb({ error: 'EFORBIDDEN' }); }
|
||||
let id = data.id;
|
||||
ctx.adminRdyEvt.reg(() => {
|
||||
let doc = ctx.adminDoc.proxy;
|
||||
let t = doc.tickets;
|
||||
let chan = data.channel;
|
||||
|
||||
let ticket = t.active[chan] || t.pending[chan] || t.closed[chan];
|
||||
ticket.tags = data.tags || [];
|
||||
Realtime.whenRealtimeSyncs(ctx.adminDoc.realtime, function () {
|
||||
cb({done:true});
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var clearLegacy = function (ctx, data, cId, cb) {
|
||||
let proxy = ctx.store.proxy;
|
||||
ctx.store.mailbox.close('supportadmin', function () {
|
||||
|
@ -1245,6 +1263,9 @@ define([
|
|||
if (cmd === 'USE_RECORDED') {
|
||||
return void useRecorded(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'SET_TAGS_ADMIN') {
|
||||
return void setTagsAdmin(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'GET_LEGACY') {
|
||||
return void getLegacy(ctx, data, clientId, cb);
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ define([
|
|||
// Support panel functions
|
||||
let open = [];
|
||||
let refreshAll = function () {};
|
||||
let allTags = [];
|
||||
let refresh = ($container, type, _cb) => {
|
||||
let cb = Util.mkAsync(_cb || function () {});
|
||||
APP.module.execCommand('LIST_TICKETS_ADMIN', {
|
||||
|
@ -228,21 +229,44 @@ define([
|
|||
}
|
||||
refreshAll();
|
||||
});
|
||||
|
||||
};
|
||||
onMove.isTicketActive = type === 'active';
|
||||
|
||||
const onTag = (channel, tags) => {
|
||||
APP.module.execCommand('SET_TAGS_ADMIN', {
|
||||
channel, tags
|
||||
}, function (obj) {
|
||||
if (obj && obj.error) {
|
||||
console.error(obj && obj.error);
|
||||
return void UI.warn(Messages.error);
|
||||
}
|
||||
(tags || []).forEach(tag => {
|
||||
if (!allTags.includes(tag)) { allTags.push(tag); }
|
||||
});
|
||||
//UI.log(Messags.saved);
|
||||
//refreshAll();
|
||||
});
|
||||
};
|
||||
onTag.getAllTags = () => {
|
||||
return allTags || [];
|
||||
};
|
||||
|
||||
// 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) {
|
||||
// Update allTags
|
||||
var d = tickets[channel];
|
||||
(d.tags || []).forEach(tag => {
|
||||
if (!allTags.includes(tag)) { allTags.push(tag); }
|
||||
});
|
||||
// Make ticket
|
||||
var ticket = APP.support.makeTicket({
|
||||
id: channel,
|
||||
content: d,
|
||||
form: activeForms[channel],
|
||||
recorded: APP.recorded,
|
||||
onShow, onHide, onClose, onReply, onMove
|
||||
onShow, onHide, onClose, onReply, onMove, onTag
|
||||
});
|
||||
|
||||
var container;
|
||||
|
@ -283,6 +307,7 @@ define([
|
|||
};
|
||||
}));
|
||||
}).nThen(waitFor => {
|
||||
allTags = [];
|
||||
refresh($(activeContainer), 'active', waitFor());
|
||||
refresh($(pendingContainer), 'pending', waitFor());
|
||||
refresh($(closedContainer), 'closed', waitFor());
|
||||
|
|
|
@ -385,7 +385,7 @@ define([
|
|||
|
||||
var makeTicket = function (ctx, opts) {
|
||||
let { id, content, form, recorded,
|
||||
onShow, onHide, onClose, onReply, onMove, onDelete } = opts;
|
||||
onShow, onHide, onClose, onReply, onMove, onDelete, onTag } = opts;
|
||||
var common = ctx.common;
|
||||
var metadataMgr = common.getMetadataMgr();
|
||||
var privateData = metadataMgr.getPrivateData();
|
||||
|
@ -406,12 +406,13 @@ define([
|
|||
var adminClasses = '';
|
||||
var adminOpen;
|
||||
var ticket;
|
||||
let tagsContainer;
|
||||
if (ctx.isAdmin) {
|
||||
// Admin custom style
|
||||
adminClasses = `.cp-not-loaded`;
|
||||
// Admin actions
|
||||
let show = h('button.btn.btn-primary.cp-support-expand', Messages.admin_support_open);
|
||||
let $show = $(show);
|
||||
|
||||
// Copy URL
|
||||
let url = h('button.btn.fa.fa-link', { title: Messages.share_linkCopy, });
|
||||
$(url).click(function (e) {
|
||||
e.stopPropagation();
|
||||
|
@ -422,6 +423,9 @@ define([
|
|||
});
|
||||
|
||||
|
||||
// Load & open ticket
|
||||
let show = h('button.btn.btn-primary.cp-support-expand', Messages.admin_support_open);
|
||||
let $show = $(show);
|
||||
let visible = false;
|
||||
adminOpen = function (force, cb) {
|
||||
var $ticket = $(ticket);
|
||||
|
@ -445,17 +449,52 @@ define([
|
|||
};
|
||||
Util.onClickEnter($show, adminOpen);
|
||||
|
||||
let settings;
|
||||
// Move active/pending
|
||||
let move;
|
||||
if (onMove) {
|
||||
let text = onMove.isTicketActive ? Messages.support_movePending
|
||||
: Messages.support_moveActive;
|
||||
settings = h('button.btn.btn-secondary.fa.fa-archive', { title: text });
|
||||
Util.onClickEnter($(settings), function () {
|
||||
move = h('button.btn.btn-secondary.fa.fa-archive', { title: text });
|
||||
Util.onClickEnter($(move), function () {
|
||||
onMove(ticket, id, content);
|
||||
});
|
||||
}
|
||||
|
||||
adminActions = h('span.cp-support-title-buttons', [ url, settings, show ]);
|
||||
let tag;
|
||||
if (onTag && onTag.getAllTags) {
|
||||
tag = h('button.btn.btn-secondary.fa.fa-tags', {
|
||||
title: Messages.fm_tagsName
|
||||
});
|
||||
tagsContainer = h('div');
|
||||
let $tags = $(tagsContainer).hide();
|
||||
let input = UI.dialog.textInput({id: `cp-${Util.uid()}`});
|
||||
$tags.append(input);
|
||||
let existing = onTag.getAllTags();
|
||||
let _field = UI.tokenField(input, existing).preventDuplicates(function (val) {
|
||||
UI.warn(Messages._getKey('tags_duplicate', [val]));
|
||||
});
|
||||
_field.setTokens(content.tags || []);
|
||||
$tags.find('.token').off('click');
|
||||
|
||||
let commitTags = function () {
|
||||
setTimeout(() => {
|
||||
let newTags = Util.deduplicateString(_field.getTokens().map(function (t) {
|
||||
return t.toLowerCase();
|
||||
}));
|
||||
$tags.find('.token').off('click');
|
||||
onTag(id, newTags);
|
||||
});
|
||||
};
|
||||
_field.tokenfield.on('tokenfield:createdtoken', commitTags);
|
||||
_field.tokenfield.on('tokenfield:editedoken', commitTags);
|
||||
_field.tokenfield.on('tokenfield:removedtoken', commitTags);
|
||||
|
||||
Util.onClickEnter($(tag), () => {
|
||||
$tags.toggle();
|
||||
});
|
||||
}
|
||||
|
||||
adminActions = h('span.cp-support-title-buttons', [ url, move, tag, show ]);
|
||||
}
|
||||
|
||||
let isPremium = content.premium ? '.cp-support-ispremium' : '';
|
||||
|
@ -471,6 +510,7 @@ define([
|
|||
h('span', new Date(content.time).toLocaleString()),
|
||||
adminActions,
|
||||
]),
|
||||
tagsContainer,
|
||||
actions
|
||||
]);
|
||||
ticket.open = adminOpen;
|
||||
|
|
Loading…
Reference in New Issue