diff options
author | Simon Ser <contact@emersion.fr> | 2020-03-19 18:03:13 +0100 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2020-03-19 18:03:13 +0100 |
commit | c182fbde6334f07873700d6a487155fb3f493403 (patch) | |
tree | 11089f6315dbc9a21300f546ffa5abb8c09a53c4 | |
parent | 9eac0b453a21918f7533e78aa0fbb4d07cdbf474 (diff) | |
download | alps-c182fbde6334f07873700d6a487155fb3f493403.tar.gz alps-c182fbde6334f07873700d6a487155fb3f493403.zip |
themes/alps: new theme
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | themes/alps/assets/helpers.js | 24 | ||||
-rw-r--r-- | themes/alps/assets/style.css | 269 | ||||
-rw-r--r-- | themes/alps/compose.html | 40 | ||||
-rw-r--r-- | themes/alps/foot.html | 3 | ||||
-rw-r--r-- | themes/alps/head.html | 10 | ||||
-rw-r--r-- | themes/alps/login.html | 26 | ||||
-rw-r--r-- | themes/alps/mailbox.html | 66 | ||||
-rw-r--r-- | themes/alps/message.html | 154 | ||||
-rw-r--r-- | themes/alps/messages-header.html | 45 | ||||
-rw-r--r-- | themes/alps/nav.html | 12 |
11 files changed, 650 insertions, 0 deletions
@@ -1,6 +1,7 @@ /koushin /themes/* !/themes/sourcehut +!/themes/alps /plugins/* !/plugins/base !/plugins/caldav diff --git a/themes/alps/assets/helpers.js b/themes/alps/assets/helpers.js new file mode 100644 index 0000000..344dd17 --- /dev/null +++ b/themes/alps/assets/helpers.js @@ -0,0 +1,24 @@ +(function() { + var sheet = document.styleSheets[0]; + var addCSSRule = function(selector, rules, index) { + if ("insertRule" in sheet) { + sheet.insertRule(selector + "{" + rules + "}", index); + return; + } + if ("addRule" in sheet) { + sheet.addRule(selector, rules, index); + } + }; + + var checkboxAll = document.getElementById("action-checkbox-all"); + if (checkboxAll) { + addCSSRule(".message-list-checkbox", "display: table-cell !important;"); + checkboxAll.addEventListener("click", function(ev) { + var allChecked = this.checked; + var inputs = document.querySelectorAll("tr .message-list-checkbox input"); + Array.prototype.slice.apply().forEach(function(cb) { + cb.checked = allChecked; + }); + }); + } +})(); diff --git a/themes/alps/assets/style.css b/themes/alps/assets/style.css new file mode 100644 index 0000000..16db44c --- /dev/null +++ b/themes/alps/assets/style.css @@ -0,0 +1,269 @@ +/* Box sizing rules */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Remove default padding */ +ul[class], +ol[class] { + padding: 0; +} + +/* Remove default margin */ +body, +h1, +h2, +h3, +h4, +p, +ul[class], +ol[class], +li, +figure, +figcaption, +blockquote, +dl, +dd { + margin: 0; +} + +/* Set core body defaults */ +body { + min-height: 100vh; + scroll-behavior: smooth; + text-rendering: optimizeSpeed; + line-height: 1.5; +} + +/* Remove list styles on ul, ol elements with a class attribute */ +ul[class], +ol[class] { + list-style: none; +} + +/* A elements that don't have a class get default styles */ +a:not([class]) { + text-decoration-skip-ink: auto; +} + +/* Make images easier to work with */ +img { + max-width: 100%; + display: block; +} + +/* Natural flow and rhythm in articles by default */ +article > * + * { + margin-top: 1em; +} + +/* Inherit fonts for inputs and buttons */ +input, +button, +textarea, +select { + font: inherit; +} + +/* Remove all animations and transitions for people that prefer not to see them */ +@media (prefers-reduced-motion: reduce) { + * { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} +/** { box-sizing: content-box; }*/ +body { font-family: arial,sans-serif; font-size: 13px; padding: 0; margin: 0; + min-width: 1024px; min-height: 100vh; display: flex; flex-direction: column; +} + +input[type="text"], +input[type="email"], +input[type="password"], +input[type="file"], +textarea { + margin: 0; + border: none; + border: 1px solid #e0e0e0; + box-shadow: inset 1px 1px 0 #f8f8f8; + border-radius: 2px; + font-size: 13px; + padding: 0.3rem 0.5rem 0.3rem 0.5rem; + background-color: white; +} + +.page-wrap { + display: flex; + flex: 1 100%; + flex-direction: row; +} + +a { color: #15c; } +button { font-size: 1rem; } +header { border-bottom: 1px solid #e0e0e0;} +header nav, +footer { padding: 0.5rem 1rem 0.5rem 0.5rem; } +header nav { min-height: 1rem; } +/*header nav strong { color: #555; }*/ +header nav > a { margin-right: 1rem; } +header nav span { color: #757373; } +header nav div { float: right; } +header nav div > a{ margin-left: 1rem; } +header a.active { font-weight: bold; color: black; text-decoration: none; } + + +footer { text-align: right; } + +.actions { padding: 0.5rem; } + +.container { flex: 1 auto; display: flex; flex-direction: column; flex-wrap: nowrap; min-width: 0; } + + +aside { flex: 0 0 180px; } +aside a { width: 100%; display: block; padding: 0.4rem 0 0.4rem 0.5rem; } +aside a.active { font-weight: bold; color: black; text-decoration: none; } +aside img { display: block; } +main { flex: 1 100%; display: flex; flex-direction: column; padding: 0.5rem 1rem 0.5rem 0.5rem; min-width: 0; } + +aside a.active, +main { background-color: #f6f6f6; } +aside a.compose-mail.active { color: #008d47; } +aside a.compose-mail.active, +main.compose { background-color: #f6fff6; } +main.compose { flex: 1 auto; padding: 1rem; } +main.compose form { flex: 1 auto; display: flex; flex-direction: column; } +main.compose form label { margin-top: 5px; } +main.compose form label span { display: inline-block; font-weight: bold; min-width: 100px; } +main.compose form input { width: 80%; } +main.compose form textarea { flex: 1 auto; resize: none; margin-top: 1rem; } +main.compose button[type="submit"] { padding: 0.4rem 1rem 0.35rem; font-weight: bold; } +main.compose .actions { text-align: right; } +main table { border-collapse: collapse; width: 100%; border: 1px solid #eee; } +main table td { white-space: nowrap; padding: 0.3rem; color: #757373; + overflow: hidden; + text-overflow: ellipsis; + max-width: 200px; +} +main table tbody tr { border-bottom: 1px solid #eee; } +main table td a { text-decoration: none; } + + +main table td a:hover { text-decoration: underline; } + +main.message pre { flex: 1 auto; padding: 1rem; white-space: pre-wrap; word-break: break-all; background-color: white; border: 1px solid #eee; max-width: 100% } +main.message table { background-color: white; } +main.message th { width: 5%;} +main.message h1 { font-size: 1.2rem; padding: 0.5rem;} + +.message-list-subject a { color: #77c; } + + +.message-list-unread .message-list-sender, +.message-list-unread .message-list-subject, +.message-list-unread .message-list-date { font-weight: bold; } + +.message-list-unread .message-list-sender, +.message-list-unread .message-list-date { color: black;} + +.message-list-date { + text-align: right; + padding-right: 0.5rem; +} + +.message-list-unread .message-list-subject a { color: #00c; } + +.message-list-unread { + background-color: white; + border-left: 1px solid #f2f2f2; + border-right: 1px solid #f2f2f2; +} +.message-list-unread td { opacity: 1; } + +aside .compose-mail { + color: #008d47; + font-weight: bold; + /*background-color: #f5fcf2;*/ + text-decoration: none; +} + +main table th { + text-align: left; + padding: 0.3rem; font-weight: normal; +} + +main table thead { + border-bottom: 1px solid #e0e0e0; + background-color: white; +} +main table tfoot { + border-top: 1px solid #e0e0e0; + background-color: white; +} + +th form { display: inline; } +th input[type="text"] { + flex: 1; + margin: 0; +} +th input[type="text"] + button { + margin-left: -4rem; + width: 4rem; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.actions-wrap { display: flex; flex-direction: row; } +.actions-message { margin-right: 1rem; } +.actions-pagination { margin-left: 1rem; display: flex; flex-direction: row; } +.actions-search { flex: 1 auto; display: flex; flex-direction: row; } + + +input[type="submit"], +.button, +button, +.button-link { + margin: 0; + cursor: pointer; + text-decoration: none; + text-align: center; + display: inline-block; + /*padding: 0.4rem 0.4rem 0.35rem;*/ + padding: 0.3rem 0.3rem 0.25rem; + min-width: 1rem; + font-size: 12px; + border: 1px solid #ddd; + border-radius: 3px; + vertical-align: middle; +} +.button-link { + border: 1px solid transparent; + text-decoration: none; +} +.button-link:hover { + text-decoration: underline; +} + +input[type="submit"], +.button, +button { + background-color: #f5f5f5; + border: 1px solid #ddd; + color: black; +} + +.button:hover, +button:hover { + background-color: white; +} + +.button:active, +button:active { + color: #ccc; + background-color: #f8f8f8; +} + +.message-list-checkbox { display: none; } diff --git a/themes/alps/compose.html b/themes/alps/compose.html new file mode 100644 index 0000000..57e5a84 --- /dev/null +++ b/themes/alps/compose.html @@ -0,0 +1,40 @@ +{{template "head.html"}} +{{template "nav.html" .}} + + +<div class="page-wrap"> + <aside> + <a href="/compose" class="compose-mail active">Compose Mail</a> + <a href="/mailbox/INBOX">Inbox</a> + <a href="/mailbox/Drafts">Drafts</a> + <a href="/mailbox/Sent">Sent</a> + <a href="/mailbox/Archive">Archive</a> + <a href="/mailbox/Junk">Junk</a> + <a href="/mailbox/Trash">Trash</a> + </aside> + + <div class="container"> + <main class="compose"> + + <form method="post" action="" enctype="multipart/form-data"> + <input type="hidden" name="in_reply_to" value="{{.Message.InReplyTo}}"> + <label><span>From</span><input type="email" name="from" id="from" value="{{.Message.From}}" /></label> + <label><span>To</span><input type="email" name="to" id="to" value="{{.Message.ToString}}" multiple {{ if not .Message.To }} autofocus{{ end }}/></label> + <label><span>Subject</span><input type="text" name="subject" id="subject" value="{{.Message.Subject}}" {{ if .Message.To }} autofocus{{ end }}/></label> + <label><span>Attachments</span><input type="file" name="attachments" id="attachments" multiple></label> + + <textarea name="text" class="body">{{.Message.Text}}</textarea> + + <div class="actions"> + <button type="submit">Send Message</button> + + <a href="/mailbox/INBOX">Discard</a> + </div> + </form> + + </main> + </div> +</div> + + +{{template "foot.html"}} diff --git a/themes/alps/foot.html b/themes/alps/foot.html new file mode 100644 index 0000000..248e5d4 --- /dev/null +++ b/themes/alps/foot.html @@ -0,0 +1,3 @@ + <script type="text/javascript" src="/themes/alps/assets/helpers.js"></script> + </body> +</html> diff --git a/themes/alps/head.html b/themes/alps/head.html new file mode 100644 index 0000000..a6f679f --- /dev/null +++ b/themes/alps/head.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="theme-color" content="#ffffff"> + <title>Webmail</title> + <link rel="stylesheet" href="/themes/alps/assets/style.css"> + </head> + <body> diff --git a/themes/alps/login.html b/themes/alps/login.html new file mode 100644 index 0000000..3357142 --- /dev/null +++ b/themes/alps/login.html @@ -0,0 +1,26 @@ +{{template "head.html"}} + <h1>koushin webmail</h1> + + <form method="post" action="/login"> + <p> + <label> + <strong>Username</strong> + <br/> + <input type="text" name="username" id="username" autofocus /> + </label> + </p> + <br/> + <p> + <label> + <strong>Password</strong> + <br/> + <input type="password" name="password" id="password" /> + </label> + </p> + <br/> + <p> + <button>Sign in</button> + </p> +</form> + +{{template "foot.html"}} diff --git a/themes/alps/mailbox.html b/themes/alps/mailbox.html new file mode 100644 index 0000000..6d870ba --- /dev/null +++ b/themes/alps/mailbox.html @@ -0,0 +1,66 @@ +{{template "head.html"}} +{{template "nav.html" . }} + +<div class="page-wrap"> + <aside> + <!-- the logo image, dimensions 200x32 may be present or not --> + <a href="/compose" class="compose-mail">Compose Mail</a> + {{$current := .Mailbox}} + {{range .Mailboxes}} + <a href="/mailbox/{{.Name | pathescape}}" + {{ if eq $current.Name .Name }}class="active"{{ end }}> + {{ if eq .Name "INBOX" }} + Inbox + {{else}} + {{.Name}} + {{end}} + {{ if eq $current.Name .Name }} + {{ if $current.Unseen }}({{ $current.Unseen }}){{ end }} + {{ end }} + </a> + {{end}} + </aside> + + <div class="container"> + <form id="messages-form" method="post"></form> + <main> + <table> + <thead> + {{ template "messages-header.html" . }} + </thead> + <tbody> + {{range .Messages}} + <tr data="{{.Flags}}" class="message-list-item {{ if not (.HasFlag "\\Seen") }}message-list-unread{{ end }}"> + <td width="1%" class="message-list-checkbox"> + <input type="checkbox" name="uids" value="{{.Uid}}" form="messages-form"> + </td> + <td width="10%" class="message-list-sender"> + {{ range .Envelope.From }} + {{ if .PersonalName }} + {{.PersonalName}} + {{ else }} + {{.MailboxName}}@{{.HostName}} + {{ end }} + {{ end }} + </td> + <td width="80%" class="message-list-subject"> + <a href="/message/{{$.Mailbox.Name | pathescape}}/{{.Uid}}?part={{.TextPartName}}"> + {{if .Envelope.Subject}} + {{.Envelope.Subject}} + {{else}} + (No subject) + {{end}} + </a> + </td> + <td width="9%" nowrap="" class="message-list-date">{{ .Envelope.Date | formatdate }}</td> + </tr> + {{ end }} + </tbody> + <tfoot> + {{ template "messages-header.html" .}} + </tfoot> + </table> + </main> + </div> +</div> +{{template "foot.html"}} diff --git a/themes/alps/message.html b/themes/alps/message.html new file mode 100644 index 0000000..38ae948 --- /dev/null +++ b/themes/alps/message.html @@ -0,0 +1,154 @@ +{{template "head.html"}} +{{template "nav.html" .}} + +<div class="page-wrap"> + {{$current := .Mailbox}} + <aside> + <!-- the logo image, dimensions 200x32 may be present or not --> + <a href="/compose" class="compose-mail">Compose Mail</a> + <!-- TODO: get mailbox list from render data --> + <a href="/mailbox/INBOX" {{ if eq $current.Name "INBOX" }}class="active"{{ end }}>Inbox {{ if $current.Unseen }}({{ $current.Unseen }}){{ end }}</a> + <a href="/mailbox/Drafts" {{ if eq $current.Name "Drafts" }}class="active"{{ end }}>Drafts</a> + <a href="/mailbox/Sent" {{ if eq $current.Name "Sent" }}class="active"{{ end }}>Sent</a> + <a href="/mailbox/Archive" {{ if eq $current.Name "Archive" }}class="active"{{ end }}>Archive {{ if $current.Unseen }}({{ $current.Unseen }}){{ end }}</a> + <a href="/mailbox/Junk" {{ if eq $current.Name "Junk" }}class="active"{{ end }}>Junk {{ if $current.Unseen }}({{ $current.Unseen }}){{ end }}</a> + <a href="/mailbox/Trash" {{ if eq $current.Name "Trash" }}class="active"{{ end }}>Trash</a> + </aside> + + <div class="container"> + <main class="message"> + + +<table> + <tr> + <tr> + <th colspan="2"> + <div class="actions-wrap"> + <div class="actions-message"> + <a href="/mailbox/{{.Mailbox.Name | pathescape}}?page={{.MailboxPage}}" class="button-link">« Back</a> + + + {{ if and (ne .Mailbox.Name "Archive") (ne .Mailbox.Name "Drafts") (ne .Mailbox.Name "Sent") }} + <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/move"> + <input type="hidden" name="uids" value="{{.Message.Uid}}"> + <input type="hidden" name="to" value="Archive"> + <button>Archive</button> + </form> + {{ end }} + + {{ if and (ne .Mailbox.Name "INBOX") (ne .Mailbox.Name "Sent") (ne .Mailbox.Name "Drafts") }} + <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/move"> + <input type="hidden" name="uids" value="{{.Message.Uid}}"> + <input type="hidden" name="to" value="INBOX"> + <button> + {{ if (eq .Mailbox.Name "Junk") }} + Not Spam + {{ else }} + Move to Inbox + {{ end }} + </button> + </form> + {{ end }} + + {{ if or (eq .Mailbox.Name "INBOX") (eq .Mailbox.Name "Trash") }} + <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/move"> + <input type="hidden" name="uids" value="{{.Message.Uid}}"> + + <input type="hidden" name="to" value="Junk"> + <button>Report Spam</button> + </form> + {{ end }} + + {{ if or (eq .Mailbox.Name "Trash") (eq .Mailbox.Name "Junk") }} + <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/delete"> + <input type="hidden" name="uids" value="{{.Message.Uid}}"> + <button>Delete Permanently</button> + </form> + {{ else }} + <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/move"> + <input type="hidden" name="uids" value="{{.Message.Uid}}"> + + <input type="hidden" name="to" value="Trash"> + <button>Delete</button> + </form> + {{ end }} + + <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/flag"> + <input type="hidden" name="uids" value="{{.Message.Uid}}"> + <input type="hidden" name="flags" value="\Seen"> + <input type="hidden" name="action" value="remove"> + <button>Mark Unread</button> + </form> + + <form method="post" action="/message/{{.Mailbox.Name | pathescape}}/move"> + <input type="hidden" name="uids" value="{{.Message.Uid}}"> + <select name="to"> + {{range .Mailboxes}} + <option value="{{.Name}}" {{if eq .Name $.Mailbox.Name}}selected>Move to...{{else}}>{{.Name}}{{ end }}</option> + {{end}} + </select> + <input type="submit" value="Move"> + </form> + + + <a href="{{.Message.Uid}}/reply?part={{.Part.PathString}}">Reply</a> + + <a href="{{.Message.Uid}}/forward?part={{.Part.PathString}}">Forward</a> + </div> + </div> + </th> +</tr> + + </tr> + <tr> + <th colspan="2"> + <h1> + {{if .Message.Envelope.Subject}} + {{.Message.Envelope.Subject}} + {{else}} + (No subject) + {{end}} + </h1> + </th> + </tr> + + <tr> + <th>From:</th> + <td>{{template "addr-list" .Message.Envelope.From}}</td> + </tr> + <tr> + <th>Date:</th> + <td>{{.Message.Envelope.Date | formatdate}}</td> + </tr> + <tr> + <th>To:</th><td>{{template "addr-list" .Message.Envelope.To}}</td> + </tr> + {{if .Message.Envelope.Cc}} + <tr> + <th>Cc:</th><td>{{template "addr-list" .Message.Envelope.Cc}}</td> + </tr> + {{end}} + {{if .Message.Envelope.Bcc}} + <tr> + <th>Bcc:</th> + <td>{{template "addr-list" .Message.Envelope.Bcc}}</td> + </tr> + {{ end }} +</table> + +{{define "addr-list"}} + {{range $i, $addr := .}} + {{if $i}},{{end}} + <strong>{{.PersonalName}}</strong> + <<a href="/compose?to={{.Address}}">{{.Address}}</a>> + {{end}} +{{end}} + +{{if .View}} + {{.View}} +{{else}} + <p>Can't preview this message part.</p> + <a href="{{.Message.Uid}}/raw?part={{.Part.PathString}}">Download</a> +{{end}} + +{{template "foot.html"}} diff --git a/themes/alps/messages-header.html b/themes/alps/messages-header.html new file mode 100644 index 0000000..9384fb6 --- /dev/null +++ b/themes/alps/messages-header.html @@ -0,0 +1,45 @@ +<tr> + <th width="1%" class="message-list-checkbox"> + <input type="checkbox" id="action-checkbox-all"/> + </th> + <th colspan="3"> + <div class="actions-wrap"> + <div class="actions-message"> + {{ if and (eq .Mailbox.Name "INBOX") (not (eq .Mailbox.Name "Archive")) }} + <button form="messages-form" formaction="/message/{{.Mailbox.Name | pathescape}}/move?to=Archive">Archive</button> + + {{ end }} + + {{ if or (eq .Mailbox.Name "INBOX") (eq .Mailbox.Name "Trash") }} + <button form="messages-form" formaction="/message/{{.Mailbox.Name | pathescape}}/move?to=Junk">Report Spam</button> + {{ end }} + + {{ if ne .Mailbox.Name "Trash"}} + <button form="messages-form" formaction="/message/{{.Mailbox.Name | pathescape}}/move?to=Trash">Delete</button> + {{ else }} + <button form="messages-form" formaction="/message/{{.Mailbox.Name | pathescape}}/delete">Delete Permanently</button> + {{ end }} + + + <a href="{{ .GlobalData.Path }}" class="button-link">Refresh</a> + </div> + + <form action="" method="post" class="actions-search"> + <input type="text" name="query" value="{{.Query}}" placeholder="Search messages..."> + <button>Search</button> + </form> + + {{if or (ge .PrevPage 0) (ge .NextPage 0) }} + <div class="actions-pagination"> + {{if ge .PrevPage 0}} + {{if ge .PrevPage 1}}<a href="?page=0" class="button-link">«</a>{{ end }} + <a href="?page={{.PrevPage}}" class="button-link">‹</a> + {{end}} + {{if ge .NextPage 0}} + <a href="?page={{.NextPage}}" class="button-link">›</a> + {{end}} + </div> + {{ end }} + </div> + </th> +</tr> diff --git a/themes/alps/nav.html b/themes/alps/nav.html new file mode 100644 index 0000000..820b2e3 --- /dev/null +++ b/themes/alps/nav.html @@ -0,0 +1,12 @@ +<header> + <nav> + <a href="/" class="active">Email</a> + <a href="/calendar">Calendar</a> + <a href="/contacts">Contacts</a> + <div> + <span>{{ .GlobalData.Username }}</span> + <a href="/settings">Settings</a> + <a href="/logout">Sign Out</a> + </div> + </nav> +</header> |