summaryrefslogtreecommitdiff
path: root/templates/mod
diff options
context:
space:
mode:
authorMichael Save <savetheinternet@tinyboard.org>2012-08-27 02:28:04 +1000
committerMichael Save <savetheinternet@tinyboard.org>2012-08-27 02:28:04 +1000
commit6a705fd8c2324b642ac6bfc660d76cff6d5eab62 (patch)
tree7f916bebf46f66ed55569ea1456686524aebc192 /templates/mod
parent1dcb385e9e3791d2d3c1d049fe9b8d906539088e (diff)
parentc919e7362542117f613c2800017ae89c269a07b5 (diff)
Merge branch 'mod-rewrite'
Conflicts: inc/lib/Twig/Extensions/Extension/Tinyboard.php install.php mod.php stylesheets/style.css templates/index.html templates/page.html templates/thread.html
Diffstat (limited to 'templates/mod')
-rw-r--r--templates/mod/ban_form.html91
-rw-r--r--templates/mod/ban_list.html95
-rw-r--r--templates/mod/board.html44
-rw-r--r--templates/mod/config-editor.html56
-rw-r--r--templates/mod/confirm.html7
-rw-r--r--templates/mod/dashboard.html139
-rw-r--r--templates/mod/debug/antispam.html65
-rw-r--r--templates/mod/inbox.html36
-rw-r--r--templates/mod/log.html47
-rw-r--r--templates/mod/login.html26
-rw-r--r--templates/mod/move.html41
-rw-r--r--templates/mod/new_pm.html18
-rw-r--r--templates/mod/news.html70
-rw-r--r--templates/mod/noticeboard.html65
-rw-r--r--templates/mod/pm.html44
-rw-r--r--templates/mod/rebuild.html71
-rw-r--r--templates/mod/rebuilt.html12
-rw-r--r--templates/mod/report.html26
-rw-r--r--templates/mod/reports.html6
-rw-r--r--templates/mod/theme_config.html27
-rw-r--r--templates/mod/theme_installed.html9
-rw-r--r--templates/mod/theme_rebuilt.html2
-rw-r--r--templates/mod/themes.html40
-rw-r--r--templates/mod/user.html125
-rw-r--r--templates/mod/users.html71
-rw-r--r--templates/mod/view_ip.html163
26 files changed, 1396 insertions, 0 deletions
diff --git a/templates/mod/ban_form.html b/templates/mod/ban_form.html
new file mode 100644
index 00000000..5d5f2b81
--- /dev/null
+++ b/templates/mod/ban_form.html
@@ -0,0 +1,91 @@
+{% if post and board %}
+ {% set action = '?/' ~ board ~ '/ban/' ~ post %}
+{% else %}
+ {% set action = '?/ban' %}
+{% endif %}
+
+<form action="{{ action }}" method="post">
+ {% if redirect %}
+ <input type="hidden" name="redirect" value="{{ redirect|e }}">
+ {% endif %}
+ {% if post and board %}
+ <input type="hidden" name="delete" value="{% if delete %}1{% else %}0{% endif %}">
+ {% endif %}
+
+ <table>
+
+ <tr>
+ <th>
+ <label for="ip">{% trans 'IP' %} <span class="unimportant">{% trans '(or subnet)' %}</span></label>
+ </th>
+ <td>
+ {% if not hide_ip %}
+ <input type="text" name="ip" id="ip" size="30" maxlength="40" value="{{ ip }}">
+ {% else %}
+ <em>{% trans 'hidden' %}</em>
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>
+ <label for="reason">{% trans 'Reason' %}</label>
+ </th>
+ <td>
+ <textarea name="reason" id="reason" rows="5" cols="30">{{ reason|e }}</textarea>
+ </td>
+ </tr>
+ {% if post and board and not delete %}
+ <tr>
+ <th>
+ <label for="reason">{% trans 'Message' %}</label>
+ </th>
+ <td>
+ <input type="checkbox" id="public_message" name="public_message">
+ <input type="text" name="message" id="message" size="35" maxlength="200" value="{{ config.mod.default_ban_message|e }}">
+ <span class="unimportant">({% trans 'public; attached to post' %})</span>
+ <script type="text/javascript">
+ document.getElementById('message').disabled = true;
+ document.getElementById('public_message').onchange = function() {
+ document.getElementById('message').disabled = !this.checked;
+ }
+ </script>
+ </td>
+ </tr>
+ {% endif %}
+ <tr>
+ <th>
+ <label for="length">{% trans 'Length' %}</label>
+ </th>
+ <td>
+ <input type="text" name="length" id="length" size="20" maxlength="40">
+ <span class="unimportant">(eg. "2d1h30m" or "2 days")</span></td>
+ </tr>
+ <tr>
+ <th>{% trans 'Board' %}</th>
+ <td>
+ <ul style="list-style:none;padding:2px 5px">
+ <li>
+ <input type="radio" name="board" value="*" id="ban-allboards" checked>
+ <label style="display:inline" for="ban-allboards">
+ <em>{% trans 'all boards' %}</em>
+ </label>
+ </li>
+
+ {% for board in boards %}
+ <li>
+ <input type="radio" name="board" value="{{ board.uri }}" id="ban-board-{{ board.uri }}">
+ <label style="display:inline" for="ban-board-{{ board.uri }}">
+ {{ config.board_abbreviation|sprintf(board.uri) }} - {{ board.title|e }}
+ </label>
+ </li>
+ {% endfor %}
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td><input name="new_ban" type="submit" value="{% trans 'New Ban' %}"></td>
+ </tr>
+ </table>
+</form>
+
diff --git a/templates/mod/ban_list.html b/templates/mod/ban_list.html
new file mode 100644
index 00000000..2edb9cdf
--- /dev/null
+++ b/templates/mod/ban_list.html
@@ -0,0 +1,95 @@
+{% if bans|count == 0 %}
+ <p style="text-align:center" class="unimportant">({% trans 'There are no active bans.' %})</p>
+{% else %}
+ <form action="" method="post">
+ <table class="mod" style="width:100%">
+ <tr>
+ <th>{% trans 'IP address/mask' %}</th>
+ <th>{% trans 'Reason' %}</th>
+ <th>{% trans 'Board' %}</th>
+ <th>{% trans 'Set' %}</th>
+ <th>{% trans 'Duration' %}</th>
+ <th>{% trans 'Expires' %}</th>
+ <th>{% trans 'Staff' %}</th>
+ </tr>
+ {% for ban in bans %}
+ <tr{% if ban.expires != 0 and ban.expires < time() %} style="text-decoration:line-through"{% endif %}>
+ <td style="white-space: nowrap">
+ <input type="checkbox" name="ban_{{ ban.id }}">
+ {% if ban.real_ip %}
+ <a href="?/IP/{{ ban.ip }}">{{ ban.ip }}</a>
+ {% else %}
+ {{ ban.ip|e }}
+ {% endif %}
+ </td>
+ <td>
+ {% if ban.reason %}
+ {{ ban.reason }}
+ {% else %}
+ -
+ {% endif %}
+ </td>
+ <td style="white-space: nowrap">
+ {% if ban.board %}
+ {{ config.board_abbreviation|sprintf(ban.board) }}
+ {% else %}
+ <em>{% trans 'all boards' %}</em>
+ {% endif %}
+ </td>
+ <td style="white-space: nowrap">
+ <span title="{{ ban.set|date(config.post_date) }}">
+ {{ ban.set|ago }} ago
+ </span>
+ </td>
+ <td style="white-space: nowrap">
+ {% if ban.expires == 0 %}
+ -
+ {% else %}
+ {{ (ban.expires - ban.set + time()) | until }}
+ {% endif %}
+ </td>
+ <td style="white-space: nowrap">
+ {% if ban.expires == 0 %}
+ <em>{% trans 'never' %}</em>
+ {% else %}
+ {{ ban.expires|date(config.post_date) }}
+ {% if ban.expires > time() %}
+ <small>(in {{ ban.expires|until }})</small>
+ {% endif %}
+ {% endif %}
+ </td>
+ <td>
+ {% if ban.username %}
+ {% if mod|hasPermission(config.mod.view_banstaff) %}
+ <a href="?/new_PM/{{ ban.username|e }}">{{ ban.username|e }}</a>
+ {% else %}
+ {% if mod|hasPermission(config.mod.view_banquestionmark) %}
+ <em>?</em>
+ {% else %}
+
+ {% endif %}
+ {% endif %}
+ {% elseif ban.mod == -1 %}
+ <em>system</em>
+ {% else %}
+ <em>{% trans 'deleted?' %}</em>
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+
+ <p style="text-align:center">
+ <input type="submit" name="unban" value="{% trans 'Unban selected' %}">
+ </p>
+ </form>
+{% endif %}
+
+{% if count > bans|count %}
+ <p class="unimportant" style="text-align:center;word-wrap:break-word">
+ {% for i in range(0, (count - 1) / config.mod.modlog_page) %}
+ <a href="?/bans/{{ i + 1 }}">[{{ i + 1 }}]</a>
+ {% endfor %}
+ </p>
+{% endif %}
+
diff --git a/templates/mod/board.html b/templates/mod/board.html
new file mode 100644
index 00000000..0775e421
--- /dev/null
+++ b/templates/mod/board.html
@@ -0,0 +1,44 @@
+{% if new %}
+ {% set action = '?/new-board' %}
+{% else %}
+ {% set action = '?/edit/' ~ board.uri %}
+{% endif %}
+
+<form action="{{ action }}" method="post">
+ <table>
+ <tr>
+ <th>{% trans 'URI' %}</th>
+ <td>
+ {% if not new %}
+ {{ config.board_abbreviation|sprintf(board.uri) }}
+ {% else %}
+ /<input size="10" maxlength="255" type="text" name="uri" autocomplete="off">/
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>{% trans 'Title' %}</th>
+ <td>
+ <input size="25" type="text" name="title" value="{{ board.title|e }}" autocomplete="off">
+ </td>
+ </tr>
+ <tr>
+ <th>{% trans 'Subtitle' %}</th>
+ <td>
+ <input size="25" type="text" name="subtitle" value="{{ board.subtitle|e }}" autocomplete="off">
+ </td>
+ </tr>
+ </table>
+
+ <ul style="padding:0;text-align:center;list-style:none">
+ {% if new %}
+ <li><input type="submit" value="{% trans 'Create board' %}"></li>
+ {% else %}
+ <li><input type="submit" value="{% trans 'Save changes' %}"></li>
+ {% if mod|hasPermission(config.mod.deleteboard) %}
+ <li><input name="delete" onclick="return confirm('Are you sure you want to permanently delete this board?');" type="submit" value="{% trans 'Delete board' %}"></li>
+ {% endif %}
+ {% endif %}
+ </ul>
+</form>
+
diff --git a/templates/mod/config-editor.html b/templates/mod/config-editor.html
new file mode 100644
index 00000000..ec7213bb
--- /dev/null
+++ b/templates/mod/config-editor.html
@@ -0,0 +1,56 @@
+<form method="post" action="">
+ <table class="mod config-editor">
+ <tr>
+ <th class="minimal">Name</th>
+ <th>Value</th>
+ <th class="minimal">Type</th>
+ <th>Description</th>
+ </tr>
+ {% for var in conf if var.type != 'array' %}
+ {% if var.name|count == 1 %}
+ {% set name = 'cf_' ~ var.name %}
+ {% else %}
+ {% set name = 'cf_' ~ var.name|join('/') %}
+ {% endif %}
+
+ <tr>
+ <th class="minimal">
+ {% if var.name|count == 1 %}
+ {{ var.name }}
+ {% else %}
+ {{ var.name|join(' &rarr; ') }}
+ {% endif %}
+ </th>
+
+ <td>
+ {% if var.type == 'string' %}
+ <input name="{{ name }}" type="text" value="{{ var.value|e }}">
+ {% elseif var.type == 'integer' %}
+ <input name="{{ name }}" type="number" value="{{ var.value|e }}">
+ {% elseif var.type == 'boolean' %}
+ <input name="{{ name }}" type="checkbox" {% if var.value %}checked{% endif %}>
+ {% else %}
+ ?
+ {% endif %}
+
+ {% if var.type == 'integer' or var.type == 'boolean' %}
+ <small>Default: <code>{{ var.default }}</code></small>
+ {% endif %}
+ </td>
+
+ <td class="minimal">
+ {{ var.type|e }}
+ </td>
+
+ <td>
+ {{ var.comment|join('<br>') }}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+
+ <ul style="padding:0;text-align:center;list-style:none">
+ <li><input name="save" type="submit" value="{% trans 'Save changes' %}"></li>
+ </ul>
+</form>
+
diff --git a/templates/mod/confirm.html b/templates/mod/confirm.html
new file mode 100644
index 00000000..6dc4d66a
--- /dev/null
+++ b/templates/mod/confirm.html
@@ -0,0 +1,7 @@
+<p style="text-align:center;font-size:1.1em">
+ {% trans 'Are you sure you want to do that?' %} <a href="?/{{ request }}">{% trans 'Click to proceed to' %} ?/{{ request }}</a>.
+</p>
+<p class="unimportant" style="text-align:center">
+ {% trans 'You are seeing this message because we were unable to serve a confirmation dialog, probably due to Javascript being disabled.' %}
+</p>
+
diff --git a/templates/mod/dashboard.html b/templates/mod/dashboard.html
new file mode 100644
index 00000000..30742dc1
--- /dev/null
+++ b/templates/mod/dashboard.html
@@ -0,0 +1,139 @@
+<fieldset>
+ <legend>{% trans 'Boards' %}</legend>
+
+ <ul>
+ {% for board in boards %}
+ <li>
+ <a href="?/{{ config.board_path|sprintf(board.uri) }}{{ config.file_index }}">{{ config.board_abbreviation|sprintf(board.uri) }}</a>
+ -
+ {{ board.title|e }}
+ {% if board.subtitle %}
+ <small>&mdash; {{ board.subtitle|e }}</small>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.manageboards) %}
+ <a href="?/edit/{{ board.uri }}"><small>[{% trans 'edit' %}]</small></a>
+ {% endif %}
+ </li>
+ {% endfor %}
+
+ {% if mod|hasPermission(config.mod.newboard) %}
+ <li style="margin-top:15px"><a href="?/new-board"><strong>{% trans 'Create new board' %}</strong></a></li>
+ {% endif %}
+ </ul>
+</fieldset>
+
+<fieldset>
+ <legend>{% trans 'Messages' %}</legend>
+ <ul>
+ {% if mod|hasPermission(config.mod.noticeboard) %}
+ {% if noticeboard|count > 0 %}
+ <li>
+ {% trans 'Noticeboard' %}:
+ <ul>
+ {% for post in noticeboard %}
+ <li>
+ <a href="?/noticeboard#{{ post.id }}">
+ {% if post.subject %}
+ {{ post.subject|e }}
+ {% else %}
+ <em>{% trans 'no subject' %}</em>
+ {% endif %}
+ </a>
+ <small class="unimportant">
+ &mdash; by
+ {% if post.username %}
+ {{ post.username|e }}
+ {% else %}
+ <em>deleted?</em>
+ {% endif %}
+ at
+ {{ post.time|date(config.post_date) }}
+ </small>
+ </li>
+ {% endfor %}
+ </ul>
+ </li>
+ {% endif %}
+ <li><a href="?/noticeboard">{% trans 'View all entries' %}</a></li>
+ {% endif %}
+ <li><a href="?/news">{% trans 'News' %}</a></li>
+ <li>
+ <a href="?/inbox">
+ {% trans 'PM inbox' %}
+ {% if unread_pms > 0 %}<strong>{%endif %}({{ unread_pms }} unread){% if unread_pms > 0 %}</strong>{%endif %}
+ </a>
+ </li>
+ </ul>
+</fieldset>
+
+<fieldset>
+ <legend>{% trans 'Administration' %}</legend>
+
+ <ul>
+ {% if mod|hasPermission(config.mod.reports) %}
+ <li>
+ {% if reports > 0 %}<strong>{% endif %}
+ <a href="?/reports">{% trans 'Report queue' %} ({{ reports }})</a>
+ {% if reports > 0 %}</strong>{% endif %}
+ </li>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.view_banlist) %}
+ <li><a href="?/bans">{% trans 'Ban list' %}</a></li>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.manageusers) %}
+ <li><a href="?/users">{% trans 'Manage users' %}</a></li>
+ {% elseif mod|hasPermission(config.mod.change_password) %}
+ <li><a href="?/users/{{ mod.id }}">{% trans 'Change password' %}</a></li>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.themes) %}
+ <li><a href="?/themes">{% trans 'Manage themes' %}</a></li>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.modlog) %}
+ <li><a href="?/log">{% trans 'Moderation log' %}</a></li>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.rebuild) %}
+ <li><a href="?/rebuild">{% trans 'Rebuild' %}</a></li>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.show_config) %}
+ <li><a href="?/config">{% trans 'Configuration' %}</a></li>
+ {% endif %}
+
+ </ul>
+</fieldset>
+
+<fieldset>
+ <legend>{% trans 'Search' %}</legend>
+
+ {# TODO #}
+</fieldset>
+
+{% if config.debug %}
+ <fieldset>
+ <legend>{% trans 'Debug' %}</legend>
+ <ul>
+ <li><a href="?/debug/antispam">{% trans 'Anti-spam' %}</a></li>
+ </ul>
+ </fieldset>
+{% endif %}
+
+{% if newer_release %}
+ <fieldset>
+ <legend>Update</legend>
+ <ul>
+ <li>
+ A newer version of Tinyboard
+ (<strong>v{{ newer_release.massive }}.{{ newer_release.major }}.{{ newer_release.minor }}</strong>) is available!
+ See <a href="http://tinyboard.org">http://tinyboard.org/</a> for upgrade instructions.
+ </li>
+ </ul>
+ </fieldset>
+{% endif %}
+
+<fieldset>
+ <legend>{% trans 'User account' %}</legend>
+
+ <ul>
+ <li><a href="?/logout">{% trans 'Logout' %}</a></li>
+ </ul>
+</fieldset>
+
diff --git a/templates/mod/debug/antispam.html b/templates/mod/debug/antispam.html
new file mode 100644
index 00000000..a846bc17
--- /dev/null
+++ b/templates/mod/debug/antispam.html
@@ -0,0 +1,65 @@
+<p style="text-align:center">
+ Most used (in active):
+</p>
+<table class="modlog" style="width:700px;margin:auto">
+ <tr>
+ <th>Board</th>
+ <th>Thread</th>
+ <th>Hash (SHA1)</th>
+ <th>Created</th>
+ <th>Expires</th>
+ <th>Passed</th>
+ </tr>
+ {% for hash in top %}
+ <tr>
+ <td>{{ config.board_abbreviation|sprintf(hash.board) }}</td>
+ <td>
+ {% if hash.thread %}
+ {{ hash.thread }}
+ {% else %}
+ -
+ {% endif %}</td>
+ <td>
+ <small><code>{{ hash.hash }}</code></small>
+ </td>
+ <td>
+ <span title="{{ hash.created|date(config.post_date) }}">{{ hash.created|ago }} ago</span>
+ </td>
+ <td>
+ {% if hash.expires %}
+ <span title="{{ hash.expires|date(config.post_date) }}">
+ {{ hash.expires|until }}
+ </span>
+ {% else %}
+ -
+ {% endif %}
+ </td>
+ <td>{{ hash.passed }}</td>
+ </tr>
+ {% endfor %}
+</table>
+<p style="text-align:center">
+ Total: <strong>{{ total }}</strong> (<strong>{{ expiring }}</strong> set to expire)
+</p>
+
+<form method="post" action="?/debug/antispam">
+ <table class="modlog" style="width:1%;white-space:nowrap;margin:auto">
+ <tr>
+ <th>Board</th>
+ <th>Thread</th>
+ <th></th>
+ </tr>
+ <tr>
+ <td>
+ <input type="text" name="board" style="width:90px" value="{{ board }}">
+ </td>
+ <td>
+ <input type="text" name="thread" style="width:90px" value="{{ thread }}">
+ </td>
+ <td>
+ <input type="submit" name="filter" value="Filter">
+ <input type="submit" name="purge" value="Purge">
+ </td>
+ </tr>
+ </table>
+</form>
diff --git a/templates/mod/inbox.html b/templates/mod/inbox.html
new file mode 100644
index 00000000..97afe446
--- /dev/null
+++ b/templates/mod/inbox.html
@@ -0,0 +1,36 @@
+{% if messages|count == 0 %}
+ <p style="text-align:center" class="unimportant">({% trans 'No private messages for you.' %})</p>
+{% else %}
+ <table class="modlog">
+ <tr>
+ <th>{% trans 'ID' %}</th>
+ <th>{% trans 'From' %}</th>
+ <th>{% trans 'Date' %}</th>
+ <th>{% trans 'Message snippet' %}</th>
+ </tr>
+ {% for message in messages %}
+ <tr{% if message.unread %} style="font-weight:bold"{% endif %}>
+ <td class="minimal">
+ <a href="?/PM/{{ message.id }}">
+ {{ message.id }}
+ </a>
+ </td>
+ <td class="minimal">
+ {% if message.username %}
+ <a href="?/new_PM/{{ message.username|e }}">{{ message.username|e }}</a>
+ {% else %}
+ <em>{% trans 'deleted?' %}</em>
+ {% endif %}
+ </td>
+ <td class="minimal">
+ {{ message.time|date(config.post_date) }}
+ </td>
+ <td>
+ <a href="?/PM/{{ message.id }}">
+ {{ message.snippet }}
+ </a>
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+{% endif %}
diff --git a/templates/mod/log.html b/templates/mod/log.html
new file mode 100644
index 00000000..dca1b2d0
--- /dev/null
+++ b/templates/mod/log.html
@@ -0,0 +1,47 @@
+<table class="modlog">
+ <tr>
+ <th>{% trans 'Staff' %}</th>
+ <th>{% trans 'IP address' %}</th>
+ <th>{% trans 'Time' %}</th>
+ <th>{% trans 'Board' %}</th>
+ <th>{% trans 'Action' %}</th>
+ </tr>
+ {% for log in logs %}
+ <tr>
+ <td class="minimal">
+ {% if log.username %}
+ <a href="?/new_PM/{{ log.username|e }}">{{ log.username|e }}</a>
+ {% elseif log.mod == -1 %}
+ <em>system</em>
+ {% else %}
+ <em>{% trans 'deleted?' %}</em>
+ {% endif %}
+ </td>
+ <td class="minimal">
+ <a href="?/IP/{{ log.ip }}">{{ log.ip }}</a>
+ </td>
+ <td class="minimal">
+ <span title="{{ log.time|date(config.post_date) }}">{{ log.time|ago }}</span>
+ </td>
+ <td class="minimal">
+ {% if log.board %}
+ <a href="?/{{ config.board_path|sprintf(log.board) }}{{ config.file_index }}">{{ config.board_abbreviation|sprintf(log.board) }}</a>
+ {% else %}
+ -
+ {% endif %}
+ </td>
+ <td>
+ {{ log.text }}
+ </td>
+ </tr>
+ {% endfor %}
+</table>
+
+{% if count > logs|count %}
+ <p class="unimportant" style="text-align:center;word-wrap:break-word">
+ {% for i in range(0, (count - 1) / config.mod.modlog_page) %}
+ <a href="?/log/{{ i + 1 }}">[{{ i + 1 }}]</a>
+ {% endfor %}
+ </p>
+{% endif %}
+
diff --git a/templates/mod/login.html b/templates/mod/login.html
new file mode 100644
index 00000000..43a28d56
--- /dev/null
+++ b/templates/mod/login.html
@@ -0,0 +1,26 @@
+{% if error %}<h2 style="text-align:center">{{ error }}</h2>{% endif %}
+<form action="" method="post">
+<table style="margin-top:25px;">
+ <tr>
+ <th>
+ {% trans 'Username' %}
+ </th>
+ <td>
+ <input type="text" name="username" size="20" maxlength="30" value="{{ username|e }}">
+ </td>
+ </tr>
+ <tr>
+ <th>
+ {% trans 'Password' %}
+ </th>
+ <td>
+ <input type="password" name="password" size="20" maxlength="30" value="">
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>
+ <input type="submit" name="login" value="{% trans %}Continue{% endtrans %}" />
+ </td>
+</table>
+</form>
diff --git a/templates/mod/move.html b/templates/mod/move.html
new file mode 100644
index 00000000..802903b2
--- /dev/null
+++ b/templates/mod/move.html
@@ -0,0 +1,41 @@
+<form action="?/{{ board }}/move/{{ post }}" method="post">
+ <table>
+ <tr>
+ <th>
+ {% trans 'Thread ID' %}
+ </th>
+ <td>
+ &gt;&gt;&gt;{{ config.board_abbreviation|sprintf(board) }}{{ post }}
+ </td>
+ </tr>
+ <tr>
+ <th>
+ {% trans 'Leave shadow thread' %}
+ </th>
+ <td>
+ <input type="checkbox" name="shadow" checked>
+ <span class="unimportant">({% trans 'locks thread; replies to it with a link.' %})</span>
+ </td>
+ </tr>
+ <tr>
+ <th>{% trans 'Target board' %}</th>
+ <td>
+ <ul style="list-style:none;padding:0">
+ {% for targetboard in boards if targetboard.uri != board %}
+ <li>
+ <input type="radio" name="board" value="{{ targetboard.uri }}" id="ban-board-{{ targetboard.uri }}">
+ <label style="display:inline" for="ban-board-{{ targetboard.uri }}">
+ {{ config.board_abbreviation|sprintf(targetboard.uri) }} - {{ targetboard.title|e }}
+ </label>
+ </li>
+ {% endfor %}
+ </ul>
+ </td>
+ </tr>
+ </table>
+
+ <ul style="padding:0;text-align:center;list-style:none">
+ <li><input type="submit" value="{% trans 'Move thread' %}"></li>
+ </ul>
+</form>
+
diff --git a/templates/mod/new_pm.html b/templates/mod/new_pm.html
new file mode 100644
index 00000000..3fd78ac6
--- /dev/null
+++ b/templates/mod/new_pm.html
@@ -0,0 +1,18 @@
+<form action="?/new_PM/{{ username|e }}" method="post">
+ <table>
+ <tr>
+ <th>To</th>
+ {% if mod|hasPermission(config.mod.editusers) %}
+ <td><a href="?/users/{{ id }}">{{ username|e }}</a></td>
+ {% else %}
+ <td>{{ username|e }}</td>
+ {% endif %}
+ </tr>
+ <tr>
+ <th>Message</th>
+ <td><textarea name="message" rows="10" cols="40">{{ message }}</textarea></td>
+ </tr>
+ </table>
+
+ <p style="text-align:center"><input type="submit" value="{% trans 'Send message' %}"></p>
+</form>
diff --git a/templates/mod/news.html b/templates/mod/news.html
new file mode 100644
index 00000000..b6c35798
--- /dev/null
+++ b/templates/mod/news.html
@@ -0,0 +1,70 @@
+{% if mod|hasPermission(config.mod.news) %}
+ <fieldset>
+ <legend>{% trans 'New post' %}</legend>
+ <form style="margin:0" action="" method="post">
+ <table>
+ <tr>
+ <th>
+ {% if mod|hasPermission(config.mod.news_custom) %}
+ <label for="name">{% trans 'Name' %}</label>
+ {% else %}
+ {% trans 'Name' %}
+ {% endif %}
+ </th>
+ <td>
+ {% if mod|hasPermission(config.mod.news_custom) %}
+ <input type="text" size="55" name="name" id="name" value="{{ mod.username|e }}">
+ {% else %}
+ {{ mod.username|e }}
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th><label for="subject">{% trans 'Subject' %}</label></th>
+ <td><input type="text" size="55" name="subject" id="subject"></td>
+ </tr>
+ <tr>
+ <th><label for="body">{% trans 'Body' %}</label></th>
+ <td><textarea name="body" id="body" style="width:100%;height:100px"></textarea></td>
+ </tr>
+ </table>
+ <p style="text-align:center">
+ <input type="submit" value="{% trans 'Post news entry' %}">
+ </p>
+ </form>
+ </fieldset>
+{% endif %}
+
+{% for post in news %}
+ <div class="ban">
+ {% if mod|hasPermission(config.mod.news_delete) %}
+ <span style="float:right;padding:2px">
+ <a class="unimportant" href="?/news/delete/{{ post.id }}">[{% trans 'delete' %}]</a>
+ </span>
+ {% endif %}
+ <h2 id="{{ post.id }}">
+ <small class="unimportant">
+ <a href="#{{ post.id }}">#</a>
+ </small>
+ {% if post.subject %}
+ {{ post.subject|e }}
+ {% else %}
+ <em>{% trans 'no subject' %}</em>
+ {% endif %}
+ <small class="unimportant">
+ &mdash; {% trans 'by' %} {{ post.name }} {% trans 'at' %} {{ notice.time|date(config.post_date) }}
+ </small>
+ </h2>
+ <p>
+ {{ post.body }}
+ </p>
+ </div>
+{% endfor %}
+
+{% if count > news|count %}
+ <p class="unimportant" style="text-align:center;word-wrap:break-word">
+ {% for i in range(0, (count - 1) / config.mod.news_page) %}
+ <a href="?/news/{{ i + 1 }}">[{{ i + 1 }}]</a>
+ {% endfor %}
+ </p>
+{% endif %}
diff --git a/templates/mod/noticeboard.html b/templates/mod/noticeboard.html
new file mode 100644
index 00000000..463b8430
--- /dev/null
+++ b/templates/mod/noticeboard.html
@@ -0,0 +1,65 @@
+{% if mod|hasPermission(config.mod.noticeboard_post) %}
+ <fieldset>
+ <legend>{% trans 'New post' %}</legend>
+ <form style="margin:0" action="" method="post">
+ <table>
+ <tr>
+ <th>{% trans 'Name' %}</th>
+ <td>{{ mod.username|e }}</td>
+ </tr>
+ <tr>
+ <th><label for="subject">{% trans 'Subject' %}</label></th>
+ <td><input type="text" size="55" name="subject" id="subject" /></td>
+ </tr>
+ <tr>
+ <th>{% trans 'Body' %}</th>
+ <td><textarea name="body" style="width:100%;height:100px"></textarea></td>
+ </tr>
+ </table>
+ <p style="text-align:center">
+ <input type="submit" value="{% trans 'Post to noticeboard' %}" />
+ </p>
+ </form>
+ </fieldset>
+{% endif %}
+
+{% for post in noticeboard %}
+ <div class="ban">
+ {% if mod|hasPermission(config.mod.noticeboard_delete) %}
+ <span style="float:right;padding:2px">
+ <a class="unimportant" href="?/noticeboard/delete/{{ post.id }}">[{% trans 'delete' %}]</a>
+ </span>
+ {% endif %}
+ <h2 id="{{ post.id }}">
+ <small class="unimportant">
+ <a href="#{{ post.id }}">#</a>
+ </small>
+ {% if post.subject %}
+ {{ post.subject|e }}
+ {% else %}
+ <em>{% trans 'no subject' %}</em>
+ {% endif %}
+ <small class="unimportant">
+ &mdash; {% trans 'by' %}
+ {% if post.username %}
+ {{ post.username|e }}
+ {% else %}
+ <em>{% trans 'deleted?' %}</em>
+ {% endif %}
+ {% trans 'at' %}
+ {{ post.time|date(config.post_date) }}
+ </small>
+ </h2>
+ <p>
+ {{ post.body }}
+ </p>
+ </div>
+{% endfor %}
+
+{% if count > noticeboard|count %}
+ <p class="unimportant" style="text-align:center;word-wrap:break-word">
+ {% for i in range(0, (count - 1) / config.mod.noticeboard_page) %}
+ <a href="?/noticeboard/{{ i + 1 }}">[{{ i + 1 }}]</a>
+ {% endfor %}
+ </p>
+{% endif %}
diff --git a/templates/mod/pm.html b/templates/mod/pm.html
new file mode 100644
index 00000000..c62cae58
--- /dev/null
+++ b/templates/mod/pm.html
@@ -0,0 +1,44 @@
+<form action="" method="post">
+ <table>
+ <tr>
+ <th>{% trans 'From' %}</th>
+ {% if username %}
+ <td><a href="?/new_PM/{{ username|e }}">{{ username|e }}</a></td>
+ {% else %}
+ <td><em>{% trans 'deleted?' %}</em></td>
+ {% endif %}
+ </tr>
+ {% if to != mod.id %}
+ <tr>
+ <th>To</th>
+ {% if to_username %}
+ <td><a href="?/new_PM/{{ to_username|e }}">{{ to_username|e }}</a></td>
+ {% else %}
+ <td><em>{% trans 'deleted?' %}</em></td>
+ {% endif %}
+ </tr>
+ {% endif %}
+ <tr>
+ <th>{% trans 'Date' %}</th>
+ <td>{{ time|date(config.post_date) }} <small>({{ time|ago }} ago)</small></td>
+
+ </tr>
+ <tr>
+ <th>{% trans 'Message' %}</th>
+ <td>{{ message }}</td>
+ </tr>
+ </table>
+
+ <ul style="list-style:none;text-align:center;padding:0">
+ <li style="padding:5px 0">
+ <input type="submit" name="delete" value="{% trans 'Delete forever' %}">
+ </li>
+ {% if mod|hasPermission(config.mod.create_pm) %}
+ <li style="padding:5px 0">
+ <a href="?/PM/{{ id }}/reply">
+ {% trans 'Reply with quote' %}
+ </a>
+ </li>
+ {% endif %}
+ </ul>
+</form>
diff --git a/templates/mod/rebuild.html b/templates/mod/rebuild.html
new file mode 100644
index 00000000..7c6b28ba
--- /dev/null
+++ b/templates/mod/rebuild.html
@@ -0,0 +1,71 @@
+<form style="width:300px;margin:auto" action="?/rebuild" method="post">
+ <ul id="rebuild">
+ <li style="margin-bottom:8px">
+ <input type="checkbox" name="rebuild_all" id="rebuild_all" onchange="toggleall(this.checked)">
+ <label for="rebuild_all"><strong>{% trans 'Toggle all' %}</strong></label>
+ <script>
+ function toggleall(val) {
+ /* TODO: something more suitable for all browsers? */
+ var elements = document.getElementById('rebuild').querySelectorAll('input');
+ for (i in elements) {
+ elements[i].checked = val;
+ }
+ }
+ </script>
+ </li>
+ <li>
+ <input type="checkbox" name="rebuild_cache" id="rebuild_cache" checked>
+ <label for="rebuild_cache">{% trans 'Flush cache' %}</label>
+ </li>
+ <li>
+ <input type="checkbox" name="rebuild_javascript" id="rebuild_javascript" checked>
+ <label for="rebuild_javascript">{% trans 'Rebuild Javascript' %}</label>
+ </li>
+ <li>
+ <input type="checkbox" name="rebuild_index" id="rebuild_index" checked>
+ <label for="rebuild_index">{% trans 'Rebuild index pages' %}</label>
+ </li>
+ <li>
+ <input type="checkbox" name="rebuild_thread" id="rebuild_thread" checked>
+ <label for="rebuild_thread">{% trans 'Rebuild thread pages' %}</label>
+ </li>
+ <li>
+ <input type="checkbox" name="rebuild_themes" id="rebuild_themes" checked>
+ <label for="rebuild_themes">{% trans 'Rebuild themes' %}</label>
+ </li>
+ <li>
+ <input type="checkbox" name="rebuild_posts" id="rebuild_posts">
+ <label for="rebuild_posts">{% trans 'Rebuild replies' %}</label>
+ </li>
+ </ul>
+
+ <hr>
+
+ <ul id="boards">
+ <li style="margin-bottom:8px">
+ <input type="checkbox" name="boards_all" id="boards_all" onchange="toggleallboards(this.checked)" checked>
+ <label for="boards_all"><strong>{% trans 'All boards' %}</strong></label>
+ <script>
+ function toggleallboards(val) {
+ /* TODO: something more suitable for all browsers? */
+ var elements = document.getElementById('boards').querySelectorAll('input');
+ for (i in elements) {
+ elements[i].checked = val;
+ }
+ }
+ </script>
+ </li>
+ {% for board in boards %}
+ <li>
+ <input type="checkbox" name="board_{{ board.uri }}" id="board-{{ board.uri }}" checked>
+ <label for="board-{{ board.uri }}">
+ {{ config.board_abbreviation|sprintf(board.uri) }} - {{ board.title|e }}
+ </label>
+ </li>
+ {% endfor %}
+ </ul>
+
+ <p style="text-align:center">
+ <input type="submit" value="{% trans 'Rebuild' %}" name="rebuild">
+ </p>
+</form>
diff --git a/templates/mod/rebuilt.html b/templates/mod/rebuilt.html
new file mode 100644
index 00000000..57d16fff
--- /dev/null
+++ b/templates/mod/rebuilt.html
@@ -0,0 +1,12 @@
+<div class="ban">
+ <h2>{% trans 'Rebuilt' %}</h2>
+ <ul>
+ {% for log in logs %}
+ <li>{{ log }}</li>
+ {% endfor %}
+ </ul>
+ <p>
+ <a href="?/rebuild">{% trans 'Go back and rebuild again' %}</a>.
+ </p>
+</div>
+
diff --git a/templates/mod/report.html b/templates/mod/report.html
new file mode 100644
index 00000000..9c8463ed
--- /dev/null
+++ b/templates/mod/report.html
@@ -0,0 +1,26 @@
+<div class="report">
+ <hr>
+ {% trans 'Board' %}: <a href="?/{{ report.board }}/{{ config.file_index }}">{{ config.board_abbreviation|sprintf(report.board) }}</a>
+ <br>
+ {% trans 'Reason' %}: {{ report.reason }}
+ <br>
+ {% trans 'Report date' %}: {{ report.time|date(config.post_date) }}
+ <br>
+ {% if mod|hasPermission(config.mod.show_ip, report.board) %}
+ {% trans 'Reported by' %}: <a href="?/IP/{{ report.ip }}">{{ report.ip }}</a>
+ <br>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.report_dismiss, report.board) or mod|hasPermission(config.mod.report_dismiss_ip, report.board) %}
+ <hr>
+ {% if mod|hasPermission(config.mod.report_dismiss, report.board) %}
+ <a title="{% trans 'Discard abuse report' %}" href="?/reports/{{ report.id }}/dismiss">Dismiss</a>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.report_dismiss_ip, report.board) %}
+ {% if mod|hasPermission(config.mod.report_dismiss, report.board) %}
+ |
+ {% endif %}
+ <a title="{% trans 'Discard all abuse reports by this IP address' %}" href="?/reports/{{ report.id }}/dismissall">Dismiss+</a>
+ {% endif %}
+ {% endif %}
+</div>
+
diff --git a/templates/mod/reports.html b/templates/mod/reports.html
new file mode 100644
index 00000000..26bceacc
--- /dev/null
+++ b/templates/mod/reports.html
@@ -0,0 +1,6 @@
+{% if reports %}
+ {{ reports }}
+{% else %}
+ <p style="text-align:center" class="unimportant">({% trans 'There are no reports.' %})</p>
+{% endif %}
+
diff --git a/templates/mod/theme_config.html b/templates/mod/theme_config.html
new file mode 100644
index 00000000..2dbb8397
--- /dev/null
+++ b/templates/mod/theme_config.html
@@ -0,0 +1,27 @@
+<form action="" method="post">
+ {% if not config %}
+ <p style="text-align:center" class="unimportant">(No configuration required.)</p>
+ {% else %}
+ <table>
+ {% for conf in theme.config %}
+ <tr>
+ <th>{{ conf.title }}</th>
+ <td>
+ <input type="text" name="{{ conf.name }}"
+ {% if settings[conf.name] %}value="{{ settings[conf.name] }}"{% else %}{% if conf.default %}value="{{ conf.default }}"{% endif %}{% endif %}
+ {% if conf.size %}
+ size="{{ conf.size }}"
+ {% endif %}
+ />
+ {% if conf.comment %}
+ <span class="unimportant">{{ conf.comment }}</span>
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ {% endif %}
+ <p style="text-align:center">
+ <input name="install" type="submit" value="{% trans 'Install theme' %}" />
+ </p>
+</form>
diff --git a/templates/mod/theme_installed.html b/templates/mod/theme_installed.html
new file mode 100644
index 00000000..e6beec10
--- /dev/null
+++ b/templates/mod/theme_installed.html
@@ -0,0 +1,9 @@
+{% if message %}
+ <div style="border:1px dashed maroon;padding:20px;margin:auto;max-width:800px">{{ message }}</div>
+{% endif %}
+
+{% if result %}
+ <p style="text-align:center">{% trans 'Successfully installed and built theme.' %}</p>
+{% endif %}
+
+<p style="text-align:center"><a href="?/themes">{% trans 'Go back to themes' %}</a>.</p>
diff --git a/templates/mod/theme_rebuilt.html b/templates/mod/theme_rebuilt.html
new file mode 100644
index 00000000..b366e7a6
--- /dev/null
+++ b/templates/mod/theme_rebuilt.html
@@ -0,0 +1,2 @@
+<p style="text-align:center">{{ 'Successfully rebuilt the <strong>%s</strong> theme.'|trans|sprintf(theme_name) }}</p>
+<p style="text-align:center"><a href="?/themes">{% trans 'Go back to themes' %}</a>.</p>
diff --git a/templates/mod/themes.html b/templates/mod/themes.html
new file mode 100644
index 00000000..b596826d
--- /dev/null
+++ b/templates/mod/themes.html
@@ -0,0 +1,40 @@
+{% if themes|count == 0 %}
+ <p style="text-align:center" class="unimportant">({% trans 'There are no themes available.' %})</p>
+{% else %}
+ <table class="modlog">
+ {% for theme_name, theme in themes %}
+ <tr>
+ <th class="minimal">{% trans 'Name' %}</th>
+ <td>{{ theme.name }}</td>
+ </tr>
+ <tr>
+ <th class="minimal">{% trans 'Version' %}</th>
+ <td>{{ theme.version }}</td>
+ </tr>
+ <tr>
+ <th class="minimal">{% trans 'Description' %}</th>
+ <td>{{ theme.description }}</td>
+ </tr>
+ <tr>
+ <th class="minimal">{% trans 'Thumbnail' %}</th>
+ <td>
+ <img style="float:none;margin:4px{% if theme_name in themes_in_use %};border:2px solid red;padding:4px{% endif %}" src="{{ config.dir.themes_uri }}/{{ theme_name }}/thumb.png" />
+ </td>
+ </tr>
+ <tr>
+ <th class="minimal">{% trans 'Actions' %}</th>
+ <td><ul style="padding:0 20px">
+ <li><a title=" {% trans 'Use theme' %}" href="?/themes/{{ theme_name }}">
+ {% if theme_name in themes_in_use %}{% trans 'Reconfigure' %}{% else %}{% trans 'Install' %}{% endif %}
+ </a></li>
+ {% if theme_name in themes_in_use %}
+ <li><a href="?/themes/{{ theme_name }}/rebuild">{% trans 'Rebuild' %}</a></li>
+ <li><a href="?/themes/{{ theme_name }}/uninstall" onclick="return confirm('Are you sure you want to uninstall this theme?');">{% trans 'Uninstall' %}</a></li>
+ {% endif %}
+ </ul></td>
+ </tr>
+ <tr style="height:40px"><td colspan="2"><hr/></td></tr>
+ </tr>
+ {% endfor %}
+ </table>
+{% endif %}
diff --git a/templates/mod/user.html b/templates/mod/user.html
new file mode 100644
index 00000000..3c4b89cf
--- /dev/null
+++ b/templates/mod/user.html
@@ -0,0 +1,125 @@
+{% if new %}
+ {% set action = '?/users/new' %}
+{% else %}
+ {% set action = '?/users/' ~ user.id %}
+{% endif %}
+
+<form action="{{ action }}" method="post">
+ <table>
+ <tr>
+ <th>{% trans 'Username' %}</th>
+ <td>
+ {% if new or mod|hasPermission(config.mod.editusers) %}
+ <input size="20" maxlength="30" type="text" name="username" value="{{ user.username|e }}" autocomplete="off">
+ {% else %}
+ {{ user.username|e }}
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>{% trans 'Password' %}{% if not new %} <small style="font-weight:normal">({% trans 'new; optional' %})</small>{% endif %}</th>
+ <td>
+ {% if new or (mod|hasPermission(config.mod.editusers) or (mod|hasPermission(config.mod.change_password) and user.id == mod.id)) %}
+ <input size="20" maxlength="30" type="password" name="password" value="" autocomplete="off">
+ {% else %}
+ -
+ {% endif %}
+ </td>
+ </tr>
+ {% if new %}
+ <tr>
+ <th>{% trans 'Class' %}</th>
+ <td>
+ <ul style="padding:5px 8px;list-style:none">
+ <li>
+ <input type="radio" name="type" id="janitor" value="{{ constant('JANITOR') }}">
+ <label for="janitor">{% trans 'Janitor' %}</label>
+ </li>
+ <li>
+ <input type="radio" name="type" id="mod" value="{{ constant('MOD') }}" checked>
+ <label for="mod">{% trans 'Mod' %}</label>
+ </li>
+ <li>
+ <input type="radio" name="type" id="admin" value="{{ constant('Admin') }}">
+ <label for="admin">{% trans 'Admin' %}</label>
+ </li>
+ </ul>
+ </td>
+ </tr>
+ {% endif %}
+ <tr>
+ <th>{% trans 'Boards' %}</th>
+ <td>
+ <ul style="padding:0 5px;list-style:none">
+ <li>
+ <input type="checkbox" id="allboards" name="allboards"
+ {% if '*' in user.boards %} checked{% endif %}
+ {% if not mod|hasPermission(config.mod.editusers) %}
+ disabled
+ {% endif %}
+ >
+ <label for="allboards">"*" - {% trans 'All boards' %}</label>
+ </li>
+ {% for board in boards %}
+ <li>
+ <input type="checkbox" id="board_{{ board.uri }}" name="board_{{ board.uri }}"
+ {% if board.uri in user.boards %} checked{% endif %}
+ {% if not mod|hasPermission(config.mod.editusers) %}
+ disabled
+ {% endif %}
+ >
+ <label for="board_{{ board.uri }}">
+ {{ config.board_abbreviation|sprintf(board.uri) }}
+ -
+ {{ board.title|e }}
+ </label>
+ </li>
+ {% endfor %}
+ </ul>
+ </td>
+ </tr>
+ </table>
+
+ <ul style="padding:0;text-align:center;list-style:none">
+ {% if new %}
+ <li><input type="submit" value="{% trans 'Create user' %}"></li>
+ {% else %}
+ <li><input type="submit" value="{% trans 'Save changes' %}"></li>
+ {% if mod|hasPermission(config.mod.deleteusers) %}
+ <li><input name="delete" onclick="return confirm('Are you sure you want to permanently delete this user?');" type="submit" value="{% trans 'Delete user' %}"></li>
+ {% endif %}
+ {% endif %}
+ </ul>
+</form>
+
+{% if logs|count > 0 %}
+ <table class="modlog" style="width:600px">
+ <tr>
+ <th>{% trans 'IP address' %}</th>
+ <th>{% trans 'Time' %}</th>
+ <th>{% trans 'Board' %}</th>
+ <th>{% trans 'Action' %}</th>
+ </tr>
+ {% for log in logs %}
+ <tr>
+ <td class="minimal">
+ <a href="?/IP/{{ log.ip }}">{{ log.ip }}</a>
+ </td>
+ <td class="minimal">
+ <span title="{{ log.time|date(config.post_date) }}">{{ log.time|ago }}</span>
+ </td>
+ <td class="minimal">
+ {% if log.board %}
+ <a href="?/{{ config.board_path|sprintf(log.board) }}{{ config.file_index }}">{{ config.board_abbreviation|sprintf(log.board) }}</a>
+ {% else %}
+ -
+ {% endif %}
+ </td>
+ <td>
+ {{ log.text }}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+{% endif %}
+
diff --git a/templates/mod/users.html b/templates/mod/users.html
new file mode 100644
index 00000000..6ea6248f
--- /dev/null
+++ b/templates/mod/users.html
@@ -0,0 +1,71 @@
+<table class="modlog" style="width:auto">
+ <tr>
+ <th>{% trans 'ID' %}</th>
+ <th>{% trans 'Username' %}</th>
+ <th>{% trans 'Type' %}</th>
+ <th>{% trans 'Boards' %}</th>
+ {% if mod|hasPermission(config.mod.modlog) %}
+ <th>{% trans 'Last action' %}</th>
+ {% endif %}
+ <th>&hellip;</th>
+ </tr>
+
+ {% for user in users %}
+ <tr>
+ <td><small>{{ user.id }}</small></td>
+ <td>{{ user.username|e }}</td>
+ <td>
+ {% if user.type == constant('JANITOR') %}{% trans 'Janitor' %}
+ {% elseif user.type == constant('MOD') %}{% trans 'Mod' %}
+ {% elseif user.type == constant('ADMIN') %}{% trans 'Admin' %}
+ {% endif %}
+ </td>
+ <td>
+ {% if user.boards == '' %}
+ <em>{% trans 'none' %}</em>
+ {% elseif user.boards == '*' %}
+ <em>{% trans 'all boards' %}</em>
+ {% else %}
+ {# This is really messy, but IMO it beats doing it in PHP. #}
+ {% set boards = user.boards|split(',') %}
+ {% set _boards = [] %}
+ {% for board in boards %}
+ {% set _boards = _boards|push(board == '*' ? '*' : config.board_abbreviation|sprintf(board)) %}
+ {% endfor %}
+ {% set _boards = _boards|sort %}
+ {{ _boards|join(', ') }}
+ {% endif %}
+ </td>
+ {% if mod|hasPermission(config.mod.modlog) %}
+ <td>
+ {% if user.last %}
+ <span title="{{ user.action|e }}">{{ user.last|ago }}</span>
+ {% else %}
+ <em>{% trans 'never' %}</em>
+ {% endif %}
+ </td>
+ {% endif %}
+ <td>
+ {% if mod|hasPermission(config.mod.promoteusers) and user.type < constant('ADMIN') %}
+ <a style="float:left;text-decoration:none" href="?/users/{{ user.id }}/promote" title="{% trans 'Promote' %}">&#9650;</a>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.promoteusers) and user.type > constant('JANITOR') %}
+ <a style="float:left;text-decoration:none" href="?/users/{{ user.id }}/demote" title="{% trans 'Demote' %}">&#9660;</a>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.editusers) or (mod|hasPermission(config.mod.change_password) and mod.id == user.id) %}
+ <a class="unimportant" style="margin-left:5px;float:right" href="?/users/{{ user.id }}">[{% trans 'edit' %}]</a>
+ {% endif %}
+ {% if mod|hasPermission(config.mod.create_pm) %}
+ <a class="unimportant" style="margin-left:5px;float:right" href="?/new_PM/{{ user.username|e }}">[{% trans 'PM' %}]</a>
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+</table>
+
+{% if mod|hasPermission(config.mod.createusers) %}
+ <p style="text-align:center">
+ <a href="?/users/new">Create a new user</a>
+ </p>
+{% endif %}
+
diff --git a/templates/mod/view_ip.html b/templates/mod/view_ip.html
new file mode 100644
index 00000000..c49880ae
--- /dev/null
+++ b/templates/mod/view_ip.html
@@ -0,0 +1,163 @@
+{% for board_posts in posts %}
+ <fieldset>
+ <legend>
+ <a href="?/{{ config.board_path|sprintf(board_posts.board.uri) }}{{ config.file_index }}">
+ {{ config.board_abbreviation|sprintf(board_posts.board.uri) }}
+ -
+ {{ board_posts.board.title|e }}
+ </a>
+ </legend>
+ {{ board_posts.posts|join('<hr>') }}
+ </fieldset>
+{% endfor %}
+
+{% if mod|hasPermission(config.mod.view_notes) %}
+ <fieldset id="notes">
+ <legend>
+ {% set notes_on_record = 'note' ~ (notes|count != 1 ? 's' : '') ~ ' on record' %}
+ <legend>{{ notes|count }} {% trans notes_on_record %}</legend>
+ </legend>
+
+ {% if notes|count > 0 %}
+ <table class="modlog">
+ <tr>
+ <th>{% trans 'Staff' %}</th>
+ <th>{% trans 'Note' %}</th>
+ <th>{% trans 'Date' %}</th>
+ {% if mod|hasPermission(config.mod.remove_notes) %}
+ <th>{% trans 'Actions' %}</th>
+ {% endif %}
+ </tr>
+ {% for note in notes %}
+ <tr>
+ <td class="minimal">
+ {% if note.username %}
+ <a href="?/new_PM/{{ note.username|e }}">{{ note.username|e }}</a>
+ {% else %}
+ <em>{% trans 'deleted?' %}</em>
+ {% endif %}
+ </td>
+ <td>
+ {{ note.body }}
+ </td>
+ <td class="minimal">
+ {{ note.time|date(config.post_date) }}
+ </td>
+ {% if mod|hasPermission(config.mod.remove_notes) %}
+ <td class="minimal">
+ <a href="?/IP/{{ ip }}/remove_note/{{ note.id }}">
+ <small>[{% trans 'remove' %}]</small>
+ </a>
+ </td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </table>
+ {% endif %}
+
+ {% if mod|hasPermission(config.mod.create_notes) %}
+ <form action="" method="post" style="margin:0">
+ <table>
+ <tr>
+ <th>{% trans 'Staff' %}</th>
+ <td>{{ mod.username|e }}</td>
+ </tr>
+ <tr>
+ <th>
+ <label for="note">{% trans 'Note' %}</label>
+ </th>
+ <td>
+ <textarea id="note" name="note" rows="5" cols="30"></textarea>
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td><input type="submit" value="{% trans 'New note' %}"></td>
+ </tr>
+ </table>
+ </form>
+ {% endif %}
+ </fieldset>
+{% endif %}
+
+{% if bans|count > 0 and mod|hasPermission(config.mod.view_ban) %}
+ <fieldset id="bans">
+ {% set bans_on_record = 'ban' ~ (bans|count != 1 ? 's' : '') ~ ' on record' %}
+ <legend>{{ bans|count }} {% trans bans_on_record %}</legend>
+
+ {% for ban in bans %}
+ <form action="" method="post" style="text-align:center">
+ <table style="width:400px;margin-bottom:10px;border-bottom:1px solid #ddd;padding:5px">
+ <tr>
+ <th>{% trans 'Status' %}</th>
+ <td>
+ {% if config.mod.view_banexpired and ban.expires != 0 and ban.expires < time() %}
+ {% trans 'Expired' %}
+ {% else %}
+ {% trans 'Active' %}
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>{% trans 'IP' %}</th>
+ <td>{{ ban.ip }}</td>
+ </tr>
+ <tr>
+ <th>{% trans 'Reason' %}</th>
+ <td>
+ {% if ban.reason %}
+ {{ ban.reason }}
+ {% else %}
+ <em>{% trans 'no reason' %}</em>
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>{% trans 'Board' %}</th>
+ <td>
+ {% if ban.board %}
+ {{ config.board_abbreviation|sprintf(ban.board) }}
+ {% else %}
+ <em>{% trans 'all boards' %}</em>
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>{% trans 'Set' %}</th>
+ <td>{{ ban.set|date(config.post_date) }}</td>
+ </tr>
+ <tr>
+ <th>{% trans 'Expires' %}</th>
+ <td>
+ {% if ban.expires %}
+ {{ ban.expires|date(config.post_date) }}
+ {% else %}
+ <em>{% trans 'never' %}</em>
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>{% trans 'Staff' %}</th>
+ <td>
+ {% if ban.username %}
+ {{ ban.username|e }}
+ {% else %}
+ <em>{% trans 'deleted?' %}</em>
+ {% endif %}
+ </td>
+ </tr>
+ </table>
+ <input type="hidden" name="ban_id" value="{{ ban.id }}">
+ <input type="submit" name="unban" value="{% trans 'Remove ban' %}">
+ </form>
+ {% endfor %}
+ </fieldset>
+{% endif %}
+
+{% if mod|hasPermission(config.mod.ban) %}
+ <fieldset>
+ <legend>{% trans 'New ban' %}</legend>
+ {% set redirect = '?/IP/' ~ ip ~ '#bans' %}
+ {% include 'mod/ban_form.html' %}
+ </fieldset>
+{% endif %}