This is an automated email from the ASF dual-hosted git repository. humbedooh pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-ponymail-foal.git
commit a968f072c1514e28c0205150afaec6ae900785b8 Author: Daniel Gruno <[email protected]> AuthorDate: Mon Mar 29 17:16:33 2021 +0200 Initial work on a simple email editor interface Much more work to be done, but this is a start.. --- webui/admin.html | 78 +++++++++++++++++++++++++ webui/css/scaffolding.css | 12 ++++ webui/js/source/mgmt.js | 146 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+) diff --git a/webui/admin.html b/webui/admin.html new file mode 100644 index 0000000..c981080 --- /dev/null +++ b/webui/admin.html @@ -0,0 +1,78 @@ +<!DOCTYPE html> +<!-- Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. The +ASF licenses this file to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at . +http://www.apache.org/licenses/LICENSE-2.0 . Unless required by +applicable law or agreed to in writing, software distributed under the +License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES +OR CONDITIONS OF ANY KIND, either express or implied. See the License +for the specific language governing permissions and limitations under +the License. --> +<html lang="en"> + <head> + <meta charset="utf-8"> + <base href="../"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=420, initial-scale=1"> + <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> + + <!-- Left empty on purpose!--> + <title></title> + + <!-- Bootstrap --> + + <link href="css/bootstrap.min.css" rel="stylesheet" media="all"> + <link href="css/scaffolding.css" rel="stylesheet" media="all"> + <link href="css/modal.css" rel="stylesheet" media="all"> + <link href="css/spinner.css" rel="stylesheet" media="all"> + <link rel="alternate" href="/api/static.lua"/> + <link rel="stylesheet" href="//cdn.jsdelivr.net/font-hack/2.013/css/hack.min.css"> + + <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> + <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> + <!--[if lt IE 9]> + <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> + <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> + <![endif]--> + </head> + + <body onload="admin_init();"> + <header class="navbar navbar-default" style="margin-bottom: 0px; background: linear-gradient(to bottom, rgba(229,229,229,1) 0%,rgba(191,191,191,1) 100%);"> + <div class="container-fluid"> + <!-- Brand and toggle get grouped for better mobile display --> + <div class="navbar-header collapse navbar-collapse"> + <a class="navbar-brand" href="./"><span><img src="images/foal.png" style="margin-top: -10px !important;" height="30"/> <span class='hidden-xs title'>Pony Mail!</span></a> + </div> + + + </div> + + </header> + + <div class="container-fluid"> + <noscript> + <div class="bs-callout bs-callout-alert"> + This site requires JavaScript enabled. Please enable it. + </div> + </noscript> + <div class="row"> + + <div id="panel"> + + </div> + </div> + </div> + <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <!-- Include all compiled plugins (below), or include individual files as needed --> + <script src="js/bootstrap.min.js"></script> + <script src="js/config.js"></script> + <script src="js/wordcloud.js"></script> + <script src="js/weburl.js"></script> + <script src="js/ponymail.js"></script> + <div id="splash" class="splash fade-in"> </div> + <div style="clear: both;"></div> + </body> +</html> diff --git a/webui/css/scaffolding.css b/webui/css/scaffolding.css index c74953b..49987ed 100644 --- a/webui/css/scaffolding.css +++ b/webui/css/scaffolding.css @@ -878,6 +878,18 @@ a .listview_email_threaded { +.email_kv_edit { + width: 100%; + float: left; + height: 32px; + position: relative; + min-width: 370px; + background: #EEE; + border-bottom: 0.75px solid #CCC9; + z-index: 1; +} + + .email_kv { width: 100%; float: left; diff --git a/webui/js/source/mgmt.js b/webui/js/source/mgmt.js new file mode 100644 index 0000000..7099724 --- /dev/null +++ b/webui/js/source/mgmt.js @@ -0,0 +1,146 @@ +let admin_current_email = null; + +async function POST(url, formdata, state) { + const resp = await fetch(url, { + credentials: "same-origin", + mode: "same-origin", + method: "post", + headers: { "Content-Type": "application/json" }, + body: formdata + }); + return resp +} + +// Deletes (hides) an email from the archives +async function admin_hide_email() { + formdata = JSON.stringify({ + action: "delete", + document: admin_current_email + }); + let rv = await POST('%sapi/mgmt.json'.format(apiURL), formdata, {}); + let response = await rv.text(); + if (rv.status == 200) { + modal("Email removed", "Server responded with: " + response, "help"); + } else { + modal("Something went wrong!", "Server responded with: " + response, "error"); + } +} + +// Saves an email with edits +async function admin_save_email() { + let from = document.getElementById('email_from').value; + let subject = document.getElementById('email_subject').value; + let listname = document.getElementById('email_listname').value; + let private = document.getElementById('email_private').value; + let body = document.getElementById('email_body').value; + let formdata = JSON.stringify({ + action: "edit", + document: admin_current_email, + from: from, + subject: subject, + list: listname, + private: private, + body: body + }) + let rv = await POST('%sapi/mgmt.json'.format(apiURL), formdata, {}); + let response = await rv.text(); + if (rv.status == 200) { + modal("Email changed", "Server responded with: " + response, "help"); + } else { + modal("Something went wrong!", "Server responded with: " + response, "error"); + } +} + +function admin_email_preview(stats, json) { + admin_current_email = json.mid; + let cp = document.getElementById("panel"); + let div = new HTML('div'); + cp.inject(div); + + div.inject(new HTML('h1', {}, "Editing email " + json.mid + ":")); + + // Author + let author_field = new HTML('div', {class: 'email_kv_edit'}); + let author_key = new HTML('div', {class: 'email_key'}, "From: "); + let author_value = new HTML('input', {id: 'email_from', style: {width: "480px"}, value: json.from}); + author_field.inject([author_key, author_value]); + div.inject(author_field); + + // Subject + let subject_field = new HTML('div', {class: 'email_kv_edit'}); + let subject_key = new HTML('div', {class: 'email_key'}, "Subject: "); + let subject_value = new HTML('input', {id: 'email_subject', style: {width: "480px"}, value: json.subject}); + subject_field.inject([subject_key, subject_value]); + div.inject(subject_field); + + // Date + let date_field = new HTML('div', {class: 'email_kv_edit'}); + let date_key = new HTML('div', {class: 'email_key'}, "Date: "); + let date_value = new HTML('div', {class: 'email_value'}, new Date(json.epoch * 1000.0).ISOBare()); + date_field.inject([date_key, date_value]); + div.inject(date_field); + + // List + let listname = json.list_raw.replace(".", "@", 1).replace(/[<>]/g, ""); + let list_field = new HTML('div', {class: 'email_kv_edit'}); + let list_key = new HTML('div', {class: 'email_key'}, "List: "); + let list_value = new HTML('input', {id: 'email_listname', style: {width: "480px"}, value: listname}); + list_field.inject([list_key, list_value]); + div.inject(list_field); + + // Private email? + let priv_field = new HTML('div', {class: 'email_kv_edit'}); + let priv_key = new HTML('div', {class: 'email_key'}, "Private: "); + let priv_value = new HTML('select', {id:'email_private'}); + priv_value.inject(new HTML('option', {value: 'no', style: {color: 'green'}, selected: json.private ? null : "selected"}, "No")); + priv_value.inject(new HTML('option', {value: 'yes', style: {color: 'red'}, selected: json.private ? "selected" : null}, "Yes")); + priv_field.inject([priv_key, priv_value]); + div.inject(priv_field); + + // Attachments? + if (json.attachments && json.attachments.length > 0) { + let attach_field = new HTML('div', {class: 'email_kv'}); + let attach_key = new HTML('div', {class: 'email_key'}, "Attachment(s): "); + let alinks = []; + for (let n = 0; n < json.attachments.length; n++) { + let attachment = json.attachments[n]; + let link = `${pm_config.apiURL}api/email.lua?attachment=true&id=${json.mid}&file=${attachment.hash}`; + let a = new HTML('a', {href: link, target: '_blank'}, attachment.filename); + alinks.push(a); + let fs = ` ${attachment.size} bytes`; + if (attachment.size >= 1024) fs = ` ${Math.floor(attachment.size/1024)} KB`; + if (attachment.size >= 1024*1024) fs = ` ${Math.floor(attachment.size/(1024*10.24))/100} MB`; + alinks.push (fs); + alinks.push(new HTML('br')); + } + let attach_value = new HTML('div', {class: 'email_value'}, alinks); + attach_field.inject([attach_key, attach_value]); + div.inject(attach_field); + } + + let text = new HTML('textarea', {id: 'email_body', style: {width: "100%", height: "480px"}}, json.body); + div.inject(text); + + let btn_edit = new HTML('button', {onclick: "admin_save_email();"}, "Save changes to archive"); + let btn_hide = new HTML('button', {onclick: "admin_hide_email();", style: {marginLeft: "24px", color: 'red'}}, "Remove email from archives*"); + div.inject(new HTML('br')); + div.inject(btn_edit); + div.inject(btn_hide); + div.inject(new HTML('br')); + div.inject(new HTML('small', {}, "* Emails that are removed may still be recovered by the base system administrator. For complete expungement, please contact the system administrator.")) +} + +function admin_init() { + let mid = location.href.split('/').pop(); + // Specific email/list handling? + if (mid.length > 0) { + // List handling? + if (mid.match(/^<.+>$/)) { + + } + // Email handling? + else { + GET('%sapi/email.lua?id=%s'.format(apiURL, mid), admin_email_preview, null); + } + } +} \ No newline at end of file
