From 9aafd5f3c5594522b681b608386852e6625bbea8 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 10 Jun 2020 18:42:46 +0200 Subject: [PATCH 1/3] Add category and attachments to support tickets --- customize.dist/src/less2/include/support.less | 3 + www/support/inner.js | 3 +- www/support/ui.js | 135 +++++++++++++++++- 3 files changed, 132 insertions(+), 9 deletions(-) diff --git a/customize.dist/src/less2/include/support.less b/customize.dist/src/less2/include/support.less index 890ba810d..1d62157de 100644 --- a/customize.dist/src/less2/include/support.less +++ b/customize.dist/src/less2/include/support.less @@ -4,6 +4,9 @@ @msg-bg: #eee; @fromme-bg: #ddd; .cp-support-form-container { + div { + margin-bottom: 10px; + } [type="text"] { width: @sidebar_button-width; margin-bottom: 10px; diff --git a/www/support/inner.js b/www/support/inner.js index 3d907421d..089af5230 100644 --- a/www/support/inner.js +++ b/www/support/inner.js @@ -166,8 +166,6 @@ define([ var form = APP.support.makeForm(); - $div.find('button').before(form); - var id = Util.uid(); $div.find('button').click(function () { @@ -183,6 +181,7 @@ define([ $('.cp-sidebarlayout-category[data-category="tickets"]').click(); } }); + $div.find('button').before(form); return $div; }; diff --git a/www/support/ui.js b/www/support/ui.js index 04330734e..e95a8e8cf 100644 --- a/www/support/ui.js +++ b/www/support/ui.js @@ -6,8 +6,9 @@ define([ '/common/common-hash.js', '/common/common-util.js', '/common/clipboard.js', + '/common/common-ui-elements.js', '/customize/messages.js', -], function ($, ApiConfig, h, UI, Hash, Util, Clipboard, Messages) { +], function ($, ApiConfig, h, UI, Hash, Util, Clipboard, UIElements, Messages) { var send = function (ctx, id, type, data, dest) { var common = ctx.common; @@ -61,9 +62,14 @@ define([ }; var sendForm = function (ctx, id, form, dest) { - var $title = $(form).find('.cp-support-form-title'); - var $content = $(form).find('.cp-support-form-msg'); + var $form = $(form); + var $cat = $form.find('.cp-support-form-category'); + var $title = $form.find('.cp-support-form-title'); + var $content = $form.find('.cp-support-form-msg'); + var $attachments = $form.find('.cp-support-form-attachments'); + + var category = $cat.val().trim(); var title = $title.val().trim(); if (!title) { return void UI.alert(Messages.support_formTitleError); @@ -72,18 +78,38 @@ define([ if (!content) { return void UI.alert(Messages.support_formContentError); } + $cat.val(''); $content.val(''); $title.val(''); + var attachments = []; + $attachments.find('> span').each(function (i, el) { + var $el = $(el); + attachments.push({ + href: $el.attr('data-href'), + name: $el.attr('data-name') + }); + }); + send(ctx, id, 'TICKET', { + category: category, title: title, + attachments: attachments, message: content, }, dest); return true; }; - var makeForm = function (cb, title) { +Messages.support_cat_account = "User account"; // XXX +Messages.support_cat_data = "Loss of content"; // XXX +Messages.support_cat_bug = "Bug report"; // XXX +Messages.support_cat_other = "Other"; // XXX +Messages.support_category = "Category"; // XXX +Messages.support_attachments = "Attachments"; // XXX +Messages.support_addAttachment = "Add attachment"; // XXX + + var makeForm = function (ctx, cb, title) { var button; if (typeof(cb) === "function") { @@ -93,8 +119,34 @@ define([ var cancel = title ? h('button.btn.btn-secondary', Messages.cancel) : undefined; + var category = h('input.cp-support-form-category', { + type: 'hidden', + value: '' + }); + var categories = ['account', 'data', 'bug', 'other'].map(function (key) { + return { + tag: 'a', + content: h('span', Messages['support_cat_'+key]), + action: function () { + $(category).val(key); + } + }; + }); + var catContainer = h('div.cp-dropdown-container' + (title ? '.cp-hidden': '')); + var dropdownCfg = { + text: Messages.support_category, + options: categories, + container: $(catContainer), + isSelect: true + }; + var $drop = UIElements.createDropdown(dropdownCfg); + + var attachments, addAttachment; + var content = [ h('hr'), + category, + catContainer, h('input.cp-support-form-title' + (title ? '.cp-hidden' : ''), { placeholder: Messages.support_formTitle, type: 'text', @@ -104,11 +156,51 @@ define([ h('textarea.cp-support-form-msg', { placeholder: Messages.support_formMessage }), + h('label', Messages.support_attachments), + attachments = h('div.cp-support-form-attachments'), + addAttachment = h('button', Messages.support_addAttachment), h('hr'), button, cancel ]; + $(addAttachment).click(function () { + var $input = $('', { + 'type': 'file', + 'style': 'display: none;', + 'multiple': 'multiple', + 'accept': 'image/*' + }).on('change', function (e) { + var files = Util.slice(e.target.files); + files.forEach(function (file) { + var ev = {}; + ev.callback = function (data) { + var x, a; + var span = h('span', { + 'data-name': data.name, + 'data-href': data.url + }, [ + x = h('i.fa.fa-times'), + a = h('a', { + href: '#' + }, data.name) + ]); + $(x).click(function () { + $(span).remove(); + }); + $(a).click(function (e) { + e.preventDefault(); + ctx.common.openURL(data.url); + }); + + $(attachments).append(span); + }; + ctx.FM.handleFile(file, ev); + }); + }); + $input.click(); + }); + var form = h('div.cp-support-form-container', content); $(cancel).click(function () { @@ -125,6 +217,7 @@ define([ var privateData = metadataMgr.getPrivateData(); var ticketTitle = content.title + ' (#' + content.id + ')'; + var ticketCategory; var answer = h('button.btn.btn-primary.cp-support-answer', Messages.support_answer); var close = h('button.btn.btn-danger.cp-support-close', Messages.support_close); var hide = h('button.btn.btn-danger.cp-support-hide', Messages.support_remove); @@ -137,6 +230,7 @@ define([ var url; if (ctx.isAdmin) { + ticketCategory = Messages['support_cat_'+(content.category || 'other')] + ' - '; url = h('button.btn.btn-primary.fa.fa-clipboard'); $(url).click(function () { var link = privateData.origin + privateData.pathname + '#' + 'support-' + content.id; @@ -148,7 +242,7 @@ define([ var $ticket = $(h('div.cp-support-list-ticket', { 'data-id': content.id }, [ - h('h2', [ticketTitle, url]), + h('h2', [ticketCategory, ticketTitle, url]), actions ])); @@ -179,7 +273,7 @@ define([ $(answer).click(function () { $ticket.find('.cp-support-form-container').remove(); $(actions).hide(); - var form = makeForm(function () { + var form = makeForm(ctx, function () { var sent = sendForm(ctx, content.id, form, content.sender); if (sent) { $(actions).show(); @@ -215,6 +309,20 @@ define([ ev.stopPropagation(); }); + var attachments = (content.attachments || []).map(function (obj) { + if (!obj || !obj.name || !obj.href) { return; } + var a = h('a', { + href: '#' + }, obj.name) + $(a).click(function (e) { + e.preventDefault(); + ctx.common.openURL(obj.href); + }); + return h('span', [ + a + ]); + }); + var adminClass = (fromAdmin? '.cp-support-fromadmin': ''); var premiumClass = (fromPremium && !fromAdmin? '.cp-support-frompremium': ''); var name = Util.fixHTML(content.sender.name) || Messages.anonymous; @@ -226,6 +334,7 @@ define([ h('span.cp-support-message-time', content.time ? new Date(content.time).toLocaleString() : '') ]), h('pre.cp-support-message-content', content.message), + h('div', attachments), isAdmin ? userData : undefined, ]); }; @@ -257,10 +366,22 @@ define([ adminKeys: Array.isArray(ApiConfig.adminKeys)? ApiConfig.adminKeys.slice(): [], }; + var fmConfig = { + body: $('body'), + onUploaded: function (ev, data) { + if (ev.callback) { + ev.callback(data); + } + } + }; + ctx.FM = common.createFileManager(fmConfig); + ui.sendForm = function (id, form, dest) { return sendForm(ctx, id, form, dest); }; - ui.makeForm = makeForm; + ui.makeForm = function (cb, title) { + return makeForm(ctx, cb, title); + }; ui.makeTicket = function ($div, content, onHide) { return makeTicket(ctx, $div, content, onHide); }; From e7a6397084f5da42f27aeeab02384aac73b62533 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 11 Jun 2020 14:49:59 +0200 Subject: [PATCH 2/3] Add category filter and improve UI --- customize.dist/src/less2/include/support.less | 12 +++++ www/admin/inner.js | 17 +++++++ www/common/common-ui-elements.js | 4 +- www/support/app-support.less | 9 ++++ www/support/ui.js | 51 ++++++++++++------- 5 files changed, 73 insertions(+), 20 deletions(-) diff --git a/customize.dist/src/less2/include/support.less b/customize.dist/src/less2/include/support.less index 1d62157de..d83746b51 100644 --- a/customize.dist/src/less2/include/support.less +++ b/customize.dist/src/less2/include/support.less @@ -18,6 +18,18 @@ height: 300px; } } + .cp-support-attachments { + display: flex; + .fa { + cursor: pointer; + margin-right: 10px; + } + &> span { + border: 1px solid #ddd; + margin-right: 5px; + padding: 10px; + } + } .cp-support-container { .cp-support-list-ticket { display: flex; diff --git a/www/admin/inner.js b/www/admin/inner.js index 2ff62cf1f..90048e76d 100644 --- a/www/admin/inner.js +++ b/www/admin/inner.js @@ -185,6 +185,20 @@ define([ var $container = makeBlock('support-list'); var $div = $(h('div.cp-support-container')).appendTo($container); + var catContainer = h('div.cp-dropdown-container'); + $div.append(catContainer); + 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 || ''; @@ -277,6 +291,9 @@ define([ UI.alert(Messages.error); }); }); + if (category !== 'all' && $ticket.attr('data-cat') !== category) { + $ticket.hide(); + } } $ticket.append(APP.support.makeMessage(content, hash)); reorder(); diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 4393d1201..4d2f8b3c7 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2204,7 +2204,9 @@ define([ if (config.isSelect && value) { var $val = $innerblock.find('[data-value="'+value+'"]'); setActive($val); - $innerblock.scrollTop($val.position().top + $innerblock.scrollTop()); + try { + $innerblock.scrollTop($val.position().top + $innerblock.scrollTop()); + } catch (e) {} } if (config.feedback) { Feedback.send(config.feedback); } }; diff --git a/www/support/app-support.less b/www/support/app-support.less index 7684c054e..41af016fd 100644 --- a/www/support/app-support.less +++ b/www/support/app-support.less @@ -18,6 +18,15 @@ display: flex; flex-flow: column; + .cp-support-form-attachments { + .fa { + cursor: pointer; + } + &> span { + padding: 10px; + } + } + .cp-support-language-list { .cp-support-language { margin-left: 5px; diff --git a/www/support/ui.js b/www/support/ui.js index e95a8e8cf..e4d60e919 100644 --- a/www/support/ui.js +++ b/www/support/ui.js @@ -66,7 +66,7 @@ define([ var $cat = $form.find('.cp-support-form-category'); var $title = $form.find('.cp-support-form-title'); var $content = $form.find('.cp-support-form-msg'); - var $attachments = $form.find('.cp-support-form-attachments'); + var $attachments = $form.find('.cp-support-attachments'); var category = $cat.val().trim(); @@ -105,10 +105,32 @@ Messages.support_cat_account = "User account"; // XXX Messages.support_cat_data = "Loss of content"; // XXX Messages.support_cat_bug = "Bug report"; // XXX Messages.support_cat_other = "Other"; // XXX +Messages.support_cat_all = "All"; // XXX Messages.support_category = "Category"; // XXX Messages.support_attachments = "Attachments"; // XXX Messages.support_addAttachment = "Add attachment"; // XXX + var makeCategoryDropdown = function (ctx, container, onChange, all) { + var categories = ['account', 'data', 'bug', 'other']; + if (all) { categories.push('all'); } + categories = categories.map(function (key) { + return { + tag: 'a', + content: h('span', Messages['support_cat_'+key]), + action: function () { + onChange(key); + } + }; + }); + var dropdownCfg = { + text: Messages.support_category, + options: categories, + container: $(container), + isSelect: true + }; + return UIElements.createDropdown(dropdownCfg); + }; + var makeForm = function (ctx, cb, title) { var button; @@ -123,23 +145,10 @@ Messages.support_addAttachment = "Add attachment"; // XXX type: 'hidden', value: '' }); - var categories = ['account', 'data', 'bug', 'other'].map(function (key) { - return { - tag: 'a', - content: h('span', Messages['support_cat_'+key]), - action: function () { - $(category).val(key); - } - }; - }); var catContainer = h('div.cp-dropdown-container' + (title ? '.cp-hidden': '')); - var dropdownCfg = { - text: Messages.support_category, - options: categories, - container: $(catContainer), - isSelect: true - }; - var $drop = UIElements.createDropdown(dropdownCfg); + makeCategoryDropdown(ctx, catContainer, function (key) { + $(category).val(key); + }); var attachments, addAttachment; @@ -157,7 +166,7 @@ Messages.support_addAttachment = "Add attachment"; // XXX placeholder: Messages.support_formMessage }), h('label', Messages.support_attachments), - attachments = h('div.cp-support-form-attachments'), + attachments = h('div.cp-support-attachments'), addAttachment = h('button', Messages.support_addAttachment), h('hr'), button, @@ -240,6 +249,7 @@ Messages.support_addAttachment = "Add attachment"; // XXX } var $ticket = $(h('div.cp-support-list-ticket', { + 'data-cat': content.category, 'data-id': content.id }, [ h('h2', [ticketCategory, ticketTitle, url]), @@ -334,7 +344,7 @@ Messages.support_addAttachment = "Add attachment"; // XXX h('span.cp-support-message-time', content.time ? new Date(content.time).toLocaleString() : '') ]), h('pre.cp-support-message-content', content.message), - h('div', attachments), + h('div.cp-support-attachments', attachments), isAdmin ? userData : undefined, ]); }; @@ -382,6 +392,9 @@ Messages.support_addAttachment = "Add attachment"; // XXX ui.makeForm = function (cb, title) { return makeForm(ctx, cb, title); }; + ui.makeCategoryDropdown = function (container, onChange, all) { + return makeCategoryDropdown(ctx, container, onChange, all); + }; ui.makeTicket = function ($div, content, onHide) { return makeTicket(ctx, $div, content, onHide); }; From 62dabc0afc15e39b55c79639a5d8e66d1ff8acce Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 17 Jun 2020 10:20:03 -0400 Subject: [PATCH 3/3] add some XXX notes to address before the next release --- www/support/ui.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/www/support/ui.js b/www/support/ui.js index e4d60e919..7449e2e07 100644 --- a/www/support/ui.js +++ b/www/support/ui.js @@ -66,10 +66,11 @@ define([ var $cat = $form.find('.cp-support-form-category'); var $title = $form.find('.cp-support-form-title'); var $content = $form.find('.cp-support-form-msg'); + // XXX block submission until pending uploads are complete? var $attachments = $form.find('.cp-support-attachments'); - var category = $cat.val().trim(); + var category = $cat.val().trim(); // XXX make category a required field? var title = $title.val().trim(); if (!title) { return void UI.alert(Messages.support_formTitleError); @@ -182,6 +183,8 @@ Messages.support_addAttachment = "Add attachment"; // XXX }).on('change', function (e) { var files = Util.slice(e.target.files); files.forEach(function (file) { + // XXX validate that the href is hosted on the same instance + // use relative URLs or compare it against a list or allowed domains? var ev = {}; ev.callback = function (data) { var x, a; @@ -324,6 +327,7 @@ Messages.support_addAttachment = "Add attachment"; // XXX var a = h('a', { href: '#' }, obj.name) + // XXX disallow remote URLs $(a).click(function (e) { e.preventDefault(); ctx.common.openURL(obj.href);