get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/1516044/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 1516044,
    "url": "http://patchwork.ozlabs.org/api/patches/1516044/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/patchwork/patch/20210811213705.36293-11-stephen@that.guru/",
    "project": {
        "id": 16,
        "url": "http://patchwork.ozlabs.org/api/projects/16/?format=api",
        "name": "Patchwork",
        "link_name": "patchwork",
        "list_id": "patchwork.lists.ozlabs.org",
        "list_email": "patchwork@lists.ozlabs.org",
        "web_url": "http://jk.ozlabs.org/projects/patchwork/",
        "scm_url": "git://github.com/getpatchwork/patchwork",
        "webscm_url": "https://github.com/getpatchwork/patchwork",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20210811213705.36293-11-stephen@that.guru>",
    "list_archive_url": null,
    "date": "2021-08-11T21:36:56",
    "name": "[RFC,10/19] templates: Convert user profile view",
    "commit_ref": null,
    "pull_url": null,
    "state": "rfc",
    "archived": false,
    "hash": "ab3525cf0980f94fee6544db9a6517c876fd57e9",
    "submitter": {
        "id": 69991,
        "url": "http://patchwork.ozlabs.org/api/people/69991/?format=api",
        "name": "Stephen Finucane",
        "email": "stephen@that.guru"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/patchwork/patch/20210811213705.36293-11-stephen@that.guru/mbox/",
    "series": [
        {
            "id": 257699,
            "url": "http://patchwork.ozlabs.org/api/series/257699/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/patchwork/list/?series=257699",
            "date": "2021-08-11T21:36:49",
            "name": "Integrate Bulma",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/257699/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1516044/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1516044/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "patchwork@lists.ozlabs.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "patchwork@lists.ozlabs.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org\n (client-ip=112.213.38.117; helo=lists.ozlabs.org;\n envelope-from=patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org;\n receiver=<UNKNOWN>)",
            "ozlabs.org;\n\tdkim=fail reason=\"key not found in DNS\" header.d=that.guru\n header.i=@that.guru header.a=rsa-sha256 header.s=x header.b=Rzv/XhAS;\n\tdkim-atps=neutral",
            "lists.ozlabs.org;\n\tdkim=fail reason=\"key not found in DNS\" header.d=that.guru\n header.i=@that.guru header.a=rsa-sha256 header.s=x header.b=Rzv/XhAS;\n\tdkim-atps=neutral",
            "lists.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=that.guru\n (client-ip=136.175.108.123; helo=mail-108-mta123.mxroute.com;\n envelope-from=stephen@that.guru; receiver=<UNKNOWN>)",
            "lists.ozlabs.org;\n dkim=fail reason=\"key not found in DNS\" header.d=that.guru\n header.i=@that.guru\n header.a=rsa-sha256 header.s=x header.b=Rzv/XhAS;\n dkim-atps=neutral"
        ],
        "Received": [
            "from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 4GlPBl6wYKz9sSs\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 12 Aug 2021 08:10:07 +1000 (AEST)",
            "from boromir.ozlabs.org (localhost [IPv6:::1])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 4GlPBl5M3Kz3bjK\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 12 Aug 2021 08:10:07 +1000 (AEST)",
            "from mail-108-mta123.mxroute.com (mail-108-mta123.mxroute.com\n [136.175.108.123])\n (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n (No client certificate requested)\n by lists.ozlabs.org (Postfix) with ESMTPS id 4GlPBb1pR0z3002\n for <patchwork@lists.ozlabs.org>; Thu, 12 Aug 2021 08:09:58 +1000 (AEST)",
            "from filter004.mxroute.com ([149.28.56.236] filter004.mxroute.com)\n (Authenticated sender: mN4UYu2MZsgR)\n by mail-108-mta123.mxroute.com (ZoneMTA) with ESMTPSA id\n 17b3743be1700074ba.002 for <patchwork@lists.ozlabs.org>\n (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256);\n Wed, 11 Aug 2021 22:09:51 +0000"
        ],
        "X-Zone-Loop": "06b58b888e965e9c4432153efbeefda52fef509ef17c",
        "X-Originating-IP": "[149.28.56.236]",
        "DKIM-Signature": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=that.guru;\n s=x;\n h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:\n In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID:\n Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc\n :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe:\n List-Post:List-Owner:List-Archive;\n bh=SMQG0ZM01sQ88dRj8uQ3mjoSnhrdt6med75lif5QzPM=; b=Rzv/XhASQzkvf9Rs1+nuzhYyn9\n H60CwrnaG3Dm9SdHkax1FcEETP0FrD2+rldfrELRwJ+wkpE+xQdMfOxVsp6QuKpIwX1HJRwFndwJ7\n bTvuy7xN3qDeS66LRHaFYiqoHodY+xyUOlxxx6ZuNFcwzUzdS0VjTZRys1LQnYuoJfP2lg73FKoxq\n YxJXfR58kCtLL9KeM5YuxFq4lc6+7I9LiVrkbPxq/Lxmz9qzEy7pHlH5IXoiBxUBhfvogebd1msSc\n 6g1D2rBSZ81W9UTn8SG3XDDJpHsw/cMQ/Dxmlae7TuvqAdBTZ8KroqKIMAlNOwifSYWhLyxITAw/L\n tlpPBQWg==;",
        "From": "Stephen Finucane <stephen@that.guru>",
        "To": "patchwork@lists.ozlabs.org",
        "Subject": "[RFC PATCH 10/19] templates: Convert user profile view",
        "Date": "Wed, 11 Aug 2021 22:36:56 +0100",
        "Message-Id": "<20210811213705.36293-11-stephen@that.guru>",
        "X-Mailer": "git-send-email 2.31.1",
        "In-Reply-To": "<20210811213705.36293-1-stephen@that.guru>",
        "References": "<20210811213705.36293-1-stephen@that.guru>",
        "MIME-Version": "1.0",
        "X-AuthUser": "stephen@that.guru",
        "X-Zone-Spam-Resolution": "no action",
        "X-Zone-Spam-Status": "No, score=0.9, required=15, tests=[ARC_NA=0,\n MID_CONTAINS_FROM=1, FROM_HAS_DN=0, RCPT_COUNT_THREE=0, TO_DN_SOME=0,\n MIME_GOOD=-0.1, FROM_EQ_ENVFROM=0, MIME_TRACE=0, RCVD_COUNT_ZERO=0,\n NEURAL_SPAM=0]",
        "X-BeenThere": "patchwork@lists.ozlabs.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "Patchwork development <patchwork.lists.ozlabs.org>",
        "List-Unsubscribe": "<https://lists.ozlabs.org/options/patchwork>,\n <mailto:patchwork-request@lists.ozlabs.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.ozlabs.org/pipermail/patchwork/>",
        "List-Post": "<mailto:patchwork@lists.ozlabs.org>",
        "List-Help": "<mailto:patchwork-request@lists.ozlabs.org?subject=help>",
        "List-Subscribe": "<https://lists.ozlabs.org/listinfo/patchwork>,\n <mailto:patchwork-request@lists.ozlabs.org?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "base64",
        "Errors-To": "patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org",
        "Sender": "\"Patchwork\"\n <patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>"
    },
    "content": "This is our first \"full page\", in that we have a navbar. A large number\nof TODOs are left here as we're simply changing templates rather than\nupdating views, but those gaps will be closed in a future change.\n\nSigned-off-by: Stephen Finucane <stephen@that.guru>\n---\n patchwork/templates/patchwork/login.html      |   5 +-\n patchwork/templates/patchwork/profile.html    | 432 ++++++++++++------\n templates/base2.html                          |  82 ++++\n .../registration/password_reset_confirm.html  |   4 +\n .../registration/password_reset_done.html     |   4 +\n .../registration/password_reset_form.html     |   4 +\n 6 files changed, 395 insertions(+), 136 deletions(-)",
    "diff": "diff --git patchwork/templates/patchwork/login.html patchwork/templates/patchwork/login.html\nindex ef609f1f..b8ab462c 100644\n--- patchwork/templates/patchwork/login.html\n+++ patchwork/templates/patchwork/login.html\n@@ -2,8 +2,7 @@\n \n {% block title %}Sign in to Patchwork{% endblock %}\n \n-{% block headers %}\n-{% endblock %}\n+{% block navigation %}{% endblock %}\n \n {% block body %}\n <section class=\"hero is-primary is-fullheight\">\n@@ -75,3 +74,5 @@ for (var i = 0; i < btns.length; i++) {\n }\n </script>\n {% endblock %}\n+\n+{% block footer %}{% endblock %}\ndiff --git patchwork/templates/patchwork/profile.html patchwork/templates/patchwork/profile.html\nindex 552dde47..7a0b54fe 100644\n--- patchwork/templates/patchwork/profile.html\n+++ patchwork/templates/patchwork/profile.html\n@@ -1,173 +1,337 @@\n-{% extends \"base.html\" %}\n+{% extends \"base2.html\" %}\n \n {% block title %}{{ user.username }}{% endblock %}\n-{% block heading %}Your Profile{% endblock %}\n \n {% block body %}\n-<h1>Your Profile</h1>\n+<div class=\"container\" style=\"margin-top: 1rem;\">\n+  <div class=\"columns\">\n+    <div class=\"column is-3\">\n+      <aside class=\"menu\">\n+        <p class=\"menu-label\">\n+          Overview\n+        </p>\n+        <ul class=\"menu-list\">\n+          <li><a href=\"#projects\">Projects</a></li>\n+          <li><a href=\"#bundles\">Bundles</a></li>\n+          <li><a href=\"#todo\">Todo List</a></li>\n+        </ul>\n+        <p class=\"menu-label\">\n+          Settings\n+        </p>\n+        <ul class=\"menu-list\">\n+          <li><a href=\"#profile\">Profile</a></li>\n+          <li><a href=\"#linked-emails\">Linked emails</a></li>\n+          <li><a href=\"#profile-settings\">Profile settings</a></li>\n+          <li><a href=\"#security\">Security</a></li>\n+        </ul>\n+      </aside>\n+    </div>\n \n+    <div class=\"column is-9\">\n+      <h1 id=\"overview\" class=\"title\">\n+        <a href=\"#overview\" title=\"Permalink to this section\"></a>\n+        Overview\n+      </h1>\n+\n+      <section class=\"block\">\n+        <h2 id=\"projects\" class=\"title is-4\">\n+          <a href=\"#projects\" title=\"Permalink to this section\">#</a>\n+          Projects\n+        </h2>\n {% if user.profile.maintainer_projects.count %}\n-<p>\n-  Maintainer of\n+        <p>\n+          Maintainer of\n {% for project in user.profile.maintainer_projects.all %}\n-  <a href=\"{% url 'patch-list' project_id=project.linkname %}\">{{ project.linkname }}</a>{% if not forloop.last %},{% endif %}\n+            <a href=\"{% url 'patch-list' project_id=project.linkname %}\">{{ project.linkname }}</a>{% if not forloop.last %},{% endif %}\n {% endfor %}.\n-</p>\n+        </p>\n {% endif %}\n-\n {% if user.profile.contributor_projects.count %}\n-<p>\n-  Contributor to\n+        <p>\n+          Contributor to\n {% for project in user.profile.contributor_projects.all %}\n-  <a href=\"{% url 'patch-list' project_id=project.linkname %}\">{{ project.linkname }}</a>{% if not forloop.last %},{% endif %}\n+          <a href=\"{% url 'patch-list' project_id=project.linkname %}\">{{ project.linkname }}</a>{% if not forloop.last %},{% endif %}\n {% endfor %}.\n-</p>\n+        </p>\n {% endif %}\n+      </section>\n \n-<div class=\"leftcol\">\n-  <div class=\"box\">\n-    <h2>Todo</h2>\n-    <p>\n-      Your <a href=\"{% url 'user-todos' %}\">todo list</a> contains patches that\n-      have been delegated to you.\n+      <section class=\"block\">\n+        <h2 id=\"bundles\" class=\"title is-4\">\n+          <a href=\"#bundles\" title=\"Permalink to this section\">#</a>\n+          Bundles\n+        </h2>\n+{% if bundles %}\n+        <p>You have the following bundle{{ bundles|length|pluralize }}:</p>\n+        <ul>\n+{% for bundle in bundles %}\n+          <li><a href=\"{{ bundle.get_absolute_url }}\">{{ bundle.name }}</a></li>\n+{% endfor %}\n+        </ul>\n+        <p>\n+          Visit the <a href=\"{% url 'user-bundles' %}\">bundles page</a> to manage your bundles.\n+        </p>\n+{% else %}\n+        <p>You have no bundles.</p>\n+{% endif %}\n+      </section>\n+\n+      <section class=\"block\">\n+        <h2 id=\"todo\" class=\"title is-4\">\n+          <a href=\"#todo\" title=\"Permalink to this section\">#</a>\n+          Todo List\n+        </h2>\n+        <p>\n+          Your <a href=\"{% url 'user-todos' %}\">todo list</a> contains patches that\n+          have been delegated to you.\n+        </p>\n+        <p>\n {% if user.profile.n_todo_patches %}\n-      Your have {{ user.profile.n_todo_patches }}\n-      patch{{ user.profile.n_todo_patches|pluralize:\"es\" }} in your todo list.\n+          Your have {{ user.profile.n_todo_patches }}\n+          patch{{ user.profile.n_todo_patches|pluralize:\"es\" }} in your todo list.\n {% else %}\n-      You have no patches in your todo list at present.\n+          You have no patches in your todo list at present.\n {% endif %}\n-    </p>\n-  </div>\n+        </p>\n+      </section>\n \n-  <div class=\"box\">\n-    <h2>Linked email addresses</h2>\n-    <p>\n-      The following email addresses are associated with this Patchwork account.\n-      Adding alternative addresses allows Patchwork to group contributions that\n-      you have made under different addresses.\n-    </p>\n-    <p>\n-      The \"notify?\" column allows you to opt-in or opt-out of automated\n-      Patchwork notification emails. Setting it to \"no\" will disable automated\n-      notifications for that address.\n-    </p>\n-    <p>\n-      Adding a new email address will send a confirmation email to that address.\n-    </p>\n-    <table class=\"vertical\">\n-      <tr>\n-        <th>email</th>\n-        <th>action</th>\n-        <th>notify?</th>\n-      </tr>\n+      <h1 id=\"settings\" class=\"title\">\n+        <a href=\"#settings\" title=\"Permalink to this section\"></a>\n+        Settings\n+      </h1>\n+\n+{# TODO: Add view to enable this #}\n+      <section class=\"block\">\n+        <h2 id=\"profile\" class=\"title is-4\">\n+          <a href=\"#profile\" title=\"Permalink to this section\">#</a>\n+          Profile\n+        </h2>\n+        <form method=\"post\">\n+          {% csrf_token %}\n+          <div class=\"field\">\n+            <label for=\"id_username\" class=\"label\">\n+              Username\n+            </label>\n+            <div class=\"control\">\n+              <input id=\"id_username\" type=\"text\" name=\"name\" class=\"input\" value=\"{{ user.username }}\" disabled>\n+            </div>\n+          </div>\n+          <div class=\"field\">\n+            <label for=\"id_first_name\" class=\"label\">\n+              First name\n+            </label>\n+            <div class=\"control\">\n+              <input id=\"id_first_name\" type=\"text\" name=\"first_name\" class=\"input\" autocomplete=\"given-name\" value=\"{{ user.first_name }}\">\n+            </div>\n+          </div>\n+          <div class=\"field\">\n+            <label for=\"id_last_name\" class=\"label\">\n+              Last name\n+            </label>\n+            <div class=\"control\">\n+              <input id=\"id_last_name\" type=\"text\" name=\"last_name\" class=\"input\" autocomplete=\"family-name\" value=\"{{ user.last_name }}\">\n+            </div>\n+          </div>\n+          <div class=\"control\">\n+            <button class=\"button is-primary is-disabled\">Save</button>\n+          </div>\n+        </form>\n+      </section>\n+\n+      <section class=\"block\">\n+        <h2 id=\"linked-emails\" class=\"title is-4\">\n+          <a href=\"#linked-emails\" title=\"Permalink to this section\">#</a>\n+          Linked emails\n+        </h2>\n {% for email in linked_emails %}\n-      <tr>\n-        <td>{{ email.email }}</td>\n-        <td>\n+        <div class=\"card\">\n+          <div class=\"card-content\">\n+            <div class=\"columns\">\n+              <div class=\"column\">\n+                <span>{{ email.email }}</span>\n+{% if user.email == email.email %}\n+                <span class=\"tag is-primary is-medium\">Primary</span>\n+{% endif %}\n+              </div>\n {% if user.email != email.email %}\n-          <form action=\"{% url 'user-unlink' person_id=email.id %}\" method=\"post\">\n-            {% csrf_token %}\n-            <input type=\"submit\" value=\"Unlink\"/>\n-          </form>\n+              <div class=\"column is-narrow\">\n+                <form method=\"post\" action=\"{% url 'user-unlink' person_id=email.id %}\">\n+                  {% csrf_token %}\n+                  <button class=\"button is-danger\">Unlink</button>\n+                </form>\n+              </div>\n+{# TODO: Add view to enable this #}\n+              <div class=\"column is-narrow\">\n+                <form method=\"post\">\n+                  {% csrf_token %}\n+                  <button class=\"button is-info\">Make primary</button>\n+                </form>\n+              </div>\n {% endif %}\n-        </td>\n-        <td>\n+              <div class=\"column is-narrow\">\n {% if email.is_optout %}\n-          <form method=\"post\" action=\"{% url 'mail-optin' %}\">\n-            {% csrf_token %}\n-            No,\n-            <input type=\"hidden\" name=\"email\" value=\"{{ email.email }}\"/>\n-            <input type=\"submit\" value=\"Opt-in\"/>\n-          </form>\n+                <form method=\"post\" action=\"{% url 'mail-optin' %}\">\n+                  {% csrf_token %}\n+                  <input type=\"hidden\" name=\"email\" value=\"{{ email.email }}\"/>\n+                  <button class=\"button is-info is-right\">Opt-in</button>\n+                </form>\n {% else %}\n-          <form method=\"post\" action=\"{% url 'mail-optout' %}\">\n-            {% csrf_token %}\n-            Yes,\n-            <input type=\"hidden\" name=\"email\" value=\"{{ email.email }}\"/>\n-            <input type=\"submit\" value=\"Opt-out\"/>\n-          </form>\n+                <form method=\"post\" action=\"{% url 'mail-optout' %}\">\n+                  {% csrf_token %}\n+                  <input type=\"hidden\" name=\"email\" value=\"{{ email.email }}\"/>\n+                  <button class=\"button is-info\">Opt-out</button>\n+                </form>\n {% endif %}\n-        </td>\n-      </tr>\n+              </div>\n+            </div>\n+          </div>\n+        </div>\n {% endfor %}\n-      <tr>\n-        <td colspan=\"3\">\n-          <form action=\"{% url 'user-link' %}\" method=\"post\">\n+        <div class=\"block\"></div>\n+        <div class=\"block\">\n+          <form class=\"block\" method=\"post\" action=\"{% url 'user-link' %}\">\n             {% csrf_token %}\n-            {{ linkform.email }}\n-            <input type=\"submit\" value=\"Add\"/>\n+            <label for=\"id_email\" class=\"label\">\n+              Add email address\n+            </label>\n+            <div class=\"field is-grouped\">\n+              <div class=\"control\">\n+                <input id=\"id_email\" type=\"email\" name=\"email\" placeholder=\"e.g. bobsmith@example.com\" class=\"input\" required>\n+              </div>\n+              <div class=\"control\">\n+                <button class=\"button is-info\">\n+                  Add email\n+                </button>\n+              </div>\n+            </div>\n           </form>\n-        </td>\n-      </tr>\n-    </table>\n-  </div>\n-</div>\n-\n-<div class=\"rightcol\">\n-  <div class=\"box\">\n-    <h2>Bundles</h2>\n-{% if bundles %}\n-    <p>You have the following bundle{{ bundles|length|pluralize }}:</p>\n-    <ul>\n-{% for bundle in bundles %}\n-      <li><a href=\"{{ bundle.get_absolute_url }}\">{{ bundle.name }}</a></li>\n-{% endfor %}\n-    </ul>\n-    <p>Visit the <a href=\"{%url 'user-bundles' %}\">bundles page</a> to manage your bundles.</p>\n-{% else %}\n-    <p>You have no bundles.</p>\n-{% endif %}\n-  </div>\n+        </div>\n+      </section>\n \n-  <div class=\"box\">\n-    <h2>Settings</h2>\n+      <section class=\"block\">\n+        <h2 id=\"profile-settings\" class=\"title is-4\">\n+          <a href=\"#profile-settings\" title=\"Permalink to this section\">#</a>\n+          Profile settings\n+        </h2>\n+        <form class=\"block\" method=\"post\">\n+          {% csrf_token %}\n+          <div class=\"field\">\n+            <label for=\"id_items_per_page\" class=\"label\">\n+              Items per page\n+            </label>\n+            <div class=\"control\">\n+              <input id=\"id_items_per_page\" type=\"number\" name=\"items_per_page\" class=\"input\" value=\"{{ user.profile.items_per_page }}\" required>\n+              <p class=\"help\">Number of items to display per page</p>\n+            </div>\n+          </div>\n+          <div class=\"field\">\n+            <p class=\"label\">\n+              Show patch IDs\n+            </p>\n+            <div class=\"control\">\n+              <label class=\"radio\">\n+                <input type=\"radio\" name=\"show_ids\">\n+                Yes\n+              </label>\n+              <label class=\"radio\">\n+                <input type=\"radio\" name=\"show_ids\">\n+                No\n+              </label>\n+              <p class=\"help\">Show click-to-copy patch IDs in the list view</p>\n+            </div>\n+          </div>\n+          <div class=\"control\">\n+            <button class=\"button is-primary is-disabled\">Update settings</button>\n+          </div>\n+        </form>\n+      </section>\n \n-    <form method=\"post\">\n-      {% csrf_token %}\n-      <table class=\"form\">\n-        {{ profileform }}\n-        <tr>\n-          <td></td>\n-          <td><input type=\"submit\" value=\"Apply\"/></td>\n-        </tr>\n-      </table>\n-    </form>\n-  </div>\n-\n-  <div class=\"box\">\n-    <h2>Authentication</h2>\n-\n-    <table class=\"form\">\n-      <tr>\n-        <th>Password:</th>\n-        <td><a href=\"{% url 'password_change' %}\">Change password</a>\n-      </tr>\n-{% if rest_api_enabled %}\n-      <tr>\n-        <th>API Token:</th>\n-        <td>\n-{% if api_token %}\n-          <input id=\"token\" style=\"width: 25em;\" readonly value=\"{{ api_token }}\">\n-          <button type=\"button\" class=\"btn-copy\" title=\"Copy to clipboard\" data-clipboard-target=\"#token\">Copy</button>\n-{% endif %}\n-        </td>\n-      <tr>\n-        <th></th>\n-        <td>\n+      <section class=\"block\">\n+        <h2 id=\"security\" class=\"title is-4\">\n+          <a href=\"#security\" title=\"Permalink to this section\">#</a>\n+          Security\n+        </h2>\n+        <form class=\"block\" method=\"post\" action=\"{% url 'password_change' %}\">\n+          {% csrf_token %}\n+          <div class=\"field\">\n+            <label for=\"id_old_password\" class=\"label\">\n+              Current password\n+            </label>\n+            <div class=\"control\">\n+              <input id=\"id_old_password\" type=\"password\" name=\"old_password\" class=\"input\" required>\n+            </div>\n+          </div>\n+          <div class=\"field\">\n+            <label for=\"id_new_password1\" class=\"label\">\n+              New password\n+            </label>\n+            <div class=\"control\">\n+              <input id=\"id_new_password1\" type=\"password\" name=\"new_password1\" class=\"input\" required>\n+            </div>\n+          </div>\n+          <div class=\"field\">\n+            <label for=\"id_new_password2\" class=\"label\">\n+              Confirm password\n+            </label>\n+            <div class=\"control\">\n+              <input id=\"id_new_password2\" type=\"password\" name=\"new_password2\" class=\"input\" required>\n+            </div>\n+          </div>\n+          <div class=\"control\">\n+            <button class=\"button is-primary is-disabled\">Update password</button>\n+          </div>\n+        </form>\n+        <div class=\"block\">\n+          <label for=\"id_api_token\" class=\"label\">\n+            API token\n+          </label>\n+          <div class=\"field has-addons\">\n+            <div class=\"control is-expanded\">\n+              <input id=\"id_api_token\" type=\"text\" name=\"name\" class=\"input\" value=\"{{ api_token|default_if_none:'' }}\" disabled>\n+            </div>\n+{# TODO: wire this up #}\n+            <div class=\"control\">\n+              <button class=\"button is-info\">\n+                Copy\n+              </button>\n+            </div>\n+          </div>\n           <form method=\"post\" action=\"{% url 'generate_token' %}\">\n             {% csrf_token %}\n+            <div class=\"control\">\n {% if api_token %}\n-            <input type=\"submit\" value=\"Regenerate token\"/>\n+              <button class=\"button is-primary\">Regenerate token</button>\n {% else %}\n-            <input type=\"submit\" value=\"Generate token\"/>\n+              <button class=\"button is-primary\">Generate token</button>\n {% endif %}\n+            </div>\n           </form>\n-        </td>\n-      </tr>\n-{% endif %}\n-    </table>\n+        </div>\n+      </section>\n+    </div>\n   </div>\n </div>\n \n-<p style=\"clear: both\"></p>\n+<script>\n+document.addEventListener('DOMContentLoaded', () => {\n+  // Get all \"navbar-burger\" elements\n+  const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);\n+\n+  // Check if there are any navbar burgers\n+  if ($navbarBurgers.length > 0) {\n+    // Add a click event on each of them\n+    $navbarBurgers.forEach( el => {\n+      el.addEventListener('click', () => {\n+        // Get the target from the \"data-target\" attribute\n+        const target = el.dataset.target;\n+        const $target = document.getElementById(target);\n+\n+        // Toggle the \"is-active\" class on both the \"navbar-burger\" and the \"navbar-menu\"\n+        el.classList.toggle('is-active');\n+        $target.classList.toggle('is-active');\n+      });\n+    });\n+  }\n+});\n+</script>\n {% endblock %}\ndiff --git templates/base2.html templates/base2.html\nindex ac6b43bc..6380c37b 100644\n--- templates/base2.html\n+++ templates/base2.html\n@@ -10,6 +10,88 @@\n {% block headers %}{% endblock %}\n   </head>\n   <body>\n+{% block navigation %}\n+    <nav class=\"navbar is-white\" role=\"navigation\" aria-label=\"main navigation\">\n+      <div class=\"container\">\n+        <div class=\"navbar-brand\">\n+          <a class=\"navbar-item brand-text\" href=\"/\">Patchwork</a>\n+          <a role=\"button\" class=\"navbar-burger\" aria-label=\"menu\" aria-expanded=\"false\" data-target=\"navMenu\">\n+            <span aria-hidden=\"true\"></span>\n+            <span aria-hidden=\"true\"></span>\n+            <span aria-hidden=\"true\"></span>\n+          </a>\n+        </div>\n+        <div id=\"navMenu\" class=\"navbar-menu\">\n+          <div class=\"navbar-start\">\n+            <a class=\"navbar-item\" href=\"{% url 'user-todos' %}\">Todo List</a>\n+            <a class=\"navbar-item\" href=\"{% url 'user-bundles' %}\">Bundles</a>\n+            <a class=\"navbar-item\" href=\"{% url 'project-list' %}\">Projects</a>\n+          </div>\n+          <div class=\"navbar-end\">\n+{% if user.is_authenticated %}\n+            <div class=\"navbar-item has-dropdown is-hoverable\">\n+              <a class=\"navbar-link\">\n+                <span class=\"icon-text\">\n+                  <span class=\"icon\">\n+                    <i class=\"fa fa-user\"></i>\n+                  </span>\n+                  <span>{{ user.username }}</span>\n+                </span>\n+              </a>\n+              <div class=\"navbar-dropdown is-right\">\n+                <a class=\"navbar-item\" href=\"{% url 'user-todos' %}\">\n+                  Todo List\n+                </a>\n+                <a class=\"navbar-item\" href=\"{% url 'user-bundles' %}\">\n+                  Bundles\n+                </a>\n+                <a class=\"navbar-item\" href=\"{% url 'user-profile' %}\">\n+                  Profile\n+                </a>\n+{% if user.is_staff %}\n+                <hr class=\"navbar-divider\">\n+                <a class=\"navbar-item\" href=\"{% url 'admin:index' %}\">\n+                  Patchwork Settings\n+                </a>\n+{% endif %}\n+                <hr class=\"navbar-divider\">\n+                <a class=\"navbar-item\" href=\"{% url 'auth_logout' %}\">\n+                  Sign out\n+                </a>\n+              </div>\n+            </div>\n+{% else %}\n+            <div class=\"navbar-item\">\n+              <div class=\"buttons\">\n+                <a href=\"{% url 'user-register' %}\" class=\"button is-primary\">\n+                  <strong>Sign up</strong>\n+                </a>\n+                <a href=\"{% url 'auth_login' %}\" class=\"button is-light\">\n+                  Log in\n+                </a>\n+              </div>\n+            </div>\n+{% endif %}\n+          </div>\n+        </div>\n+      </div>\n+    </nav>\n+{% endblock %}\n {% block body %}{% endblock %}\n+{% block footer %}\n+    <div class=\"block\"></div>\n+\n+    <footer class=\"footer\">\n+      <div class=\"content has-text-centered\">\n+        <p>\n+          <a href=\"https://github.com/getpatchwork/patchwork/\">Patchwork patch tracking system</a>\n+          &nbsp;•&nbsp;\n+          Version {{ version }}\n+          &nbsp;•&nbsp;\n+          <a href=\"{% url 'about' %}\">About Patchwork</a>\n+        </p>\n+      </div>\n+    </footer>\n+{% endblock %}\n   </body>\n </html>\ndiff --git templates/registration/password_reset_confirm.html templates/registration/password_reset_confirm.html\nindex 1c91eb1b..90a7e136 100644\n--- templates/registration/password_reset_confirm.html\n+++ templates/registration/password_reset_confirm.html\n@@ -3,6 +3,8 @@\n {% block title %}Password reset confirmation{% endblock %}\n {% block heading %}Password reset confirmation{% endblock %}\n \n+{% block navigation %}{% endblock %}\n+\n {% block body %}\n <section class=\"hero is-primary is-fullheight\">\n   <div class=\"hero-body\">\n@@ -75,3 +77,5 @@\n   </div>\n </section>\n {% endblock %}\n+\n+{% block footer %}{% endblock %}\ndiff --git templates/registration/password_reset_done.html templates/registration/password_reset_done.html\nindex ebd38e68..65b65e77 100644\n--- templates/registration/password_reset_done.html\n+++ templates/registration/password_reset_done.html\n@@ -2,6 +2,8 @@\n \n {% block title %}Password reset email sent!{% endblock %}\n \n+{% block navigation %}{% endblock %}\n+\n {% block body %}\n <section class=\"hero is-primary is-fullheight\">\n   <div class=\"hero-body\">\n@@ -26,3 +28,5 @@\n   </div>\n </section>\n {% endblock %}\n+\n+{% block footer %}{% endblock %}\ndiff --git templates/registration/password_reset_form.html templates/registration/password_reset_form.html\nindex 431b4696..4f0c3a6a 100644\n--- templates/registration/password_reset_form.html\n+++ templates/registration/password_reset_form.html\n@@ -2,6 +2,8 @@\n \n {% block title %}Forgot your password?{% endblock %}\n \n+{% block navigation %}{% endblock %}\n+\n {% block body %}\n <section class=\"hero is-primary is-fullheight\">\n   <div class=\"hero-body\">\n@@ -46,3 +48,5 @@\n   </div>\n </section>\n {% endblock %}\n+\n+{% block footer %}{% endblock %}\n",
    "prefixes": [
        "RFC",
        "10/19"
    ]
}