These are the genuine improvements out of today

1. Table sorting
2. Fixed edit page title bugette
3. SimpleMDE working again.
This commit is contained in:
Simon Brooke 2020-02-14 16:08:17 +00:00
parent b7a7c4cfc8
commit 392a5f82ec
6 changed files with 107 additions and 44 deletions

View file

@ -131,6 +131,8 @@
"Smeagol has been unable to find some of the resources on which it depends,
possibly because of misconfiguration or missing environment variables."
;; used in sanity check report
:sortable "You can sort this table by selecting column headers"
;; used for sortable tables
:user-lacks-field "User record in the passwd file lacks a field"
;; used in sanity check report
:username-prompt "Username" ;; text of the username widget prompt on edit user page

View file

@ -1,10 +1,18 @@
{% extends "templates/base.html" %}
{% block extra-headers %}
{% script "/vendor/node_modules/tablesort/dist/tablesort.min.js" %}
{% endblock %}
{% block content %}
<div id="content">
<table>
<tr>
<th/><th>{% i18n edit-col-hdr %}</th><th>{% i18n del-col-hdr %}</th>
<p>
{% i18n sortable %}
</p>
<table id="userstable">
<tr data-sort-method='none'>
<th>{% i18n user-title-prefix %}</th>
<th data-sort-method='none'>{% i18n edit-col-hdr %}</th>
<th data-sort-method='none'>{% i18n del-col-hdr %}</th>
</tr>
{% for user in users %}
<tr>
@ -13,11 +21,12 @@
<td><a href="delete-user?target={{user}}">{% i18n del-col-hdr %} {{user}}</a></td>
</tr>
{% endfor %}
<tr>
<td><a href="edit-user">{% i18n add-user-label %}</a></td>
<td></td>
<td></td>
<tr data-sort-method='none'>
<td colspan="3"><a href="edit-user">{% i18n add-user-label %}</a></td>
</tr>
</table>
</div>
<script>
new Tablesort(document.getElementById('userstable'));
</script>
{% endblock %}

View file

@ -1,11 +1,11 @@
{% extends "templates/base.html" %}
{% block extra-headers %}
{% ifequal js-from ":cloudflare" %}
{% ifequal js-from ":cdnjs" %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/simplemde/1.11.2/simplemde.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/simplemde/1.11.2/simplemde.min.css" rel="stylesheet" type="text/css" />
{% else %}
{% style "/vendor/simplemde/dist/simplemde.min.css" %}
{% script "/vendor/simplemde/dist/simplemde.min.js" %}
{% style "vendor/simplemde/dist/simplemde.min.css" %}
{% script "vendor/simplemde/dist/simplemde.min.js" %}
{% endifequal %}
{% endblock %}

View file

@ -1,4 +1,10 @@
{% extends "templates/base.html" %}
{% block extra-headers %}
{% script "/vendor/node_modules/tablesort/dist/tablesort.min.js" %}
{% script "/vendor/node_modules/tablesort/dist/sorts/tablesort.number.min.js" %}
{% script "/vendor/node_modules/tablesort/dist/sorts/tablesort.date.min.js" %}
{% script "/vendor/node_modules/tablesort/dist/sorts/tablesort.monthname.min.js" %}
{% endblock %}
{% block content %}
<div id="content" class="list-uploads">
@ -9,12 +15,15 @@
<input name="search" id="search" type="text" value="{{search}}" required/>
</p>
</form>
<table>
<tr>
<p>
{% i18n sortable %}
</p>
<table id="uploads">
<tr data-sort-method='none'>
<th>Name</th>
<th>Uploaded</th>
<th>Type this</th>
<th>To get this</th>
<th data-sort-method='none'>To get this</th>
</tr>
{% for entry in files %}
<tr>
@ -26,9 +35,11 @@
<td>
{% if entry.is-image %} <img src="{{entry.resource}}" alt="{{entry.name|capitalize}}"/> {% else %} <a href="{{entry.resource}}">link</a> {% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
<script>
new Tablesort(document.getElementById('uploads'));
</script>
{% endblock %}

View file

@ -161,7 +161,8 @@
(log/info (format "Showing history of page '%s'" page))
(layout/render "history.html"
(merge (util/standard-params request)
{:title (util/get-message :history-title-prefix request)
{:title (str (util/get-message :history-title-prefix request)
" " page)
:page page
:history (hist/find-history repo-path file-name)}))))
@ -175,7 +176,7 @@
If `template` is supplied, use that as the formatting template as specified for
java.time.Formatter. Assumes system default timezone. Returns a string."
([^Long unix-time]
(format-instant unix-time "EEEE, dd MMMM YYYY"))
(format-instant unix-time "dd MMMM YYYY"))
([^Long unix-time ^String template]
(jt/format
(java-time/formatter template)
@ -188,8 +189,9 @@
[request]
(let
[params (keywordize-keys (:params request))
cl (count (io/resource-path))
files
(sort-by
(juxt :name (fn [x] (- 0 (count (:resource x)))))
(map
#(zipmap
[:base-name :is-image :modified :name :resource]
@ -202,19 +204,11 @@
(fs/mod-time %)
(format-instant (fs/mod-time %)))
(fs/name %)
(try
(subs (str (fs/absolute %)) cl)
(catch StringIndexOutOfBoundsException x
(log/error "Could not resolve relative path for" %
";\n resource-path is:" (io/resource-path)
";\n absolute path is:" (fs/absolute %)
";\n data-path is:" util/upload-dir
";\n content path is:" (:content-dir config))
%))])
(util/local-url %)])
(remove
#(or (cs/starts-with? (fs/name %) ".")
(fs/directory? %))
(file-seq (clojure.java.io/file util/upload-dir))))]
(file-seq (clojure.java.io/file util/upload-dir)))))]
(log/info (with-out-str (pprint files)))
(layout/render
"list-uploads.html"
@ -236,6 +230,7 @@
files)
}))))
;;;; end of list-uploads section ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn upload-page

View file

@ -2,6 +2,7 @@
:author "Simon Brooke"}
smeagol.util
(:require [clojure.java.io :as cjio]
[clojure.string :as cs]
[environ.core :refer [env]]
[me.raynes.fs :as fs]
[noir.io :as io]
@ -10,7 +11,7 @@
[smeagol.authenticate :as auth]
[smeagol.configuration :refer [config]]
[smeagol.formatting :refer [md->html]]
[taoensso.timbre :as timbre]))
[taoensso.timbre :as log]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;
@ -49,6 +50,51 @@
(def upload-dir
(str (cjio/file content-dir "uploads")))
(def local-url-base
(let [a (str (fs/absolute content-dir))]
(subs a 0 (- (count a) (count "content")))))
(defn not-servable-reason
"As a string, the reason this `file-path` cannot safely be served, or `nil`
if it is safe to serve. This reason may be logged, but should *not* be
shown to remote users, as it would allow file system probing."
[file-path]
(let [path (fs/absolute file-path)]
(cond
(cs/includes? file-path "..")
(cs/join " " file-path
"Attempts to ascend the file hierarchy are disallowed.")
(not (cs/starts-with? path local-url-base))
(cs/join " " [path "is not servable"])
(not (fs/exists? path))
(cs/join " " [path "does not exist"])
(not (fs/readable? path))
(cs/join " " [path "is not readable"]))))
(defn local-url?
"True if this `file-path` can be served as a local URL, else false."
[file-path]
(empty? (not-servable-reason file-path)))
(defn local-url
"Return a local URL for this `file-path`, or a deliberate 404 if none
can be safely served."
[file-path]
(try
(let [path (fs/absolute file-path)
problem (not-servable-reason path)]
(if
(empty? problem)
(subs (str path) (count local-url-base))
(do
(log/error
"In `smeagol.util/local-url `" file-path "` is not a servable resource.")
(str "404-not-found?path=" file-path))))
(catch Exception any
(log/error
"In `smeagol.util/local-url `" file-path "` is not a servable resource:" any)
(str "404-not-found?path=" file-path))))
(defn standard-params
"Return a map of standard parameters to pass to the template renderer."
[request]
@ -69,7 +115,7 @@
messages (try
(i18n/get-messages specifier "i18n" "en-GB")
(catch Exception any
(timbre/error
(log/error
any
(str
"Failed to parse accept-language header '"