From 00380d84c59ad1c46986f0eb050c52eb7b27fb77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Hanol?= Date: Wed, 8 Mar 2017 23:15:42 +0100 Subject: [PATCH] UX: display text & html parts alongside raw email in incoming email modal --- .../discourse/controllers/raw-email.js.es6 | 28 ++++++++++- .../discourse/templates/modal/raw-email.hbs | 50 ++++++++++++++++--- app/assets/stylesheets/common/base/modal.scss | 44 +++++++++++++--- app/controllers/admin/email_controller.rb | 3 +- app/controllers/posts_controller.rb | 7 +-- config/locales/client.en.yml | 14 +++++- lib/email.rb | 17 +++++++ 7 files changed, 144 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/raw-email.js.es6 b/app/assets/javascripts/discourse/controllers/raw-email.js.es6 index 29ea5adc284..d197c2c08e9 100644 --- a/app/assets/javascripts/discourse/controllers/raw-email.js.es6 +++ b/app/assets/javascripts/discourse/controllers/raw-email.js.es6 @@ -5,15 +5,39 @@ import IncomingEmail from 'admin/models/incoming-email'; // This controller handles displaying of raw email export default Ember.Controller.extend(ModalFunctionality, { rawEmail: "", + textPart: "", + htmlPart: "", + + tab: "raw", + + showRawEmail: Ember.computed.equal("tab", "raw"), + showTextPart: Ember.computed.equal("tab", "text_part"), + showHtmlPart: Ember.computed.equal("tab", "html_part"), + + onShow() { this.send("displayRaw"); }, loadRawEmail(postId) { return Post.loadRawEmail(postId) - .then(result => this.set("rawEmail", result.raw_email)); + .then(result => this.setProperties({ + "rawEmail": result.raw_email, + "textPart": result.text_part, + "htmlPart": result.html_part, + })); }, loadIncomingRawEmail(incomingEmailId) { return IncomingEmail.loadRawEmail(incomingEmailId) - .then(result => this.set("rawEmail", result.raw_email)); + .then(result => this.setProperties({ + "rawEmail": result.raw_email, + "textPart": result.text_part, + "htmlPart": result.html_part, + })); + }, + + actions: { + displayRaw() { this.set("tab", "raw"); }, + displayTextPart() { this.set("tab", "text_part"); }, + displayHtmlPart() { this.set("tab", "html_part"); } } }); diff --git a/app/assets/javascripts/discourse/templates/modal/raw-email.hbs b/app/assets/javascripts/discourse/templates/modal/raw-email.hbs index 12667d0143a..4a59eef06fc 100644 --- a/app/assets/javascripts/discourse/templates/modal/raw-email.hbs +++ b/app/assets/javascripts/discourse/templates/modal/raw-email.hbs @@ -1,7 +1,45 @@ -{{#d-modal-body title="raw_email.title" maxHeight="80%"}} - {{#if rawEmail}} - {{textarea value=rawEmail class="raw-email-textarea"}} - {{else}} - {{i18n 'raw_email.not_available'}} - {{/if}} +{{#d-modal-body title="raw_email.title" class="incoming-email-modal" maxHeight="80%"}} +
+ {{d-button action="displayRaw" + label="post.raw_email.displays.raw.button" + title="post.raw_email.displays.raw.title" + class=(if showRawEmail 'active') + }} + + {{#if textPart}} + {{d-button action="displayTextPart" + label="post.raw_email.displays.text_part.button" + title="post.raw_email.displays.text_part.title" + class=(if showTextPart 'active') + }} + {{/if}} + + {{#if htmlPart}} + {{d-button action="displayHtmlPart" + label="post.raw_email.displays.html_part.button" + title="post.raw_email.displays.html_part.title" + class=(if showHtmlPart 'active') + }} + {{/if}} +
+ +
+ {{#if showRawEmail}} + {{#if rawEmail}} + {{textarea value=rawEmail}} + {{else}} + {{i18n 'raw_email.not_available'}} + {{/if}} + {{/if}} + + {{#if showTextPart}} + {{textarea value=textPart}} + {{/if}} + + {{#if showHtmlPart}} +
+ {{{htmlPart}}} +
+ {{/if}} +
{{/d-modal-body}} diff --git a/app/assets/stylesheets/common/base/modal.scss b/app/assets/stylesheets/common/base/modal.scss index 56198d9e160..d98adaf25db 100644 --- a/app/assets/stylesheets/common/base/modal.scss +++ b/app/assets/stylesheets/common/base/modal.scss @@ -73,9 +73,6 @@ max-width: 710px; margin: 0 auto; background-color: $secondary; - border: 1px solid dark-light-diff($primary, $secondary, 90%, -60%); - - box-shadow: 0 3px 7px rgba(0,0,0, .8); background-clip: padding-box; } @@ -154,9 +151,6 @@ .warning { color: $danger !important; } - .raw-email-textarea { - height: 300px; - } .json-uploader { .jsfu-shade-container { display: table-row; @@ -330,3 +324,41 @@ } } +.incoming-email-modal { + .btn { + transition: none; + background-color: transparent; + margin-right: 5px; + &:hover, &.active { + color: $primary; + } + &.active { + font-weight: bold; + } + &:focus { + outline: 2px solid dark-light-diff($primary, $secondary, 90%, -60%); + } + } + .incoming-email-tabs { + margin-bottom: 15px; + } + .incoming-email-content { + height: 300px; + textarea, .incoming-email-html-part { + height: 95%; + border: none; + border-top: 1px solid dark-light-diff($primary, $secondary, 90%, -60%); + padding-top: 10px; + } + textarea { + font-family: monospace; + resize: none; + border-radius: 0px; + box-shadow: none; + } + .incoming-email-html-part { + padding: 10px 4px 4px 4px; + } + } +} + diff --git a/app/controllers/admin/email_controller.rb b/app/controllers/admin/email_controller.rb index 077937e0218..df400de93e5 100644 --- a/app/controllers/admin/email_controller.rb +++ b/app/controllers/admin/email_controller.rb @@ -78,7 +78,8 @@ class Admin::EmailController < Admin::AdminController def raw_email params.require(:id) incoming_email = IncomingEmail.find(params[:id].to_i) - render json: { raw_email: incoming_email.raw } + text, html = Email.extract_parts(incoming_email.raw) + render json: { raw_email: incoming_email.raw, text_part: text, html_part: html } end def incoming diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 52618c5cafd..5d0b793252c 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -109,14 +109,15 @@ class PostsController < ApplicationController end def cooked - post = find_post_from_params - render json: {cooked: post.cooked} + render json: { cooked: find_post_from_params.cooked } end def raw_email + params.require(:id) post = Post.unscoped.find(params[:id].to_i) guardian.ensure_can_view_raw_email!(post) - render json: { raw_email: post.raw_email } + text, html = Email.extract_parts(post.raw_email) + render json: { raw_email: post.raw_email, text_part: text, html_part: html } end def short_link diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 59e857c30dd..b72ffd81085 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -1918,6 +1918,18 @@ en: title: "Show the raw source diffs side-by-side" button: 'Raw' + raw_email: + displays: + raw: + title: "Show the raw email" + button: 'Raw' + text_part: + title: "Show the text part of the email" + button: 'Text' + html_part: + title: "Show the html part of the email" + button: 'HTML' + category: can: 'can… ' none: '(no category)' @@ -2123,7 +2135,7 @@ en: changed_by: "by {{author}}" raw_email: - title: "Raw Email" + title: "Incoming Email" not_available: "Not available!" categories_list: "Categories List" diff --git a/lib/email.rb b/lib/email.rb index f37d81aa65d..0bae995d178 100644 --- a/lib/email.rb +++ b/lib/email.rb @@ -29,4 +29,21 @@ module Email name ? name.gsub(/[:<>,"]/, '') : name end + def self.extract_parts(raw) + mail = Mail.new(raw) + text = nil + html = nil + + if mail.multipart? + text = mail.text_part + html = mail.html_part + elsif mail.content_type.to_s["text/html"] + html = mail + else + text = mail + end + + [text&.decoded, html&.decoded] + end + end