Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1523350/?format=api
{ "id": 1523350, "url": "http://patchwork.ozlabs.org/api/patches/1523350/?format=api", "web_url": "http://patchwork.ozlabs.org/project/patchwork/patch/20210901165756.181192-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": "<20210901165756.181192-11-stephen@that.guru>", "list_archive_url": null, "date": "2021-09-01T16:57:47", "name": "[RFC,v2,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/20210901165756.181192-11-stephen@that.guru/mbox/", "series": [ { "id": 260605, "url": "http://patchwork.ozlabs.org/api/series/260605/?format=api", "web_url": "http://patchwork.ozlabs.org/project/patchwork/list/?series=260605", "date": "2021-09-01T16:57:37", "name": "Integrate Bulma", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/260605/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1523350/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1523350/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\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=L/sMpa7M;\n\tdkim-atps=neutral", "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>)", "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=L/sMpa7M;\n\tdkim-atps=neutral", "lists.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=that.guru\n (client-ip=136.175.108.161; helo=mail-108-mta161.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=L/sMpa7M;\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 4H09jb64h3z9sW8\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 2 Sep 2021 03:17:39 +1000 (AEST)", "from boromir.ozlabs.org (localhost [IPv6:::1])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 4H09jb4gqVz2ywQ\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 2 Sep 2021 03:17:39 +1000 (AEST)", "from mail-108-mta161.mxroute.com (mail-108-mta161.mxroute.com\n [136.175.108.161])\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 4H09hy67rjz304R\n for <patchwork@lists.ozlabs.org>; Thu, 2 Sep 2021 03:17:06 +1000 (AEST)", "from filter004.mxroute.com ([149.28.56.236] filter004.mxroute.com)\n (Authenticated sender: mN4UYu2MZsgR)\n by mail-108-mta161.mxroute.com (ZoneMTA) with ESMTPSA id\n 17ba25d289500074ba.001 for <patchwork@lists.ozlabs.org>\n (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES128-GCM-SHA256);\n Wed, 01 Sep 2021 17:16:59 +0000" ], "X-Zone-Loop": "1d2d28f3517bba9e9a052966d382105b69a3b955be74", "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=L/sMpa7Mc6XjR9cnu+UnBqbhKm\n KJvD313zzQ4VgcTTpKhDFFU3JnLB52kRUkoOHou0SlzuQiO79AvvZarN7JES+DL1+HBFCgu9LCM+t\n 6JtyS0JhgQD2A2epr3uUID5bJ7JaABE7Q3oQo6JdxzJUc6BVxDVcZ8g9hDTRxAUS/+zGdnih0jH8s\n SPH4lYEQOSi5TGkT5xENTF11GhX+aGYaacgJJbLyFxsfqZ+tlaNxqGT3asv62JfgETWEEXwBQwLUF\n 7XlBE5+uwi9DQqvcFtN8vFtZzdMvxSl5k3+Iqr1PId2XQPOJzH4Qkqw4sIx+5eI2Bo9OR1OqH94rZ\n yxL60Xaw==;", "From": "Stephen Finucane <stephen@that.guru>", "To": "patchwork@lists.ozlabs.org", "Subject": "[RFC PATCH v2 10/19] templates: Convert user profile view", "Date": "Wed, 1 Sep 2021 17:57:47 +0100", "Message-Id": "<20210901165756.181192-11-stephen@that.guru>", "X-Mailer": "git-send-email 2.31.1", "In-Reply-To": "<20210901165756.181192-1-stephen@that.guru>", "References": "<20210901165756.181192-1-stephen@that.guru>", "MIME-Version": "1.0", "X-AuthUser": "stephen@that.guru", "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+ • \n+ Version {{ version }}\n+ • \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", "v2", "10/19" ] }