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, "Smeagol has been unable to find some of the resources on which it depends,
possibly because of misconfiguration or missing environment variables." possibly because of misconfiguration or missing environment variables."
;; used in sanity check report ;; 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" :user-lacks-field "User record in the passwd file lacks a field"
;; used in sanity check report ;; used in sanity check report
:username-prompt "Username" ;; text of the username widget prompt on edit user page :username-prompt "Username" ;; text of the username widget prompt on edit user page

View file

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

View file

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

View file

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

View file

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

View file

@ -2,6 +2,7 @@
:author "Simon Brooke"} :author "Simon Brooke"}
smeagol.util smeagol.util
(:require [clojure.java.io :as cjio] (:require [clojure.java.io :as cjio]
[clojure.string :as cs]
[environ.core :refer [env]] [environ.core :refer [env]]
[me.raynes.fs :as fs] [me.raynes.fs :as fs]
[noir.io :as io] [noir.io :as io]
@ -10,7 +11,7 @@
[smeagol.authenticate :as auth] [smeagol.authenticate :as auth]
[smeagol.configuration :refer [config]] [smeagol.configuration :refer [config]]
[smeagol.formatting :refer [md->html]] [smeagol.formatting :refer [md->html]]
[taoensso.timbre :as timbre])) [taoensso.timbre :as log]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ;;;;
@ -49,6 +50,51 @@
(def upload-dir (def upload-dir
(str (cjio/file content-dir "uploads"))) (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 (defn standard-params
"Return a map of standard parameters to pass to the template renderer." "Return a map of standard parameters to pass to the template renderer."
[request] [request]
@ -69,7 +115,7 @@
messages (try messages (try
(i18n/get-messages specifier "i18n" "en-GB") (i18n/get-messages specifier "i18n" "en-GB")
(catch Exception any (catch Exception any
(timbre/error (log/error
any any
(str (str
"Failed to parse accept-language header '" "Failed to parse accept-language header '"