summaryrefslogtreecommitdiffstats
path: root/patchwork/templates/patchwork
diff options
context:
space:
mode:
Diffstat (limited to 'patchwork/templates/patchwork')
-rw-r--r--patchwork/templates/patchwork/activation_email.txt11
-rw-r--r--patchwork/templates/patchwork/activation_email_subject.txt1
-rw-r--r--patchwork/templates/patchwork/bundle.html47
-rw-r--r--patchwork/templates/patchwork/bundles.html59
-rw-r--r--patchwork/templates/patchwork/confirm-error.html19
-rw-r--r--patchwork/templates/patchwork/filters.html183
-rw-r--r--patchwork/templates/patchwork/help/about.html17
-rw-r--r--patchwork/templates/patchwork/help/index.html2
-rw-r--r--patchwork/templates/patchwork/help/pwclient.html23
-rw-r--r--patchwork/templates/patchwork/list.html25
-rw-r--r--patchwork/templates/patchwork/login.html27
-rw-r--r--patchwork/templates/patchwork/logout.html8
-rw-r--r--patchwork/templates/patchwork/mail-form.html38
-rw-r--r--patchwork/templates/patchwork/mail-settings.html37
-rw-r--r--patchwork/templates/patchwork/optin-request.html50
-rw-r--r--patchwork/templates/patchwork/optin-request.mail12
-rw-r--r--patchwork/templates/patchwork/optin.html19
-rw-r--r--patchwork/templates/patchwork/optout-request.html51
-rw-r--r--patchwork/templates/patchwork/optout-request.mail12
-rw-r--r--patchwork/templates/patchwork/optout.html22
-rw-r--r--patchwork/templates/patchwork/pagination.html45
-rw-r--r--patchwork/templates/patchwork/patch-change-notification-subject.text1
-rw-r--r--patchwork/templates/patchwork/patch-change-notification.mail20
-rw-r--r--patchwork/templates/patchwork/patch-list.html268
-rw-r--r--patchwork/templates/patchwork/patch.html199
-rw-r--r--patchwork/templates/patchwork/profile.html144
-rw-r--r--patchwork/templates/patchwork/project.html58
-rw-r--r--patchwork/templates/patchwork/projects.html27
l---------patchwork/templates/patchwork/pwclient1
-rw-r--r--patchwork/templates/patchwork/pwclientrc15
-rw-r--r--patchwork/templates/patchwork/register.mail11
-rw-r--r--patchwork/templates/patchwork/registration-confirm.html13
-rw-r--r--patchwork/templates/patchwork/registration_form.html121
-rw-r--r--patchwork/templates/patchwork/todo-list.html17
-rw-r--r--patchwork/templates/patchwork/todo-lists.html29
-rw-r--r--patchwork/templates/patchwork/user-link-confirm.html19
-rw-r--r--patchwork/templates/patchwork/user-link.html32
-rw-r--r--patchwork/templates/patchwork/user-link.mail12
38 files changed, 1695 insertions, 0 deletions
diff --git a/patchwork/templates/patchwork/activation_email.txt b/patchwork/templates/patchwork/activation_email.txt
new file mode 100644
index 0000000..caf514a
--- /dev/null
+++ b/patchwork/templates/patchwork/activation_email.txt
@@ -0,0 +1,11 @@
+Hi,
+
+This email is to confirm your account on the patchwork patch-tracking
+system. You can activate your account by visiting the url:
+
+ http://{{site.domain}}{% url 'patchwork.views.confirm' key=confirmation.key %}
+
+If you didn't request a user account on patchwork, then you can ignore
+this mail.
+
+Happy patchworking.
diff --git a/patchwork/templates/patchwork/activation_email_subject.txt b/patchwork/templates/patchwork/activation_email_subject.txt
new file mode 100644
index 0000000..c409f38
--- /dev/null
+++ b/patchwork/templates/patchwork/activation_email_subject.txt
@@ -0,0 +1 @@
+Patchwork account confirmation
diff --git a/patchwork/templates/patchwork/bundle.html b/patchwork/templates/patchwork/bundle.html
new file mode 100644
index 0000000..4a96b6b
--- /dev/null
+++ b/patchwork/templates/patchwork/bundle.html
@@ -0,0 +1,47 @@
+{% extends "base.html" %}
+
+{% load person %}
+{% load static %}
+
+{% block headers %}
+ <script type="text/javascript" src="{% static "js/jquery-1.10.1.min.js" %}"></script>
+ <script type="text/javascript" src="{% static "js/jquery.tablednd.js" %}"></script>
+ <script type="text/javascript" src="{% static "js/bundle.js" %}"></script>
+{% endblock %}
+{% block title %}{{project.name}}{% endblock %}
+{% block heading %}bundle: {{bundle.owner.username}} /
+{{bundle.name}}{% endblock %}
+
+{% block body %}
+
+<p>This bundle contains patches for the {{ bundle.project.linkname }}
+project.</p>
+
+<p><a href="{% url 'patchwork.views.bundle.mbox' username=bundle.owner.username bundlename=bundle.name %}">Download bundle as mbox</a></p>
+
+{% if bundleform %}
+<form method="post">
+ {% csrf_token %}
+ <input type="hidden" name="form" value="bundle"/>
+<table class="form">
+
+ <tr>
+ <th colspan="2" class="headerrow">Bundle settings</th>
+ </tr>
+
+{{ bundleform }}
+ <tr>
+ <td colspan="2" class="submitrow">
+ <input type="submit" name="action" value="Update"/>
+ <input type="submit" name="action" value="Delete"/>
+ </td>
+ </tr>
+</table>
+</form>
+
+<div style="clear: both; padding: 1em;"></div>
+{% endif %}
+
+{% include "patchwork/patch-list.html" %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/bundles.html b/patchwork/templates/patchwork/bundles.html
new file mode 100644
index 0000000..11fb89d
--- /dev/null
+++ b/patchwork/templates/patchwork/bundles.html
@@ -0,0 +1,59 @@
+{% extends "base.html" %}
+
+{% load static %}
+
+{% block title %}Bundles{% endblock %}
+{% block heading %}Bundles{% endblock %}
+
+{% block body %}
+
+{% if bundles %}
+<table class="bundlelist">
+ <tr>
+ <th>Name</th>
+ <th>Project</th>
+ <th>Public Link</th>
+ <th>Patches</td>
+ <th>Download</th>
+ <th>Delete</th>
+ </tr>
+{% for bundle in bundles %}
+ <tr>
+ <td><a href="{{ bundle.get_absolute_url }}">{{ bundle.name }}</a></td>
+ <td>{{ bundle.project.linkname }}</td>
+ <td>
+ {% if bundle.public %}
+ <a href="{{ bundle.public_url }}">{{ bundle.public_url }}</a>
+ {% endif %}
+ </td>
+ <td style="text-align: right">{{ bundle.n_patches }}</td>
+ <td style="text-align: center;"><a
+ href="{% url 'patchwork.views.bundle.mbox' username=bundle.owner.username bundlename=bundle.name %}"
+ ><img src="{% static "images/16-em-down.png" %}" width="16" height="16" alt="download"
+ title="download"/></a></td>
+ <td style="text-align: center;">
+ <form method="post"
+ onsubmit="return confirm_delete('bundle', '{{bundle.name|escapejs}}');">
+ {% csrf_token %}
+ {{ bundle.delete_form.as_p }}
+ <input type="image"
+ src="{% static "images/patchwork/16-em-cross.png" %}" width="16" height="16" alt="delete"
+ title="delete" border="0" style="border: none;"/>
+ </form>
+ </td>
+
+ </tr>
+{% endfor %}
+</table>
+{% endif %}
+
+<p>Bundles are groups of related patches. You can create bundles by
+selecting patches from a project, then using the 'create bundle' form
+to give your bundle a name. Each bundle can be public or private; public
+bundles are given a persistent URL, based you your username and the name
+of the bundle. Private bundles are only visible to you.</p>
+
+{% if not bundles %}
+<p>You have no bundles.</p>
+{% endif %}
+{% endblock %}
diff --git a/patchwork/templates/patchwork/confirm-error.html b/patchwork/templates/patchwork/confirm-error.html
new file mode 100644
index 0000000..81292e2
--- /dev/null
+++ b/patchwork/templates/patchwork/confirm-error.html
@@ -0,0 +1,19 @@
+{% extends "base.html" %}
+
+{% block title %}Confirmation{% endblock %}
+{% block heading %}Confirmation{% endblock %}
+
+
+{% block body %}
+
+{% if error == 'inactive' %}
+<p>This confirmation has already been processed; you've probably visited this
+page before.</p>
+{% endif %}
+
+{% if error == 'expired' %}
+<p>The confirmation has expired. If you'd still like to perform the
+{{conf.get_type_display}} process, you'll need to resubmit the request.</p>
+{% endif %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/filters.html b/patchwork/templates/patchwork/filters.html
new file mode 100644
index 0000000..10ca587
--- /dev/null
+++ b/patchwork/templates/patchwork/filters.html
@@ -0,0 +1,183 @@
+{% load static %}
+
+<script type="text/javascript" language="JavaScript">
+var filterform_displayed = false;
+function filter_click()
+{
+ var form = document.getElementById('filterform');
+ if (!form) {
+ return;
+ }
+
+ if (filterform_displayed) {
+ form.style['display'] = 'none';
+ filterform_displayed = false;
+ } else {
+ form.style['display'] = 'block';
+ filterform_displayed = true;
+ }
+
+
+}
+function enable_selected_submitter(select, input)
+{
+ select.name = 'submitter';
+ input.name = '';
+}
+function filter_form_submit(form)
+{
+ var i;
+
+ var submitter_select = document.getElementById("submitter_select");
+ var submitter_input = document.getElementById("submitter_input");
+ if (!submitter_select || !submitter_input) {
+ req = null;
+ return;
+ }
+
+ /* submitter handling. if possible, use the select box, otherwise leave
+ * as-is (and so the text box is used). */
+
+ if (submitter_select.options.length == 0) {
+ /* if there's no match, just use the input */
+
+ } else if (submitter_select.options.length == 1) {
+ /* if there's only one match, request by id */
+ submitter_select.selectedIndex = 0;
+ enable_selected_submitter(submitter_select, submitter_input);
+
+ } else if (submitter_select.selectedIndex != -1) {
+ /* if the user has explicitly selected, request by id */
+ enable_selected_submitter(submitter_select, submitter_input);
+
+ }
+
+ for (i = 0; i < form.elements.length; i++) {
+ var e = form.elements[i];
+ if (e.type == 'submit') {
+ continue;
+ }
+
+ /* handle submitter data */
+ if (e.type == 'select-one') {
+ if (e.name == '') {
+ e.disabled = true;
+ }
+ if (e.selectedIndex != -1
+ && e.options[e.selectedIndex].value == '') {
+ e.disabled = true;
+ }
+
+ continue;
+ }
+
+ if (e.value == '') {
+ e.disabled = true;
+ }
+ }
+}
+
+var req = null;
+
+function submitter_complete_response()
+{
+ if (req.readyState != 4) {
+ return
+ }
+
+ var completions;
+ eval("completions = " + req.responseText);
+
+ if (completions.length == 0) {
+ req = null;
+ return;
+ }
+
+ var submitter_select = document.getElementById("submitter_select");
+ var submitter_input = document.getElementById("submitter_input");
+ if (!submitter_select || !submitter_input) {
+ req = null;
+ return;
+ }
+
+ for (i = 0; i < completions.length; i++) {
+ name = completions[i]['fields']['name'];
+ if (name) {
+ name = completions[i]['fields']['name'] +
+ ' <' + completions[i]['fields']['email'] + '>';
+ } else {
+ name = completions[i]['fields']['email'];
+ }
+ o = new Option(name, completions[i]['pk']);
+ submitter_select.options[i] = o;
+ }
+
+ /* remove remaining options */
+ for (; i < submitter_select.length; i++) {
+ submitter_select.options[i] = null;
+ }
+
+ submitter_select.disabled = false;
+ req = null;
+}
+
+function submitter_field_change(field)
+{
+ var limit = 20;
+ var value = field.value;
+ if (value.length < 4) {
+ return;
+ }
+
+ if (req) {
+ return;
+ }
+
+ var url = '{% url 'patchwork.views.submitter_complete' %}?q=' + value +
+ '&l=' + limit;
+ req = new XMLHttpRequest();
+ req.onreadystatechange = submitter_complete_response;
+ req.open("GET", url, true);
+ req.send('');
+}
+</script>
+
+<div class="filters">
+ <div id="filtersummary">
+ <strong><a href="javascript:filter_click()">Filters</a>:</strong>
+ {% if filters.applied_filters %}
+ {% for filter in filters.applied_filters %}
+ {{ filter.name }} = {{ filter.condition }}
+ {% if not filter.forced %}
+ <a href="{{ filter.url_without_me }}"><img
+ width="16" height="16" alt="remove filter" title="remove filter"
+ src="{% static "images/16-circle-blue-remove.png" %}"></a>
+ {% endif %}
+ {% if not forloop.last %}&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;{% endif %}
+ {% endfor %}
+ {% else %}
+ none
+ <a href="javascript:filter_click()"><img
+ width="16" height="16" alt="add filter" title="add filter"
+ src="{% static "images/16-circle-blue-add.png" %}"></a>
+ {% endif %}
+ </div>
+ <div id="filterform" style="padding-top: 1em; display: none">
+ <form action="" method="get" onSubmit="return filter_form_submit(this)">
+ <table>
+ {% for filter in filters.available_filters %}
+ <tr>
+ <td>{{ filter.name }}</td>
+ <td>{{ filter.form }}</td>
+ </tr>
+ {% endfor %}
+ <tr>
+ <td/>
+ <td><input type="submit" value="Apply"/></td>
+ </tr>
+ </table>
+ </form>
+ </div>
+</div>
+
+
diff --git a/patchwork/templates/patchwork/help/about.html b/patchwork/templates/patchwork/help/about.html
new file mode 100644
index 0000000..7befa6b
--- /dev/null
+++ b/patchwork/templates/patchwork/help/about.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+
+{% block title %}About{% endblock %}
+{% block heading %} - About Patchwork{% endblock %}
+
+{% block body %}
+
+<p>Patchwork is free software, and is available from the
+<a href="http://jk.ozlabs.org/projects/patchwork/">patchwork website</a>.</p>
+
+<p>Patchwork is built on the <a href="http://djangoproject.com/">django</a>
+web framework.</p>
+
+<p>Icons from the <a href="http://sweetie.sublink.ca/">Sweetie</a> icon set.</a>
+
+{% endblock %}
+
diff --git a/patchwork/templates/patchwork/help/index.html b/patchwork/templates/patchwork/help/index.html
new file mode 100644
index 0000000..5cb6467
--- /dev/null
+++ b/patchwork/templates/patchwork/help/index.html
@@ -0,0 +1,2 @@
+{% extends "base.html" %}
+
diff --git a/patchwork/templates/patchwork/help/pwclient.html b/patchwork/templates/patchwork/help/pwclient.html
new file mode 100644
index 0000000..7101ec1
--- /dev/null
+++ b/patchwork/templates/patchwork/help/pwclient.html
@@ -0,0 +1,23 @@
+{% extends "base.html" %}
+
+{% block title %}Command-line client{% endblock %}
+{% block heading %} - Command-line client{% endblock %}
+
+{% block body %}
+
+<p><code>pwclient</code> is the command-line client for patchwork. Currently,
+it provides access to some read-only features of patchwork, such as downloading
+and applying patches.</p>
+
+<p>To use pwclient, you will need:</p>
+<ul>
+ <li>The <a href="{% url 'patchwork.views.pwclient' %}">pwclient</a>
+ program (11kB, python script)</li>
+ <li>(optional) a <code>.pwclientrc</code> file in your home directory.</li>
+</ul>
+
+<p>You can create your own <code>.pwclientrc</code> file. Each
+<a href="{% url 'patchwork.views.projects' %}">patchwork project</a>
+provides a sample linked from the 'project info' page.</p>
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/list.html b/patchwork/templates/patchwork/list.html
new file mode 100644
index 0000000..654fe8c
--- /dev/null
+++ b/patchwork/templates/patchwork/list.html
@@ -0,0 +1,25 @@
+{% extends "base.html" %}
+
+{% load person %}
+{% load static %}
+
+{% block title %}{{project.name}}{% endblock %}
+{% block heading %}{{project.name}}{% endblock %}
+
+{% block body %}
+
+<h2>Incoming patches</h2>
+
+{% if errors %}
+<p>The following error{{ errors|length|pluralize:" was,s were" }} encountered
+while updating patches:</p>
+<ul class="errorlist">
+{% for error in errors %}
+ <li>{{ error }}</li>
+{% endfor %}
+</ul>
+{% endif %}
+
+{% include "patchwork/patch-list.html" %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/login.html b/patchwork/templates/patchwork/login.html
new file mode 100644
index 0000000..2dfc2a7
--- /dev/null
+++ b/patchwork/templates/patchwork/login.html
@@ -0,0 +1,27 @@
+{% extends "base.html" %}
+
+{% block title %}Login{% endblock %}
+{% block heading %}Login{% endblock %}
+
+
+{% block body %}
+<form method="post">
+{% csrf_token %}
+<table class="form loginform">
+ <tr>
+ <th colspan="2" class="headerrow">login</th>
+ </tr>
+ {% if error %}
+ <tr>
+ <td colspan="2">{{ error }}</td>
+ </tr>
+ {% endif %}
+ {{ form }}
+ <tr>
+ <td colspan="2" class="submitrow">
+ <input type="submit" value="Login"/>
+ </td>
+ </tr>
+</table>
+</form>
+{% endblock %}
diff --git a/patchwork/templates/patchwork/logout.html b/patchwork/templates/patchwork/logout.html
new file mode 100644
index 0000000..f030aee
--- /dev/null
+++ b/patchwork/templates/patchwork/logout.html
@@ -0,0 +1,8 @@
+{% extends "base.html" %}
+
+{% block title %}Logout{% endblock %}
+{% block heading %}Logout{% endblock %}
+
+{% block body %}
+<p>Logged out</p>
+{% endblock %}
diff --git a/patchwork/templates/patchwork/mail-form.html b/patchwork/templates/patchwork/mail-form.html
new file mode 100644
index 0000000..d71b2fb
--- /dev/null
+++ b/patchwork/templates/patchwork/mail-form.html
@@ -0,0 +1,38 @@
+{% extends "base.html" %}
+
+{% block title %}mail settings{% endblock %}
+{% block heading %}mail settings{% endblock %}
+
+{% block body %}
+
+<p>You can configure patchwork to send you mail on certain events,
+or block automated mail altogether. Enter your email address to
+view or change your email settings.</p>
+
+<form method="post">
+{% csrf_token %}
+<table class="form registerform">
+{% if form.errors %}
+ <tr>
+ <td colspan="2" class="error">
+ There was an error accessing your mail settings:
+ </td>
+ </tr>
+{% endif %}
+ <tr>
+ <th>{{ form.email.label_tag }}</th>
+ <td>
+ {{form.email}}
+ {{form.email.errors}}
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="submitrow">
+ <input type="submit" value="Access mail settings"/>
+ </td>
+ </tr>
+</table>
+</form>
+
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/mail-settings.html b/patchwork/templates/patchwork/mail-settings.html
new file mode 100644
index 0000000..440af08
--- /dev/null
+++ b/patchwork/templates/patchwork/mail-settings.html
@@ -0,0 +1,37 @@
+{% extends "base.html" %}
+
+{% block title %}mail settings{% endblock %}
+{% block heading %}mail settings{% endblock %}
+
+{% block body %}
+<p>Settings for <strong>{{email}}</strong>:</p>
+
+<table class="horizontal">
+ <tr>
+ <th>Opt-out list</th>
+{% if is_optout %}
+ <td>Patchwork <strong>may not</strong> send automated notifications to
+ this address.</td>
+ <td>
+ <form method="post" action="{% url 'patchwork.views.mail.optin' %}">
+ {% csrf_token %}
+ <input type="hidden" name="email" value="{{email}}"/>
+ <input type="submit" value="Opt-in"/>
+ </form>
+ </td>
+
+{% else %}
+ <td>Patchwork <strong>may</strong> send automated notifications to
+ this address.</td>
+ <td>
+ <form method="post" action="{% url 'patchwork.views.mail.optout' %}">
+ {% csrf_token %}
+ <input type="hidden" name="email" value="{{email}}"/>
+ <input type="submit" value="Opt-out"/>
+ </form>
+ </td>
+{% endif %}
+ </tr>
+</table>
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/optin-request.html b/patchwork/templates/patchwork/optin-request.html
new file mode 100644
index 0000000..3dfb1bd
--- /dev/null
+++ b/patchwork/templates/patchwork/optin-request.html
@@ -0,0 +1,50 @@
+{% extends "base.html" %}
+
+{% block title %}opt-in{% endblock %}
+{% block heading %}opt-in{% endblock %}
+
+{% block body %}
+{% if email_sent %}
+<p><strong>Opt-in confirmation email sent</strong></p>
+<p>An opt-in confirmation mail has been sent to
+<strong>{{confirmation.email}}</strong>, containing a link. Please click on
+that link to confirm your opt-in.</p>
+{% else %}
+{% if error %}
+<p class="error">{{error}}</p>
+{% endif %}
+
+{% if form %}
+<p>This form allows you to opt-in to automated email from patchwork. Use
+this if you have previously opted-out of patchwork mail, but now want to
+received notifications from patchwork.</p>
+When you submit it, an email will be sent to your address with a link to click
+to finalise the opt-in. Patchwork does this to prevent someone opting you in
+without your consent.</p>
+<form method="post" action="">
+{% csrf_token %}
+{{form.email.errors}}
+<div style="padding: 0.5em 1em 2em;">
+{{form.email.label_tag}}: {{form.email}}
+</div>
+<input type="submit" value="Send me an opt-in link">
+</form>
+{% endif %}
+
+{% if error and admins %}
+<p>If you are having trouble opting in, please email
+{% for admin in admins %}
+{% if admins|length > 1 and forloop.last %} or {% endif %}
+{{admin.0}} &lt;<a href="mailto:{{admin.1}}">{{admin.1}}</a
+>&gt;{% if admins|length > 2 and not forloop.last %}, {% endif %}
+{% endfor %}
+{% endif %}
+
+{% endif %}
+
+{% if user.is_authenticated %}
+<p>Return to your <a href="{% url 'patchwork.views.user.profile' %}">user
+profile</a>.</p>
+{% endif %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/optin-request.mail b/patchwork/templates/patchwork/optin-request.mail
new file mode 100644
index 0000000..d97c78b
--- /dev/null
+++ b/patchwork/templates/patchwork/optin-request.mail
@@ -0,0 +1,12 @@
+Hi,
+
+This email is to confirm that you would like to opt-in to automated
+email from the patchwork system at {{site.domain}}.
+
+To complete the opt-in process, visit:
+
+ http://{{site.domain}}{% url 'patchwork.views.confirm' key=confirmation.key %}
+
+If you didn't request this opt-in, you don't need to do anything.
+
+Happy patchworking.
diff --git a/patchwork/templates/patchwork/optin.html b/patchwork/templates/patchwork/optin.html
new file mode 100644
index 0000000..01aaa0e
--- /dev/null
+++ b/patchwork/templates/patchwork/optin.html
@@ -0,0 +1,19 @@
+{% extends "base.html" %}
+
+{% block title %}opt-in{% endblock %}
+{% block heading %}opt-in{% endblock %}
+
+{% block body %}
+
+<p><strong>Opt-in complete</strong>. You have sucessfully opted back in to
+automated email from this patchwork system, using the address
+<strong>{{email}}</strong>.</p>
+<p>If you later decide that you no longer want to receive automated mail from
+patchwork, just visit <a href="{% url 'patchwork.views.mail.settings' %}"
+>http://{{site.domain}}{% url 'patchwork.views.mail.settings' %}</a>, or
+visit the main patchwork page and navigate from there.</p>
+{% if user.is_authenticated %}
+<p>Return to your <a href="{% url 'patchwork.views.user.profile' %}">user
+profile</a>.</p>
+{% endif %}
+{% endblock %}
diff --git a/patchwork/templates/patchwork/optout-request.html b/patchwork/templates/patchwork/optout-request.html
new file mode 100644
index 0000000..092dbbb
--- /dev/null
+++ b/patchwork/templates/patchwork/optout-request.html
@@ -0,0 +1,51 @@
+{% extends "base.html" %}
+
+{% block title %}opt-out{% endblock %}
+{% block heading %}opt-out{% endblock %}
+
+{% block body %}
+{% if email_sent %}
+<p><strong>Opt-out confirmation email sent</strong></p>
+<p>An opt-out confirmation mail has been sent to
+<strong>{{confirmation.email}}</strong>, containing a link. Please click on
+that link to confirm your opt-out.</p>
+{% else %}
+{% if error %}
+<p class="error">{{error}}</p>
+{% endif %}
+
+{% if form %}
+<p>This form allows you to opt-out of automated email from patchwork.</p>
+<p>If you opt-out of email, Patchwork may still email you if you do certain
+actions yourself (such as create a new patchwork account), but will not send
+you unsolicited email.</p>
+When you submit it, one email will be sent to your address with a link to click
+to finalise the opt-out. Patchwork does this to prevent someone opting you out
+without your consent.</p>
+<form method="post" action="">
+{% csrf_token %}
+{{form.email.errors}}
+<div style="padding: 0.5em 1em 2em;">
+{{form.email.label_tag}}: {{form.email}}
+</div>
+<input type="submit" value="Send me an opt-out link">
+</form>
+{% endif %}
+
+{% if error and admins %}
+<p>If you are having trouble opting out, please email
+{% for admin in admins %}
+{% if admins|length > 1 and forloop.last %} or {% endif %}
+{{admin.0}} &lt;<a href="mailto:{{admin.1}}">{{admin.1}}</a
+>&gt;{% if admins|length > 2 and not forloop.last %}, {% endif %}
+{% endfor %}
+{% endif %}
+
+{% endif %}
+
+{% if user.is_authenticated %}
+<p>Return to your <a href="{% url 'patchwork.views.user.profile' %}">user
+profile</a>.</p>
+{% endif %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/optout-request.mail b/patchwork/templates/patchwork/optout-request.mail
new file mode 100644
index 0000000..67203ca
--- /dev/null
+++ b/patchwork/templates/patchwork/optout-request.mail
@@ -0,0 +1,12 @@
+Hi,
+
+This email is to confirm that you would like to opt-out from all email
+from the patchwork system at {{site.domain}}.
+
+To complete the opt-out process, visit:
+
+ http://{{site.domain}}{% url 'patchwork.views.confirm' key=confirmation.key %}
+
+If you didn't request this opt-out, you don't need to do anything.
+
+Happy patchworking.
diff --git a/patchwork/templates/patchwork/optout.html b/patchwork/templates/patchwork/optout.html
new file mode 100644
index 0000000..b140bf4
--- /dev/null
+++ b/patchwork/templates/patchwork/optout.html
@@ -0,0 +1,22 @@
+{% extends "base.html" %}
+
+{% block title %}opt-out{% endblock %}
+{% block heading %}opt-out{% endblock %}
+
+{% block body %}
+
+<p><strong>Opt-out complete</strong>. You have successfully opted-out of
+automated notifications from this patchwork system, from the address
+<strong>{{email}}</strong></p>
+<p>Please note that you may still receive email from other patchwork setups at
+different sites, as they are run independently. You may need to opt-out of
+those separately.</p>
+<p>If you later decide to receive mail from patchwork, just visit
+<a href="{% url 'patchwork.views.mail.settings' %}"
+>http://{{site.domain}}{% url 'patchwork.views.mail.settings' %}</a>, or
+visit the main patchwork page and navigate from there.</p>
+{% if user.is_authenticated %}
+<p>Return to your <a href="{% url 'patchwork.views.user.profile' %}">user
+profile</a>.</p>
+{% endif %}
+{% endblock %}
diff --git a/patchwork/templates/patchwork/pagination.html b/patchwork/templates/patchwork/pagination.html
new file mode 100644
index 0000000..3e95126
--- /dev/null
+++ b/patchwork/templates/patchwork/pagination.html
@@ -0,0 +1,45 @@
+{% load listurl %}
+
+{% ifnotequal page.paginator.num_pages 1 %}
+<div class="paginator">
+{% if page.has_previous %}
+ <span class="prev">
+ <a href="{% listurl page=page.previous_page_number %}"
+ title="Previous Page">&laquo; Previous</a></span>
+{% else %}
+ <span class="prev-na">&laquo; Previous</span>
+{% endif %}
+
+{% if page.paginator.trailing_set %}
+ {% for p in page.paginator.trailing_set %}
+ <span class="page"><a href="{% listurl page=p %}" >{{ p }}</a></span>
+ {% endfor %}
+ ...
+{% endif %}
+
+{% for p in page.paginator.adjacent_set %}
+ {% ifequal p page.number %}
+ <span class="curr" title="Current Page">{{ p }}</span>
+ {% else %}
+ <span class="page"><a href="{% listurl page=p %}"
+ title="Page {{ p }}">{{ p }}</a></span>
+ {% endifequal %}
+{% endfor %}
+
+{% if page.paginator.leading_set %}
+ ...
+ {% for p in page.paginator.leading_set %}
+ <span class="page"><a href="{% listurl page=p %}">{{ p }}</a></span>
+ {% endfor %}
+{% endif %}
+
+{% if page.has_next %}
+ <span class="next">
+ <a href="{% listurl page=page.next_page_number %}"
+ title="Next Page">Next &raquo;</a>
+ </span>
+{% else %}
+ <span class="next-na">Next &raquo;</span>
+{% endif %}
+</div>
+{% endifnotequal %}
diff --git a/patchwork/templates/patchwork/patch-change-notification-subject.text b/patchwork/templates/patchwork/patch-change-notification-subject.text
new file mode 100644
index 0000000..c9d96d4
--- /dev/null
+++ b/patchwork/templates/patchwork/patch-change-notification-subject.text
@@ -0,0 +1 @@
+[{{ projects|join:"," }}] Patch notification: {{notifications|length}} patch{{notifications|length|pluralize:"es"}} updated
diff --git a/patchwork/templates/patchwork/patch-change-notification.mail b/patchwork/templates/patchwork/patch-change-notification.mail
new file mode 100644
index 0000000..4246704
--- /dev/null
+++ b/patchwork/templates/patchwork/patch-change-notification.mail
@@ -0,0 +1,20 @@
+Hello,
+
+The following patch{{notifications|length|pluralize:"es"}} (submitted by you) {{notifications|length|pluralize:"has,have"}} been updated in patchwork:
+{% for notification in notifications %}
+ * {{notification.patch.project.linkname}}: {{notification.patch.name|safe}}
+ - http://{{site.domain}}{{notification.patch.get_absolute_url}}
+ - for: {{notification.patch.project.name}}
+ was: {{notification.orig_state}}
+ now: {{notification.patch.state}}
+{% endfor %}
+This email is a notification only - you do not need to respond.
+
+Happy patchworking.
+
+--
+
+This is an automated mail sent by the patchwork system at
+{{site.domain}}. To stop receiving these notifications, edit
+your mail settings at:
+ http://{{site.domain}}{% url 'patchwork.views.mail.settings' %}
diff --git a/patchwork/templates/patchwork/patch-list.html b/patchwork/templates/patchwork/patch-list.html
new file mode 100644
index 0000000..675f67f
--- /dev/null
+++ b/patchwork/templates/patchwork/patch-list.html
@@ -0,0 +1,268 @@
+{% load person %}
+{% load listurl %}
+{% load static %}
+
+{% include "patchwork/pagination.html" %}
+
+
+<table class="patchlist">
+ <tr>
+ <td class="patchlistfilters">
+ {% include "patchwork/filters.html" %}
+ </td>
+ {% if order.editable %}
+ <td class="patchlistreorder">
+ <form method="post" id="reorderform">
+ {% csrf_token %}
+ <input type="hidden" name="form" value="reorderform"/>
+ <input type="hidden" name="order_start" value="0"/>
+ <span id="reorderhelp"></span>
+ <input id="reorder-cancel" type="button" value="Cancel"
+ onClick="order_cancel_click(this)"/>
+ <input id="reorder-change" type="button" value="Change order"
+ onClick="order_button_click(this)"/>
+ </form>
+ </td>
+ {% endif %}
+ </tr>
+</table>
+
+{% if page.paginator.long_page and user.is_authenticated %}
+<div class="floaty">
+ <a title="jump to form" href="#patchforms"><span
+ style="font-size: 120%">&#9662;</span></a>
+</div>
+{% endif %}
+
+<form method="post">
+{% csrf_token %}
+<input type="hidden" name="form" value="patchlistform"/>
+<input type="hidden" name="project" value="{{project.id}}"/>
+<table class="patchlist" id="patchlist">
+ <thead>
+ <tr>
+ {% if user.is_authenticated %}
+ <th>
+ <input type="checkbox" onChange="select_all(this)"/>
+ </th>
+ {% endif %}
+
+ <th>
+ {% ifequal order.name "name" %}
+ <a class="colactive"
+ href="{% listurl order=order.reversed_name %}"><img
+ {% if order.reversed %}
+ src="{% static "images/16-arrow-up.png" %}"
+ {% else %}
+ src="{% static "images/16-arrow-down.png" %}"
+ {%endif%}
+ width="16" height="16"
+ ></a> <a class="colactive"
+ href="{% listurl order=order.reversed_name %}">Patch</a>
+ {% else %}
+ {% if not order.editable %}
+ <a class="colinactive" href="{% listurl order="name" %}">Patch</a>
+ {% else %}
+ <span class="colinactive">Patch</span>
+ {% endif %}
+ {% endifequal %}
+ </th>
+
+ <th>
+ {% ifequal order.name "date" %}
+ <a class="colactive"
+ href="{% listurl order=order.reversed_name %}"><img
+ {% if order.reversed %}
+ src="{% static "images/16-arrow-up.png" %}"
+ {% else %}
+ src="{% static "images/16-arrow-down.png" %}"
+ {%endif%}
+ width="16" height="16"
+ ></a> <a class="colactive"
+ href="{% listurl order=order.reversed_name %}">Date</a>
+ {% else %}
+ {% if not order.editable %}
+ <a class="colinactive" href="{% listurl order="date" %}">Date</a>
+ {% else %}
+ <span class="colinactive">Date</span>
+ {% endif %}
+ {% endifequal %}
+ </th>
+
+ <th>
+ {% ifequal order.name "submitter" %}
+ <a class="colactive"
+ href="{% listurl order=order.reversed_name %}"><img
+ {% if order.reversed %}
+ src="{% static "images/16-arrow-up.png" %}"
+ {% else %}
+ src="{% static "images/16-arrow-down.png" %}"
+ {%endif%}
+ width="16" height="16"
+ ></a> <a class="colactive"
+ href="{% listurl order=order.reversed_name %}">Submitter</a>
+ {% else %}
+ {% if not order.editable %}
+ <a class="colinactive" href="{% listurl order="submitter" %}">Submitter</a>
+ {% else %}
+ <span class="colinactive">Submitter</span>
+ {% endif %}
+ {% endifequal %}
+ </th>
+
+ <th>
+ {% ifequal order.name "delegate" %}
+ <a class="colactive"
+ href="{% listurl order=order.reversed_name %}"><img
+ {% if order.reversed %}
+ src="{% static "images/16-arrow-up.png" %}"
+ {% else %}
+ src="{% static "images/16-arrow-down.png" %}"
+ {%endif%}
+ width="16" height="16"
+ ></a> <a class="colactive"
+ href="{% listurl order=order.reversed_name %}">Delegate</a>
+ {% else %}
+ {% if not order.editable %}
+ <a class="colinactive" href="{% listurl order="delegate" %}">Delegate</a>
+ {% else %}
+ <span class="colinactive">Delegate</span>
+ {% endif %}
+ {% endifequal %}
+ </th>
+
+ <th>
+ {% ifequal order.name "state" %}
+ <a class="colactive"
+ href="{% listurl order=order.reversed_name %}"><img
+ {% if order.reversed %}
+ src="{% static "images/16-arrow-up.png" %}"
+ {% else %}
+ src="{% static "images/16-arrow-down.png" %}"
+ {%endif%}
+ width="16" height="16"
+ ></a> <a class="colactive"
+ href="{% listurl order=order.reversed_name %}">State</a>
+ {% else %}
+ {% if not order.editable %}
+ <a class="colinactive" href="{% listurl order="state" %}">State</a>
+ {% else %}
+ <span class="colinactive">State</span>
+ {% endif %}
+ {% endifequal %}
+ </th>
+
+ </tr>
+ </thead>
+
+{% if page.paginator.count %}
+ <tbody>
+ {% for patch in page.object_list %}
+ <tr id="patch_row:{{patch.id}}" class="{% cycle 'odd' 'even' %}">
+ {% if user.is_authenticated %}
+ <td>
+ <input type="checkbox" name="patch_id:{{patch.id}}"/>
+ </td>
+ {% endif %}
+ <td><a href="{% url 'patchwork.views.patch.patch' patch_id=patch.id %}"
+ >{{ patch.name|default:"[no subject]" }}</a></td>
+ <td>{{ patch.date|date:"Y-m-d" }}</td>
+ <td>{{ patch.submitter|personify:project }}</td>
+ <td>{{ patch.delegate.username }}</td>
+ <td>{{ patch.state }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+
+{% include "patchwork/pagination.html" %}
+
+<div class="patchforms" id="patchforms" name="patchforms">
+
+{% if patchform %}
+ <div class="patchform patchform-properties">
+ <h3>Properties</h3>
+ <table class="form">
+ <tr>
+ <th>Change state:</th>
+ <td>
+ {{ patchform.state }}
+ {{ patchform.state.errors }}
+ </td>
+ </tr>
+ <tr>
+ <th>Delegate to:</td>
+ <td>
+ {{ patchform.delegate }}
+ {{ patchform.delegate.errors }}
+ </td>
+ </tr>
+ <tr>
+ <th>Archive:</td>
+ <td>
+ {{ patchform.archived }}
+ {{ patchform.archived.errors }}
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>
+ <input type="submit" name="action" value="{{patchform.action}}"/>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+{% endif %}
+
+{% if user.is_authenticated %}
+ <div class="patchform patchform-bundle">
+ <h3>Bundling</h3>
+ <table class="form">
+ <tr>
+ <td>Create bundle:</td>
+ <td>
+ <input type="text" name="bundle_name"/>
+ <input name="action" value="Create" type="submit"/>
+ </td>
+ </tr>
+ {% if bundles %}
+ <tr>
+ <td>Add to bundle:</td>
+ <td>
+ <select name="bundle_id"/>
+ {% for bundle in bundles %}
+ <option value="{{bundle.id}}">{{bundle.name}}</option>
+ {% endfor %}
+ </select>
+ <input name="action" value="Add" type="submit"/>
+ </td>
+ </tr>
+ {% endif %}
+ {% if bundle %}
+ <tr>
+ <td>Remove from bundle:</td>
+ <td>
+ <input type="hidden" name="removed_bundle_id" value="{{bundle.id}}"/>
+ <input name="action" value="Remove" type="submit"/>
+ </td>
+ </tr>
+ {% endif %}
+ </table>
+ </div>
+{% endif %}
+
+
+ <div style="clear: both;">
+ </div>
+</div>
+
+{% else %}
+ <tr>
+ <td colspan="5">No patches to display</td>
+ </tr>
+{% endif %}
+
+ </table>
+</form>
+
diff --git a/patchwork/templates/patchwork/patch.html b/patchwork/templates/patchwork/patch.html
new file mode 100644
index 0000000..f18ee3b
--- /dev/null
+++ b/patchwork/templates/patchwork/patch.html
@@ -0,0 +1,199 @@
+{% extends "base.html" %}
+
+{% load syntax %}
+{% load person %}
+{% load patch %}
+
+{% block title %}{{patch.name}}{% endblock %}
+{% block heading %}{{patch.name}}{%endblock%}
+
+{% block body %}
+<script language="JavaScript" type="text/javascript">
+function toggle_headers(link_id, headers_id)
+{
+ var link = document.getElementById(link_id)
+ var headers = document.getElementById(headers_id)
+
+ var hidden = headers.style['display'] == 'none';
+
+ if (hidden) {
+ link.innerHTML = 'hide';
+ headers.style['display'] = 'block';
+ } else {
+ link.innerHTML = 'show';
+ headers.style['display'] = 'none';
+ }
+
+}
+</script>
+
+<table class="patchmeta">
+ <tr>
+ <th>Submitter</th>
+ <td>{{ patch.submitter|personify:project }}</td>
+ </tr>
+ <tr>
+ <th>Date</th>
+ <td>{{ patch.date }}</td>
+ </tr>
+ <tr>
+ <th>Message ID</th>
+ <td>{{ patch.msgid }}</td>
+ </tr>
+ <tr>
+ <th>Download</th>
+ <td>
+ <a href="{% url 'patchwork.views.patch.mbox' patch_id=patch.id %}"
+ >mbox</a>
+{% if patch.content %}|
+ <a href="{% url 'patchwork.views.patch.content' patch_id=patch.id %}"
+ >patch</a>
+{% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>Permalink</th>
+ <td><a href="{{ patch.get_absolute_url }}">{{ patch.get_absolute_url }}</a>
+ </tr>
+ <tr>
+ <th>State</th>
+ <td>{{ patch.state.name }}{% if patch.archived %}, archived{% endif %}</td>
+ </tr>
+{% if patch.commit_ref %}
+ <tr>
+ <th>Commit</th>
+ <td>{{ patch.commit_ref }}</td>
+ </tr>
+{% endif %}
+{% if patch.delegate %}
+ <tr>
+ <th>Delegated to:</th>
+ <td>{{ patch.delegate.profile.name }}</td>
+ </tr>
+{% endif %}
+ <tr>
+ <th>Headers</th>
+ <td><a id="togglepatchheaders"
+ href="javascript:toggle_headers('togglepatchheaders', 'patchheaders')"
+ >show</a>
+ <div id="patchheaders" class="patchheaders" style="display:none;">
+ <pre>{{patch.headers}}</pre>
+ </div>
+ </td>
+ </tr>
+</table>
+
+<div class="patchforms">
+
+{% if patchform %}
+ <div class="patchform patchform-properties">
+ <h3>Patch Properties</h3>
+ <form method="post">
+ {% csrf_token %}
+ <table class="form">
+ <tr>
+ <th>Change state:</th>
+ <td>
+ {{ patchform.state }}
+ {{ patchform.state.errors }}
+ </td>
+ </tr>
+ <tr>
+ <th>Delegate to:</th>
+ <td>
+ {{ patchform.delegate }}
+ {{ patchform.delegate.errors }}
+ </td>
+ </tr>
+ <tr>
+ <th>Archived:</th>
+ <td>
+ {{ patchform.archived }}
+ {{ patchform.archived.errors }}
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>
+ <input type="submit" value="Update">
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+{% endif %}
+
+{% if createbundleform %}
+ <div class="patchform patchform-bundle">
+ <h3>Bundling</h3>
+ <table class="form">
+ <tr>
+ <td>Create bundle:</td>
+ <td>
+ {% if createbundleform.non_field_errors %}
+ <dd class="errors">{{createbundleform.non_field_errors}}</dd>
+ {% endif %}
+ <form method="post">
+ {% csrf_token %}
+ <input type="hidden" name="action" value="createbundle"/>
+ {% if createbundleform.name.errors %}
+ <dd class="errors">{{createbundleform.name.errors}}</dd>
+ {% endif %}
+ {{ createbundleform.name }}
+ <input value="Create" type="submit"/>
+ </form>
+ </td>
+ </tr>
+{% if bundles %}
+ <tr>
+ <td>Add to bundle:</td>
+ <td>
+ <form method="post">
+ {% csrf_token %}
+ <input type="hidden" name="action" value="addtobundle"/>
+ <select name="bundle_id"/>
+ {% for bundle in bundles %}
+ <option value="{{bundle.id}}">{{bundle.name}}</option>
+ {% endfor %}
+ </select>
+ <input value="Add" type="submit"/>
+ </form>
+ </td>
+ </tr>
+{% endif %}
+ </table>
+
+ </div>
+{% endif %}
+
+ <div style="clear: both;">
+ </div>
+</div>
+
+{% if patch.pull_url %}
+<h2>Pull-request</h2>
+<a class="patch-pull-url" href="{{patch.pull_url}}"
+ >{{ patch.pull_url }}</a>
+{% endif %}
+
+<h2>Comments</h2>
+{% for comment in patch.comments %}
+<div class="comment">
+<div class="meta">{{ comment.submitter|personify:project }} - {{comment.date}}</div>
+<pre class="content">
+{{ comment|commentsyntax }}
+</pre>
+</div>
+{% endfor %}
+
+{% if patch.content %}
+<h2>Patch</h2>
+<div class="patch">
+<pre class="content">
+{{ patch|patchsyntax }}
+</pre>
+</div>
+{% endif %}
+
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/profile.html b/patchwork/templates/patchwork/profile.html
new file mode 100644
index 0000000..116d6d6
--- /dev/null
+++ b/patchwork/templates/patchwork/profile.html
@@ -0,0 +1,144 @@
+{% extends "base.html" %}
+
+{% block title %}User Profile: {{ user.username }}{% endblock %}
+{% block heading %}User Profile: {{ user.username }}{% endblock %}
+
+
+{% block body %}
+
+<p>
+{% if user.profile.maintainer_projects.count %}
+Maintainer of
+{% for project in user.profile.maintainer_projects.all %}
+<a href="{% url 'patchwork.views.patch.list' project_id=project.linkname %}"
+>{{ project.linkname }}</a>{% if not forloop.last %},{% endif %}{% endfor %}.
+{% endif %}
+
+{% if user.profile.contributor_projects.count %}
+Contributor to
+{% for project in user.profile.contributor_projects.all %}
+<a href="{% url 'patchwork.views.patch.list' project_id=project.linkname %}"
+>{{ project.linkname }}</a>{% if not forloop.last %},{% endif %}{% endfor %}.
+{% endif %}
+</p>
+
+<div class="leftcol">
+<div class="box">
+ <h2>Todo</h2>
+{% if user.profile.n_todo_patches %}
+ <p>Your <a href="{% url 'patchwork.views.user.todo_lists' %}">todo
+ list</a> contains {{ user.profile.n_todo_patches }}
+ patch{{ user.profile.n_todo_patches|pluralize:"es" }}.</p>
+{% else %}
+ <p>Your todo list contains patches that have been delegated to you. You
+ have no items in your todo list at present.</p>
+{% endif %}
+</div>
+
+<div class="box">
+<h2>Linked email addresses</h2>
+<p>The following email addresses are associated with this patchwork account.
+Adding alternative addresses allows patchwork to group contributions that
+you have made under different addresses.</p>
+<p>The "notify?" column allows you to opt-in or -out of automated
+patchwork notification emails. Setting it to "no" will disable automated
+notifications for that address.</p>
+<p>Adding a new email address will send a confirmation email to that
+address.</p>
+<table class="vertical">
+ <tr>
+ <th>email</th>
+ <th>action</th>
+ <th>notify?</th>
+ </tr>
+{% for email in linked_emails %}
+ <tr>
+ <td>{{ email.email }}</td>
+ <td>
+ {% ifnotequal user.email email.email %}
+ <form action="{% url 'patchwork.views.user.unlink' person_id=email.id %}"
+ method="post">
+ {% csrf_token %}
+ <input type="submit" value="Unlink"/>
+ </form>
+ {% endifnotequal %}
+ </td>
+ <td>
+ {% if email.is_optout %}
+ <form method="post" action="{% url 'patchwork.views.mail.optin' %}">
+ No,
+ {% csrf_token %}
+ <input type="hidden" name="email" value="{{email.email}}"/>
+ <input type="submit" value="Opt-in"/>
+ </form>
+ {% else %}
+ <form method="post" action="{% url 'patchwork.views.mail.optout' %}">
+ Yes,
+ {% csrf_token %}
+ <input type="hidden" name="email" value="{{email.email}}"/>
+ <input type="submit" value="Opt-out"/>
+ </form>
+ {% endif %}
+ </td>
+ </tr>
+{% endfor %}
+ <tr>
+ <td colspan="3">
+ <form action="{% url 'patchwork.views.user.link' %}" method="post">
+ {% csrf_token %}
+ {{ linkform.email }}
+ <input type="submit" value="Add"/>
+ </form>
+ </td>
+ </tr>
+</table>
+</div>
+</div>
+
+<div class="rightcol">
+
+<div class="box">
+<h2>Bundles</h2>
+
+{% if bundles %}
+<p>You have the following bundle{{ bundle|length|pluralize }}:</p>
+<ul>
+{% for bundle in bundles %}
+ <li><a href="{{ bundle.get_absolute_url }}">{{ bundle.name }}</a></li>
+{% endfor %}
+</ul>
+<p>Visit the <a href="{%url 'patchwork.views.bundle.bundles' %}">bundles
+ page</a> to manage your bundles.</p>
+{% else %}
+<p>You have no bundles.</p>
+{% endif %}
+</div>
+
+
+<div class="box">
+<h2>Settings</h2>
+
+<form method="post">
+ {% csrf_token %}
+ <table class="form">
+{{ profileform }}
+ <tr>
+ <td/>
+ <td>
+ <input type="submit" value="Apply"/>
+ </td>
+ </tr>
+ </table>
+</form>
+</div>
+
+<div class="box">
+<h2>Authentication</h2>
+<a href="{% url 'django.contrib.auth.views.password_change' %}">Change password</a>
+</div>
+
+</div>
+
+<p style="clear: both"></p>
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/project.html b/patchwork/templates/patchwork/project.html
new file mode 100644
index 0000000..be8cadc
--- /dev/null
+++ b/patchwork/templates/patchwork/project.html
@@ -0,0 +1,58 @@
+{% extends "base.html" %}
+
+{% block title %}{{ project.name }}{% endblock %}
+{% block heading %}{{ project.name }}{% endblock %}
+
+{% block body %}
+
+<table class="horizontal">
+ <tr>
+ <th>Name</th>
+ <td>{{project.name}}
+ </tr>
+ <tr>
+ <th>List address</th>
+ <td>{{project.listemail}}</td>
+ </tr>
+ <tr>
+ <th>Maintainer{{maintainers|length|pluralize}}</th>
+ <td>
+ {% for maintainer in maintainers %}
+ {{ maintainer.profile.name }}
+ &lt;<a href="mailto:{{maintainer.email}}">{{maintainer.email}}</a>&gt;
+ <br />
+ {% endfor %}
+ </td>
+ </tr>
+ <tr>
+ <th>Patch count</th>
+ <td>{{n_patches}} (+ {{n_archived_patches}} archived)</td>
+ </tr>
+{% if project.web_url %}
+ <tr>
+ <th>Website</th>
+ <td><a href="{{project.web_url}}">{{project.web_url}}</a></td>
+ </tr>
+{% endif %}
+{% if project.webscm_url %}
+ <tr>
+ <th>Source Code Web Interface</th>
+ <td><a href="{{project.webscm_url}}">{{project.webscm_url}}</a></td>
+ </tr>
+{% endif %}
+{% if project.scm_url %}
+ <tr>
+ <th>Source Code Manager URL</th>
+ <td><a href="{{project.scm_url}}">{{project.scm_url}}</a></td>
+ </tr>
+{% endif %}
+</table>
+
+{% if settings.ENABLE_XMLRPC %}
+<p>Sample <a href="{% url 'patchwork.views.help' "pwclient/" %}">patchwork
+client</a> configuration for this project: <a
+href="{% url 'patchwork.views.pwclientrc' project.linkname %}"
+>.pwclientrc</a>.</p>
+{% endif %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/projects.html b/patchwork/templates/patchwork/projects.html
new file mode 100644
index 0000000..8c727ad
--- /dev/null
+++ b/patchwork/templates/patchwork/projects.html
@@ -0,0 +1,27 @@
+{% extends "base.html" %}
+
+{% block title %}Project List{% endblock %}
+{% block heading %}Project List{% endblock %}
+
+{% block body %}
+
+{% if projects %}
+ <div class="project-set">
+ {% for p in projects %}
+ <div class="project">
+ <h2 class="project-title">
+ <a href="{% url 'patchwork.views.patch.list' project_id=p.linkname %}"
+ >{{p.linkname}}</a>
+ </h2>
+ <div class="project-name">{{p.name}}</div>
+{% if p.web_url %}
+ <div class="project-url"><a href="{{p.web_url}}">website</a></div>
+{% endif %}
+ </div>
+ {% endfor %}
+ </div>
+{% else %}
+ <p>Patchwork doesn't have any projects to display!</p>
+{% endif %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/pwclient b/patchwork/templates/patchwork/pwclient
new file mode 120000
index 0000000..5ce255f
--- /dev/null
+++ b/patchwork/templates/patchwork/pwclient
@@ -0,0 +1 @@
+../../bin/pwclient \ No newline at end of file
diff --git a/patchwork/templates/patchwork/pwclientrc b/patchwork/templates/patchwork/pwclientrc
new file mode 100644
index 0000000..d331003
--- /dev/null
+++ b/patchwork/templates/patchwork/pwclientrc
@@ -0,0 +1,15 @@
+# Sample .pwclientrc file for the {{ project.linkname }} project,
+# running on {{ site.domain }}.
+#
+# Just append this file to your existing ~/.pwclientrc
+# If you do not already have a ~/.pwclientrc, then copy this file to
+# ~/.pwclientrc, and uncomment the following two lines:
+# [options]
+# default={{ project.linkname }}
+
+[{{ project.linkname }}]
+url= {{scheme}}://{{site.domain}}{% url 'patchwork.views.xmlrpc.xmlrpc' %}
+{% if user.is_authenticated %}
+username: {{ user.username }}
+password: <add your patchwork password here>
+{% endif %}
diff --git a/patchwork/templates/patchwork/register.mail b/patchwork/templates/patchwork/register.mail
new file mode 100644
index 0000000..9079203
--- /dev/null
+++ b/patchwork/templates/patchwork/register.mail
@@ -0,0 +1,11 @@
+Hi,
+
+This email is to confirm your account on the patchwork patch-tracking
+system. You can activate your account by visiting the url:
+
+ http://{{site.domain}}{% url 'registration_activateactivation_key'=request.key %}
+
+If you didn't request a user account on patchwork, then you can ignore
+this mail.
+
+Happy patchworking.
diff --git a/patchwork/templates/patchwork/registration-confirm.html b/patchwork/templates/patchwork/registration-confirm.html
new file mode 100644
index 0000000..6111401
--- /dev/null
+++ b/patchwork/templates/patchwork/registration-confirm.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block title %}Registration{% endblock %}
+{% block heading %}Registration{% endblock %}
+
+{% block body %}
+<p>Registraton confirmed!</p>
+
+<p>Your patchwork registration is complete. Head over to your <a
+ href="{% url 'patchwork.views.user.profile' %}">profile</a> to start using
+patchwork's extra features.</p>
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/registration_form.html b/patchwork/templates/patchwork/registration_form.html
new file mode 100644
index 0000000..3a314b8
--- /dev/null
+++ b/patchwork/templates/patchwork/registration_form.html
@@ -0,0 +1,121 @@
+{% extends "base.html" %}
+
+{% block title %}Registration{% endblock %}
+{% block heading %}Registration{% endblock %}
+
+
+{% block body %}
+
+{% if confirmation and not error %}
+ <p>Registration successful!</p>
+ <p>A confirmation email has been sent to {{ confirmation.email }}. You'll
+ need to visit the link provided in that email to confirm your
+ registration.</p>
+</p>
+{% else %}
+<p>By creating a patchwork account, you can:<p>
+<ul>
+ <li>create "bundles" of patches</li>
+ <li>update the state of your own patches</li>
+</ul>
+<form method="post">
+{% csrf_token %}
+<table class="form registerform">
+ <tr>
+ <th colspan="2" class="headerrow">register</th>
+ </tr>
+ {% if error %}
+ <tr>
+ <td colspan="2">{{ error }}</td>
+ </tr>
+ {% endif %}
+
+ <tr>
+ <td>{{ form.first_name.label_tag }}</td>
+ <td>
+{% if form.first_name.errors %}
+ {{ form.first_name.errors }}
+{% endif %}
+ {{ form.first_name }}
+{% if form.first_name.help_text %}
+ <div class="help_text"/>{{ form.first_name.help_text }}</div>
+{% endif %}
+ </td>
+ </tr>
+
+ <tr>
+ <td>{{ form.last_name.label_tag }}</td>
+ <td>
+{% if form.last_name.errors %}
+ {{ form.last_name.errors }}
+{% endif %}
+ {{ form.last_name }}
+{% if form.last_name.help_text %}
+ <div class="help_text"/>{{ form.last_name.help_text }}</div>
+{% endif %}
+ </td>
+ </tr>
+
+ <tr>
+ <td></td>
+ <td class="form-help">
+ Your name is used to identify you on the site
+ </td>
+ </tr>
+
+ <tr>
+ <td>{{ form.email.label_tag }}</td>
+ <td>
+{% if form.email.errors %}
+ {{ form.email.errors }}
+{% endif %}
+ {{ form.email }}
+{% if form.email.help_text %}
+ <div class="help_text"/>{{ form.email.help_text }}</div>
+{% endif %}
+ </td>
+ </tr>
+
+ <tr>
+ <td></td>
+ <td class="form-help">
+ Patchwork will send a confirmation email to this address
+ </td>
+ </tr>
+
+ <tr>
+ <td>{{ form.username.label_tag }}</td>
+ <td>
+{% if form.username.errors %}
+ {{ form.username.errors }}
+{% endif %}
+ {{ form.username }}
+{% if form.username.help_text %}
+ <div class="help_text"/>{{ form.username.help_text }}</div>
+{% endif %}
+ </td>
+ </tr>
+
+ <tr>
+ <td>{{ form.password.label_tag }}</td>
+ <td>
+{% if form.password.errors %}
+ {{ form.password.errors }}
+{% endif %}
+ {{ form.password }}
+{% if form.password.help_text %}
+ <div class="help_text"/>{{ form.password.help_text }}</div>
+{% endif %}
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2" class="submitrow">
+ <input type="submit" value="Register"/>
+ </td>
+ </tr>
+</table>
+</form>
+{% endif %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/todo-list.html b/patchwork/templates/patchwork/todo-list.html
new file mode 100644
index 0000000..b301901
--- /dev/null
+++ b/patchwork/templates/patchwork/todo-list.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+
+{% load person %}
+
+{% block title %}{{ user }}'s todo list{% endblock %}
+{% block heading %}{{user}}'s todo list for {{ project.linkname }}{% endblock %}
+
+{% block body %}
+
+<p>A Patchwork Todo-list contains patches that are assigned to you, and
+are in an "action required" state
+({% for state in action_required_states %}{% if forloop.last and not forloop.first %} or {% endif %}{{ state }}{% if not forloop.last and not forloop.first %}, {%endif %}{% endfor %}), and are not archived.
+</p>
+
+{% include "patchwork/patch-list.html" %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/todo-lists.html b/patchwork/templates/patchwork/todo-lists.html
new file mode 100644
index 0000000..e268160
--- /dev/null
+++ b/patchwork/templates/patchwork/todo-lists.html
@@ -0,0 +1,29 @@
+{% extends "base.html" %}
+
+{% block title %}{{ user }}'s todo lists{% endblock %}
+{% block heading %}{{ user }}'s todo lists{% endblock %}
+
+{% block body %}
+
+{% if todo_lists %}
+<p>You have multiple todo lists. Each todo list contains patches for a single
+ project.</p>
+<table class="vertical">
+ <tr>
+ <th>project</th>
+ <th>patches</th>
+ </tr>
+{% for todo_list in todo_lists %}
+ <tr>
+ <td><a
+ href="{% url 'patchwork.views.user.todo_list' project_id=todo_list.project.linkname %}"
+ >{{ todo_list.project.name }}</a></td>
+ <td class="numberformat">{{ todo_list.n_patches }}</td>
+ </tr>
+{% endfor %}
+</table>
+
+{% else %}
+ No todo lists
+{% endif %}
+{% endblock %}
diff --git a/patchwork/templates/patchwork/user-link-confirm.html b/patchwork/templates/patchwork/user-link-confirm.html
new file mode 100644
index 0000000..449bfeb
--- /dev/null
+++ b/patchwork/templates/patchwork/user-link-confirm.html
@@ -0,0 +1,19 @@
+{% extends "base.html" %}
+
+{% block title %}{{ user.username }}{% endblock %}
+{% block heading %}link accounts for {{ user.username }}{% endblock %}
+
+
+{% block body %}
+
+{% if errors %}
+<p>{{ errors }}</p>
+{% else %}
+ <p>You have sucessfully linked the email address {{ person.email }} to
+ your patchwork account</p>
+
+{% endif %}
+<p>Back to <a href="{% url 'patchwork.views.user.profile' %}">your
+ profile</a>.</p>
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/user-link.html b/patchwork/templates/patchwork/user-link.html
new file mode 100644
index 0000000..e436c3a
--- /dev/null
+++ b/patchwork/templates/patchwork/user-link.html
@@ -0,0 +1,32 @@
+{% extends "base.html" %}
+
+{% block title %}{{ user.username }}{% endblock %}
+{% block heading %}link accounts for {{ user.username }}{% endblock %}
+
+
+{% block body %}
+
+{% if confirmation and not error %}
+<p>A confirmation email has been sent to {{ confirmation.email }}. Click
+on the link provided in the email to confirm that this address belongs to
+you.</p>
+
+{% else %}
+
+ {% if form.errors %}
+ <p>There was an error submitting your link request.</p>
+ {{ form.non_field_errors }}
+ {% endif %}
+ {% if error %}
+ <ul class="errorlist"><li>{{error}}</li></ul>
+ {% endif %}
+
+ <form action="{% url 'patchwork.views.user.link' %}" method="post">
+ {% csrf_token %}
+ {{linkform.email.errors}}
+ Link an email address: {{ linkform.email }}
+ </form>
+
+{% endif %}
+
+{% endblock %}
diff --git a/patchwork/templates/patchwork/user-link.mail b/patchwork/templates/patchwork/user-link.mail
new file mode 100644
index 0000000..8db6726
--- /dev/null
+++ b/patchwork/templates/patchwork/user-link.mail
@@ -0,0 +1,12 @@
+Hi,
+
+This email is to confirm that you own the email address:
+
+ {{ confirmation.email }}
+
+So that you can add it to your patchwork profile. You can confirm this
+email address by visiting the url:
+
+ http://{{site.domain}}{% url 'patchwork.views.confirm' key=confirmation.key %}
+
+Happy patchworking.