summaryrefslogtreecommitdiff
path: root/boardvoting/templates
diff options
context:
space:
mode:
authorJan Dittberner <jandd@cacert.org>2018-03-29 20:08:41 +0200
committerJan Dittberner <jandd@cacert.org>2018-03-29 20:08:41 +0200
commit4dd5e0982050ae92a9a37cb62e606b2807a85c27 (patch)
treed2b9900068afe3d747524b43fbae49b86feaa7c8 /boardvoting/templates
parentaea93c328e76fba300f5dd2c380b46c62a6db904 (diff)
downloadcacert-boardvoting-4dd5e0982050ae92a9a37cb62e606b2807a85c27.tar.gz
cacert-boardvoting-4dd5e0982050ae92a9a37cb62e606b2807a85c27.tar.xz
cacert-boardvoting-4dd5e0982050ae92a9a37cb62e606b2807a85c27.zip
Embed database migrations
- switch from goose to github.com/rubenv/sql-migrate - move assets (static, templates, migrations) to boardvoting package - add generated boardvoting/assets.go - remove unused static files from static directory - add package db with db migration configuration
Diffstat (limited to 'boardvoting/templates')
-rw-r--r--boardvoting/templates/closed_motion_mail.txt20
-rw-r--r--boardvoting/templates/create_motion_form.html73
-rw-r--r--boardvoting/templates/create_motion_mail.txt22
-rw-r--r--boardvoting/templates/denied.html17
-rw-r--r--boardvoting/templates/direct_vote_form.html27
-rw-r--r--boardvoting/templates/direct_vote_mail.txt10
-rw-r--r--boardvoting/templates/edit_motion_form.html72
-rw-r--r--boardvoting/templates/footer.html12
-rw-r--r--boardvoting/templates/header.html26
-rw-r--r--boardvoting/templates/motion.html19
-rw-r--r--boardvoting/templates/motion_fragments.html64
-rw-r--r--boardvoting/templates/motions.html52
-rw-r--r--boardvoting/templates/proxy_vote_form.html54
-rw-r--r--boardvoting/templates/proxy_vote_mail.txt13
-rw-r--r--boardvoting/templates/remind_voter_mail.txt15
-rw-r--r--boardvoting/templates/update_motion_mail.txt26
-rw-r--r--boardvoting/templates/withdraw_motion_form.html21
-rw-r--r--boardvoting/templates/withdraw_motion_mail.txt10
18 files changed, 553 insertions, 0 deletions
diff --git a/boardvoting/templates/closed_motion_mail.txt b/boardvoting/templates/closed_motion_mail.txt
new file mode 100644
index 0000000..b1b6a24
--- /dev/null
+++ b/boardvoting/templates/closed_motion_mail.txt
@@ -0,0 +1,20 @@
+Dear Board,
+
+{{ with .Decision }}The motion with the identifier {{.Tag}} has been {{.Status}}.{{ end }}
+
+The reasoning for this result is: {{ .Reasoning }}
+
+{{ with .Decision }}Motion:
+ {{.Title}}
+ {{.Content}}
+
+Vote type: {{.VoteType}}{{end}}
+
+{{ with .VoteSums }} Ayes: {{ .Ayes }}
+ Nayes: {{ .Nayes }}
+ Abstentions: {{ .Abstains }}
+
+ Percentage: {{ .Percent }}%{{ end }}
+
+Kind regards,
+the voting system. \ No newline at end of file
diff --git a/boardvoting/templates/create_motion_form.html b/boardvoting/templates/create_motion_form.html
new file mode 100644
index 0000000..b3cbadb
--- /dev/null
+++ b/boardvoting/templates/create_motion_form.html
@@ -0,0 +1,73 @@
+{{ template "header" . }}
+<div class="column">
+ <div class="ui basic segment">
+ <div class="ui floated right secondary menu">
+ <a href="/motions/" class="item" title="Show all votes">Back to motions</a>
+ </div>
+ </div>
+</div>
+<div class="column">
+ <div class="ui raised segment">
+ <form action="/newmotion/" method="post">
+ <div class="ui form{{ if .Form.Errors }} error{{ end }}">
+ <div class="three fields">
+ <div class="field">
+ <label>ID:</label>
+ (generated on submit)
+ </div>
+ <div class="field">
+ <label>Proponent:</label>
+ {{ .Voter.Name }}
+ </div>
+ <div class="field">
+ <label>Proposed date/time:</label>
+ (auto filled to current date/time)
+ </div>
+ </div>
+ <div class="required field{{ if .Form.Errors.Title }} error{{ end }}">
+ <label for="Title">Title:</label>
+ <input id="Title" name="Title" type="text" value="{{ .Form.Title }}">
+ </div>
+ <div class="required field{{ if .Form.Errors.Content }} error{{ end }}">
+ <label for="Content">Text:</label>
+ <textarea id="Content" name="Content">{{ .Form.Content }}</textarea>
+ </div>
+ <div class="two fields">
+ <div class="required field{{ if .Form.Errors.VoteType }} error{{ end }}">
+ <label for="VoteType">Vote type:</label>
+ <select id="VoteType" name="VoteType">
+ <option value="0"
+ {{ if eq "0" .Form.VoteType }}selected{{ end }}>
+ Motion
+ </option>
+ <option value="1"
+ {{ if eq "1" .Form.VoteType }}selected{{ end }}>
+ Veto
+ </option>
+ </select>
+ </div>
+ <div class="required field{{ if .Form.Errors.Due }} error{{ end }}">
+ <label for="Due">Due: (autofilled from chosen
+ option)</label>
+ <select id="Due" name="Due">
+ <option value="+3 days">In 3 Days</option>
+ <option value="+7 days">In 1 Week</option>
+ <option value="+14 days">In 2 Weeks</option>
+ <option value="+28 days">In 4 Weeks</option>
+ </select>
+ </div>
+ </div>
+ {{ with .Form.Errors }}
+ <div class="ui error message">
+ {{ with .Title }}<p>{{ . }}</p>{{ end }}
+ {{ with .Content }}<p>{{ . }}</p>{{ end }}
+ {{ with .VoteType }}<p>{{ . }}</p>{{ end }}
+ {{ with .Due }}<p>{{ . }}</p>{{ end }}
+ </div>
+ {{ end }}
+ <button class="ui button" type="submit">Propose</button>
+ </div>
+ </form>
+ </div>
+</div>
+{{ template "footer" . }} \ No newline at end of file
diff --git a/boardvoting/templates/create_motion_mail.txt b/boardvoting/templates/create_motion_mail.txt
new file mode 100644
index 0000000..b526615
--- /dev/null
+++ b/boardvoting/templates/create_motion_mail.txt
@@ -0,0 +1,22 @@
+Dear Board,
+
+{{ .Name }} has made the following motion:
+
+{{ .Title }}
+
+{{ wrap 76 .Content }}
+
+Vote type: {{ .VoteType }}
+
+Voting will close {{ .Due }}
+
+To vote please choose:
+
+Aye: {{ .VoteURL }}/aye
+Naye: {{ .VoteURL }}/naye
+Abstain: {{ .VoteURL }}/abstain
+
+To see all your pending votes: {{ .UnvotedURL }}
+
+Kind regards,
+the voting system \ No newline at end of file
diff --git a/boardvoting/templates/denied.html b/boardvoting/templates/denied.html
new file mode 100644
index 0000000..398a36f
--- /dev/null
+++ b/boardvoting/templates/denied.html
@@ -0,0 +1,17 @@
+{{ template "header" . }}
+<div class="column">
+ <div class="ui negative message">
+ <div class="header">You are not authorized to act here!</div>
+ <p>If you think this is in error, please contact the administrator.</p>
+ <p>If you don't know who that is, it is definitely not an error ;)</p>
+ {{ if .Emails }}
+ <p>The following addresses were present in your certificate:<p>
+ <ul>
+ {{ range .Emails }}
+ <li>{{ . }}</li>
+ {{ end }}
+ </ul>
+ {{ end }}
+ </div>
+</div>
+{{ template "footer" . }} \ No newline at end of file
diff --git a/boardvoting/templates/direct_vote_form.html b/boardvoting/templates/direct_vote_form.html
new file mode 100644
index 0000000..861c68a
--- /dev/null
+++ b/boardvoting/templates/direct_vote_form.html
@@ -0,0 +1,27 @@
+{{ template "header" . }}
+<div class="column">
+ <div class="ui basic segment">
+ <div class="ui floated right secondary menu">
+ <a href="/motions/" class="item" title="Show all votes">Back to motions</a>
+ </div>
+ </div>
+</div>
+{{ with .Decision }}
+<div class="column">
+ <div class="ui raised segment">
+ {{ template "motion_fragment" . }}
+ </div>
+</div>
+{{ end }}
+<form action="/vote/{{ .Decision.Tag }}/{{ .VoteChoice }}" method="post">
+ <div class="ui form">
+ {{ if eq 1 .VoteChoice }}
+ <button class="ui right labeled green icon button" type="submit"><i class="check circle icon"></i> Vote {{ .VoteChoice }}</button>
+ {{ else if eq -1 .VoteChoice }}
+ <button class="ui right labeled red icon button" type="submit"><i class="minus circle icon"></i> Vote {{ .VoteChoice }}</button>
+ {{ else }}
+ <button class="ui right labeled grey icon button" type="submit"><i class="circle icon"></i> Vote {{ .VoteChoice }}</button>
+ {{ end }}
+ </div>
+</form>
+{{ template "footer" . }} \ No newline at end of file
diff --git a/boardvoting/templates/direct_vote_mail.txt b/boardvoting/templates/direct_vote_mail.txt
new file mode 100644
index 0000000..95bacb8
--- /dev/null
+++ b/boardvoting/templates/direct_vote_mail.txt
@@ -0,0 +1,10 @@
+Dear Board,
+
+{{ .Voter }} has just voted {{ .Vote }} on motion {{ .Decision.Tag }}.
+
+Motion:
+ {{ .Decision.Title }}
+ {{ .Decision.Content }}
+
+Kind regards,
+the vote system \ No newline at end of file
diff --git a/boardvoting/templates/edit_motion_form.html b/boardvoting/templates/edit_motion_form.html
new file mode 100644
index 0000000..f686183
--- /dev/null
+++ b/boardvoting/templates/edit_motion_form.html
@@ -0,0 +1,72 @@
+{{ template "header" . }}
+<div class="column">
+ <div class="ui floated right secondary menu">
+ <a href="/motions/" class="item" title="Show all votes">Back to
+ motions</a>
+ </div>
+</div>
+<div class="column">
+ <div class="ui raised segment">
+ <form action="/motions/{{ .Form.Decision.Tag }}/edit" method="post">
+ <div class="ui form{{ if .Form.Errors }} error{{ end }}">
+ <div class="three fields">
+ <div class="field">
+ <label>ID:</label>
+ <a href="/motions/{{ .Form.Decision.Tag }}">{{ .Form.Decision.Tag }}</a>
+ </div>
+ <div class="field">
+ <label>Proponent:</label>
+ {{ .Voter.Name }}
+ </div>
+ <div class="field">
+ <label>Proposed date/time:</label>
+ {{ .Form.Decision.Proposed|date "2006-01-02 15:04:05 UTC" }}
+ </div>
+ </div>
+ <div class="required field{{ if .Form.Errors.Title }} error{{ end }}">
+ <label for="Title">Title:</label>
+ <input name="Title" type="text" value="{{ .Form.Title }}">
+ </div>
+ <div class="required field{{ if .Form.Errors.Content }} error{{ end }}">
+ <label for="Content">Text:</label>
+ <textarea name="Content">{{ .Form.Content }}</textarea>
+ </div>
+ <div class="two fields">
+ <div class="required field{{ if .Form.Errors.VoteType }} error{{ end }}">
+ <label for="VoteType">Vote type:</label>
+ <select name="VoteType">
+ <option value="0"
+ {{ if eq "0" .Form.VoteType }}selected{{ end }}>
+ Motion
+ </option>
+ <option value="1"
+ {{ if eq "1" .Form.VoteType }}selected{{ end }}>
+ Veto
+ </option>
+ </select>
+ </div>
+ <div class="required field{{ if .Form.Errors.Due }} error{{ end }}">
+ <label for="Due">Due: (autofilled from chosen
+ option)</label>
+ <select name="Due">
+ <option value="+3 days">In 3 Days</option>
+ <option value="+7 days">In 1 Week</option>
+ <option value="+14 days">In 2 Weeks</option>
+ <option value="+28 days">In 4 Weeks</option>
+ </select>
+ </div>
+ </div>
+ {{ with .Form.Errors }}
+ <div class="ui error message">
+ {{ with .Title }}<p>{{ . }}</p>{{ end }}
+ {{ with .Content }}<p>{{ . }}</p>{{ end }}
+ {{ with .VoteType }}<p>{{ . }}</p>{{ end }}
+ {{ with .Due }}<p>{{ . }}</p>{{ end }}
+ </div>
+ {{ end }}
+ <button class="ui button" type="submit">Propose</button>
+ </div>
+ </form>
+ </div>
+</div>
+{{ template "footer" . }} \ No newline at end of file
diff --git a/boardvoting/templates/footer.html b/boardvoting/templates/footer.html
new file mode 100644
index 0000000..f2bc089
--- /dev/null
+++ b/boardvoting/templates/footer.html
@@ -0,0 +1,12 @@
+{{ define "footer" }}
+</div>
+<script type="text/javascript">
+ $(document).ready(function() {
+ $('.message .close').on('click', function() {
+ $(this).closest('.message').transition('fade');
+ });
+ });
+</script>
+</body>
+</html>
+{{ end }} \ No newline at end of file
diff --git a/boardvoting/templates/header.html b/boardvoting/templates/header.html
new file mode 100644
index 0000000..8e0aedc
--- /dev/null
+++ b/boardvoting/templates/header.html
@@ -0,0 +1,26 @@
+{{ define "header" -}}
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/html">
+<head>
+ <title>{{ block "pagetitle" . }}CAcert Board Decisions{{ end }}{{ if .PageTitle }} - {{ .PageTitle }}{{ end }}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+ <link rel="stylesheet" type="text/css" href="/static/semantic.min.css"/>
+ <script type="text/javascript" src="/static/js/jquery.min.js"></script>
+ <script type="text/javascript" src="/static/semantic.min.js"></script>
+</head>
+<body class="site">
+<div class="ui container">
+ <h1 class="ui header">{{ template "pagetitle" . }}{{ if .Voter }}<div class="ui left pointing label">Authenticated as {{ .Voter.Name }} &lt;{{ .Voter.Reminder }}&gt;</div>{{ end }}</h1>
+ {{ with .Flashes }}
+ <div class="ui info message">
+ <i class="close icon"></i>
+ <div class="ui list">
+ {{ range . }}
+ <div class="ui item">{{ . }}</div>
+ {{ end }}
+ </div>
+ </div>
+ {{ end }}
+</div>
+<div class="ui one column grid container">
+{{ end }} \ No newline at end of file
diff --git a/boardvoting/templates/motion.html b/boardvoting/templates/motion.html
new file mode 100644
index 0000000..8fc7530
--- /dev/null
+++ b/boardvoting/templates/motion.html
@@ -0,0 +1,19 @@
+{{ template "header" . }}
+{{ $voter := .Voter }}
+<div class="column">
+ <div class="ui basic segment">
+ <div class="ui floated right secondary menu">
+ <a href="/motions/" class="item" title="Show all votes">All votes</a>
+ {{ if $voter }}<a href="/motions/?unvoted=1" class="item" title="Show my outstanding votes">My outstanding votes</a>{{ end }}
+ </div>
+ </div>
+</div>
+{{ with .Decision }}
+<div class="column">
+ <div class="ui raised segment">
+ {{ template "motion_fragment" . }}
+ {{ if $voter }}{{ template "motion_actions" . }}{{ end }}
+ </div>
+</div>
+{{ end}}
+{{ template "footer" . }} \ No newline at end of file
diff --git a/boardvoting/templates/motion_fragments.html b/boardvoting/templates/motion_fragments.html
new file mode 100644
index 0000000..dbe59c2
--- /dev/null
+++ b/boardvoting/templates/motion_fragments.html
@@ -0,0 +1,64 @@
+{{ define "motion_fragment" }}
+<span class="ui {{ template "status_class" .Status }} ribbon label">{{ .Status|toString|title }}</span>
+<span class="header">{{ .Modified|date "2006-01-02 15:04:05 UTC" }}</span>
+<h3 class="header"><a href="/motions/{{ .Tag }}">{{ .Tag }}: {{ .Title }}</a></h3>
+<p>{{ wrap 76 .Content | nl2br }}</p>
+<table class="ui small definition table">
+ <tbody>
+ <tr>
+ <td>Due</td>
+ <td>{{.Due|date "2006-01-02 15:04:05 UTC"}}</td>
+ </tr>
+ <tr>
+ <td>Proposed</td>
+ <td>{{.Proposer}} ({{.Proposed|date "2006-01-02 15:04:05 UTC"}})</td>
+ </tr>
+ <tr>
+ <td>Vote type:</td>
+ <td>{{ .VoteType|toString|title }}</td>
+ </tr>
+ <tr>
+ <td>Votes:</td>
+ <td>
+ <div class="ui labels">
+ <div class="ui basic label green"><i
+ class="check circle icon"></i>Aye
+ <div class="detail">{{.Ayes}}</div>
+ </div>
+ <div class="ui basic label red"><i
+ class="minus circle icon"></i>Naye
+ <div class="detail">{{.Nayes}}</div>
+ </div>
+ <div class="ui basic label grey"><i class="circle icon"></i>Abstain
+ <div class="detail">{{.Abstains}}</div>
+ </div>
+ </div>
+ {{ if .Votes }}
+ <div class="list">
+ {{ range .Votes }}
+ <div class="item">{{ .Name }}: {{ .Vote.Vote }}</div>
+ {{ end }}
+ </div>
+ <a href="/motions/{{ .Tag }}">Hide Votes</a>
+ {{ else if or ((ne 0 .Ayes) (ne 0 .Nayes) (ne 0 .Abstains)) }}
+ <a href="/motions/{{ .Tag }}?showvotes=1">Show Votes</a>
+ {{ end }}
+ </td>
+ </tr>
+ </tbody>
+</table>
+{{ end }}
+
+{{ define "status_class" }}{{ if eq . 0 }}blue{{ else if eq . 1 }}green{{ else if eq . -1 }}red{{ else if eq . -2 }}grey
+{{ end }}{{ end }}
+
+{{ define "motion_actions" }}
+{{ if eq .Status 0 }}
+<a class="ui compact right labeled green icon button" href="/vote/{{ .Tag }}/aye"><i class="check circle icon"></i> Aye</a>
+<a class="ui compact right labeled red icon button" href="/vote/{{ .Tag }}/naye"><i class="minus circle icon"></i> Naye</a>
+<a class="ui compact right labeled grey icon button" href="/vote/{{ .Tag }}/abstain"><i class="circle icon"></i> Abstain</a>
+<a class="ui compact left labeled icon button" href="/proxy/{{ .Tag }}"><i class="users icon"></i> Proxy Vote</a>
+<a class="ui compact left labeled icon button" href="/motions/{{ .Tag }}/edit"><i class="edit icon"></i> Modify</a>
+<a class="ui compact left labeled icon button" href="/motions/{{ .Tag }}/withdraw"><i class="trash icon"></i> Withdraw</a>
+{{ end }}
+{{ end }}
diff --git a/boardvoting/templates/motions.html b/boardvoting/templates/motions.html
new file mode 100644
index 0000000..3f82092
--- /dev/null
+++ b/boardvoting/templates/motions.html
@@ -0,0 +1,52 @@
+{{ template "header" . }}
+{{ $voter := .Voter }}
+<div class="column">
+ <div class="ui basic segment">
+ <div class="ui floated right secondary menu">
+
+ <a href="/motions/" class="{{ if not .Params.Flags.Unvoted }}active {{ end }}item" title="Show all votes">All votes</a>
+ {{ if $voter }}<a href="/motions/?unvoted=1" class="{{ if .Params.Flags.Unvoted }}active {{ end}}item" title="Show my outstanding votes">My outstanding votes</a>{{ end }}
+ </div>
+ {{ if $voter }}<a class="ui primary button" href="/newmotion/">New motion</a>{{ end }}
+ {{ if .PrevPage -}}
+ <a href="?page={{ .PrevPage }}{{ if .Params.Flags.Unvoted }}&unvoted=1{{ end }}"
+ class="ui left labeled icon button" title="newer motions"><i class="left arrow icon"></i> newer</a>
+ {{- end }}
+ {{ if .NextPage -}}
+ <a href="?page={{ .NextPage }}{{ if .Params.Flags.Unvoted }}&unvoted=1{{ end }}"
+ class="ui right labeled icon button" title="older motions"><i class="right arrow icon"></i> older</a>
+ {{- end }}
+ </div>
+</div>
+{{ if .Decisions }}
+ {{ range .Decisions }}
+ <div class="column">
+ <div class="ui raised segment">
+ {{ template "motion_fragment" . }}
+ {{ if $voter }}{{ template "motion_actions" . }}{{ end }}
+ </div>
+ </div>
+ {{ end }}
+<div class="column">
+ <div class="ui basic segment">
+{{ if $voter }}<a class="ui primary button" href="/newmotion/">New motion</a>{{ end }}
+{{ if .PrevPage -}}
+ <a href="?page={{ .PrevPage }}{{ if .Params.Flags.Unvoted }}&unvoted=1{{ end }}"
+ class="ui left labeled icon button" title="newer motions">
+ <i class="left arrow icon"></i> newer</a>
+{{- end }}
+{{ if .NextPage -}}
+ <a href="?page={{ .NextPage }}{{ if .Params.Flags.Unvoted }}&unvoted=1{{ end }}"
+ class="ui right labeled icon button" title="older motions">
+ <i class="right arrow icon"></i> older</a>
+{{- end }}
+ </div>
+</div>
+{{ else }}
+ {{ if .Params.Flags.Unvoted }}
+ <p>There are no motions requiring a vote from you.</p>
+ {{ else }}
+ <p>There are no motions in the system yet.</p>
+ {{ end }}
+{{ end }}
+{{ template "footer" . }} \ No newline at end of file
diff --git a/boardvoting/templates/proxy_vote_form.html b/boardvoting/templates/proxy_vote_form.html
new file mode 100644
index 0000000..3bfa9df
--- /dev/null
+++ b/boardvoting/templates/proxy_vote_form.html
@@ -0,0 +1,54 @@
+{{ template "header" . }}
+{{ $form := .Form }}
+<div class="column">
+ <div class="ui basic segment">
+ <div class="ui floated right secondary menu">
+ <a href="/motions/" class="item" title="Show all votes">Back to
+ motions</a>
+ </div>
+ </div>
+</div>
+<div class="column">
+ <div class="ui raised segment">
+ {{ with .Decision }}
+ {{ template "motion_fragment" . }}
+ {{ end }}
+ <form action="/proxy/{{ .Decision.Tag }}" method="post">
+ <div class="ui form{{ if .Form.Errors }} error{{ end }}">
+ <div class="two fields">
+ <div class="required field{{ if .Form.Errors.Voter }} error{{ end }}">
+ <label for="Voter">Voter</label>
+ <select name="Voter">
+ {{ range .Voters }}
+ <option value="{{ .Id }}"
+ {{ if eq (.Id | print) $form.Voter }}
+ selected{{ end }}>{{ .Name }}</option>
+ {{ end }}
+ </select>
+ </div>
+ <div class="required field{{ if .Form.Errors.Vote }} error{{ end }}">
+ <label for="Vote">Vote</label>
+ <select name="Vote">
+ <option value="1"{{ if eq .Form.Vote "1" }} selected{{ end }}>Aye</option>
+ <option value="0"{{ if eq .Form.Vote "0" }} selected{{ end }}>Abstain</option>
+ <option value="-1"{{ if eq .Form.Vote "-1" }} selected{{ end }}>Naye</option>
+ </select>
+ </div>
+ </div>
+ <div class="required field{{ if .Form.Errors.Justification }} error{{ end }}">
+ <label for="Justification">Justification</label>
+ <textarea name="Justification" rows="2">{{ .Form.Justification }}</textarea>
+ </div>
+ {{ with .Form.Errors }}
+ <div class="ui error message">
+ {{ with .Voter }}<p>{{ . }}</p>{{ end }}
+ {{ with .Vote }}<p>{{ . }}</p>{{ end }}
+ {{ with .Justification }}<p>{{ . }}</p>{{ end }}
+ </div>
+ {{ end }}
+ <button class="ui primary left labeled icon button" type="submit"><i class="users icon"></i> Proxy Vote</button>
+ </div>
+ </form>
+ </div>
+</div>
+{{ template "footer" . }} \ No newline at end of file
diff --git a/boardvoting/templates/proxy_vote_mail.txt b/boardvoting/templates/proxy_vote_mail.txt
new file mode 100644
index 0000000..dd7403f
--- /dev/null
+++ b/boardvoting/templates/proxy_vote_mail.txt
@@ -0,0 +1,13 @@
+Dear Board,
+
+{{ .Proxy }} has just registered a proxy vote of {{ .Vote }} for {{ .Voter }} on motion {{ .Decision.Tag }}.
+
+The justification for this was:
+{{ .Justification }}
+
+Motion:
+{{ .Decision.Title }}
+{{ .Decision.Content }}
+
+Kind regards,
+the vote system \ No newline at end of file
diff --git a/boardvoting/templates/remind_voter_mail.txt b/boardvoting/templates/remind_voter_mail.txt
new file mode 100644
index 0000000..ddf5366
--- /dev/null
+++ b/boardvoting/templates/remind_voter_mail.txt
@@ -0,0 +1,15 @@
+{{ $baseurl := .BaseURL }}
+Dear {{ .Name }},
+
+You have not voted in the following CAcert Board vote(s)/motion(s):
+
+{{ range .Decisions -}}
+{{ .VoteType }} {{ .Tag }} {{ .Title }}
+Due: {{ .Due }}
+{{ $baseurl }}/motions/{{ .Tag }}
+{{ end }}
+
+To view all your outstanding motions: {{ $baseurl }}/motions/?unvoted=1
+
+Kind regards,
+the vote system \ No newline at end of file
diff --git a/boardvoting/templates/update_motion_mail.txt b/boardvoting/templates/update_motion_mail.txt
new file mode 100644
index 0000000..ddb0996
--- /dev/null
+++ b/boardvoting/templates/update_motion_mail.txt
@@ -0,0 +1,26 @@
+Dear Board,
+
+{{ .Name }} has modified motion {{ .Tag }} to the following:
+
+{{ .Title }}
+
+{{ wrap 76 .Content }}
+
+Vote type: {{ .VoteType }}
+
+Voting will close {{ .Due }}
+
+To vote please choose:
+
+Aye: {{ .VoteURL }}/aye
+Naye: {{ .VoteURL }}/naye
+Abstain: {{ .VoteURL }}/abstain
+
+Please be aware, that if you have voted already your vote is still
+registered and valid. If this modification has an impact on how you wish to
+vote, you are responsible for voting again.
+
+To see all your pending votes: {{ .UnvotedURL }}
+
+Kind regards,
+the voting system \ No newline at end of file
diff --git a/boardvoting/templates/withdraw_motion_form.html b/boardvoting/templates/withdraw_motion_form.html
new file mode 100644
index 0000000..c5f0846
--- /dev/null
+++ b/boardvoting/templates/withdraw_motion_form.html
@@ -0,0 +1,21 @@
+{{ template "header" . }}
+<div class="column">
+ <div class="ui basic segment">
+ <div class="ui floated right secondary menu">
+ <a href="/motions/" class="item" title="Show all votes">Back to motions</a>
+ </div>
+ </div>
+</div>
+{{ with .Decision }}
+<div class="column">
+ <div class="ui raised segment">
+ {{ template "motion_fragment" . }}
+ </div>
+</div>
+{{ end }}
+<form action="/motions/{{ .Decision.Tag }}/withdraw" method="post">
+ <div class="ui form">
+ <button class="ui primary left labeled icon button" type="submit"><i class="trash icon"></i> Withdraw</button>
+ </div>
+</form>
+{{ template "footer" . }}
diff --git a/boardvoting/templates/withdraw_motion_mail.txt b/boardvoting/templates/withdraw_motion_mail.txt
new file mode 100644
index 0000000..fb3ed87
--- /dev/null
+++ b/boardvoting/templates/withdraw_motion_mail.txt
@@ -0,0 +1,10 @@
+Dear Board,
+
+{{ .Name }} has withdrawn the motion {{ .Tag }} that was as follows:
+
+{{ .Title }}
+
+{{ wrap 76 .Content }}
+
+Kind regards,
+the voting system \ No newline at end of file