From 47284dc1ec84c8a2da41eaf690a291927a601eb1 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 28 Feb 2024 12:37:00 +0100 Subject: [PATCH] New support: move tickets between active and pending --- www/common/outer/support.js | 23 +++++++++++++++++++++++ www/moderation/inner.js | 17 ++++++++++++++++- www/support/ui.js | 17 +++++++++++++++-- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/www/common/outer/support.js b/www/common/outer/support.js index d0af8b92f..7137574a5 100644 --- a/www/common/outer/support.js +++ b/www/common/outer/support.js @@ -523,6 +523,26 @@ define([ }); }; + var moveTicketAdmin = function (ctx, data, cId, cb) { + if (!ctx.adminRdyEvt) { return void cb({ error: 'EFORBIDDEN' }); } + let ticketId = data.channel; + let from = data.from; + let to = data.to; + ctx.adminRdyEvt.reg(() => { + let doc = ctx.adminDoc.proxy; + let fromDoc = doc.tickets[from]; + let toDoc = doc.tickets[to]; + if (!from || !to) { return void cb({ error: 'EINVAL' }); } + let ticket = fromDoc[ticketId]; + if (!ticket || toDoc[ticketId]) { return void cb({ error: 'CANT_MOVE' }); } + toDoc[ticketId] = ticket; + delete fromDoc[ticketId]; + Realtime.whenRealtimeSyncs(ctx.adminDoc.realtime, function () { + cb({ moved: true }); + }); + }); + }; + // Mailbox events var notifyClient = function (ctx, admin, type, channel) { @@ -1028,6 +1048,9 @@ define([ if (cmd === 'CLOSE_TICKET_ADMIN') { return void closeTicketAdmin(ctx, data, clientId, cb); } + if (cmd === 'MOVE_TICKET_ADMIN') { + return void moveTicketAdmin(ctx, data, clientId, cb); + } // Admin commands if (cmd === 'GET_PRIVATE_KEY') { return void getAdminKey(ctx, data, clientId, cb); diff --git a/www/moderation/inner.js b/www/moderation/inner.js index 1f4cc0ded..3b60ce756 100644 --- a/www/moderation/inner.js +++ b/www/moderation/inner.js @@ -177,6 +177,21 @@ define([ refreshAll(); }); }; + const onMove = function (ticket, channel, data) { + APP.module.execCommand('MOVE_TICKET_ADMIN', { + channel: channel, + from: type, + to: onMove.isTicketActive ? 'pending' : 'active' + }, function (obj) { + if (obj && obj.error) { + console.error(obj && obj.error); + return void UI.warn(Messages.error); + } + refreshAll(); + }); + + }; + onMove.isTicketActive = type === 'active'; Object.keys(tickets).sort(sortTicket).forEach(function (channel) { var d = tickets[channel]; @@ -184,7 +199,7 @@ define([ id: channel, content: d, form: activeForms[channel], - onShow, onHide, onClose, onReply + onShow, onHide, onClose, onReply, onMove }); var container; diff --git a/www/support/ui.js b/www/support/ui.js index e9d78b730..e55847c99 100644 --- a/www/support/ui.js +++ b/www/support/ui.js @@ -17,6 +17,8 @@ define([ Messages.support_team = "The Support Team"; // XXX Messages.support_answerAs = "Answer as {0}"; // XXX + Messages.support_movePending = "Move to pending"; + Messages.support_moveActive = "Move to active"; var getDebuggingData = function (ctx, data) { var common = ctx.common; @@ -300,7 +302,7 @@ define([ }; var makeTicket = function (ctx, opts) { - let { id, content, form, onShow, onHide, onClose, onReply, onDelete } = opts; + let { id, content, form, onShow, onHide, onClose, onReply, onMove, onDelete } = opts; var common = ctx.common; var metadataMgr = common.getMetadataMgr(); var privateData = metadataMgr.getPrivateData(); @@ -361,7 +363,18 @@ define([ }); }; Util.onClickEnter($show, adminOpen); - adminActions = h('span.cp-support-title-buttons', [ url, show ]); + + let settings; + if (onMove) { + let text = onMove.isTicketActive ? Messages.support_movePending + : Messages.support_moveActive; + settings = h('button.btn.btn-secondary.fa.fa-hdd-o', { title: text }); + Util.onClickEnter($(settings), function () { + onMove(ticket, id, content); + }); + } + + adminActions = h('span.cp-support-title-buttons', [ url, settings, show ]); } let isPremium = content.premium ? '.cp-support-ispremium' : '';