Added load and save. Save works, load doesn't (yet).

This commit is contained in:
simon 2014-08-16 21:34:26 +01:00
parent 34d3745ecb
commit ab01606c5c
8 changed files with 139 additions and 56 deletions

View file

@ -37,7 +37,7 @@ body {
#nav:hover #nav-menu { #nav:hover #nav-menu {
display: inline; display: inline;
} }
#nav-icon { #nav-icon {
padding: 0.25em; padding: 0.25em;
} }
@ -52,7 +52,7 @@ body {
display: inline; display: inline;
} }
#nav ul li a { #nav ul li a {
color: white; color: white;
text-decoration: none; text-decoration: none;
font-weight: bold; font-weight: bold;
@ -68,6 +68,12 @@ li.nav-item a:active { background: gray; color: white; }
color: white; color: white;
} }
/* there isn't enough room on a phone display for optional elements, and
load/save isn't going to work on a phone anyway */
.nav-optional {
display: none;
}
.widget { .widget {
margin: 0; margin: 0;
padding: 0.25em 1em; padding: 0.25em 1em;

View file

@ -6,7 +6,7 @@ body {
/* Overall container div, holds all content of page. Yes, I know it shouldn't have fixed width */ /* Overall container div, holds all content of page. Yes, I know it shouldn't have fixed width */
#main-container{ #main-container{
clear: both; clear: both;
width:100%; /* width:100%; */
} }
/* footer of the document */ /* footer of the document */
@ -54,7 +54,7 @@ body {
display: inline; display: inline;
} }
#nav ul li a { #nav ul li a {
color: white; color: white;
text-decoration: none; text-decoration: none;
font-weight: bold; font-weight: bold;

View file

@ -53,7 +53,7 @@ body {
#nav:hover #nav-menu { #nav:hover #nav-menu {
display: inline; display: inline;
} }
#nav-icon { #nav-icon {
padding: 0.25em; padding: 0.25em;
} }
@ -68,7 +68,7 @@ body {
display: inline; display: inline;
} }
#nav ul li a { #nav ul li a {
color: white; color: white;
text-decoration: none; text-decoration: none;
font-weight: bold; font-weight: bold;
@ -84,6 +84,12 @@ li.nav-item a:active { background: gray; color: white; }
color: white; color: white;
} }
/* there isn't enough room on a tablet display for optional elements, and
load/save isn't going to work on a tablet anyway */
.nav-optional {
display: none;
}
.widget { .widget {
margin: 0; margin: 0;
padding: 0.25em 1em; padding: 0.25em 1em;

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

View file

@ -23,9 +23,11 @@
<img id="nav-icon" src="{{servlet-context}}/img/threelines.png" alt="Menu"/> <img id="nav-icon" src="{{servlet-context}}/img/threelines.png" alt="Menu"/>
<ul id="nav-menu" class="nav"> <ul id="nav-menu" class="nav">
<li class="{{home-selected}}"><a href="{{servlet-context}}/">Home</a></li> <li class="{{home-selected}}"><a href="{{servlet-context}}/">Home</a></li>
<li class="{{world-selected}}"><a href="{{servlet-context}}/world">World</a></li>
<li class="{{params-selected}}"><a href="{{servlet-context}}/params">Parameters</a></li> <li class="{{params-selected}}"><a href="{{servlet-context}}/params">Parameters</a></li>
<li class="{{rules-selected}}"><a href="{{servlet-context}}/rules">Rules</a></li> <li class="{{rules-selected}}"><a href="{{servlet-context}}/rules">Rules</a></li>
<li class="{{world-selected}}"><a href="{{servlet-context}}/world">World</a></li> <li class="{{save-selected}} nav-optional"><a href="{{servlet-context}}/saved-map.mwm">Save</a></li>
<li class="{{load-selected}} nav-optional"><a href="{{servlet-context}}/load">Load</a></li>
<li class="{{about-selected}}"><a href="{{servlet-context}}/about">About</a></li> <li class="{{about-selected}}"><a href="{{servlet-context}}/about">About</a></li>
<li class="{{docs-selected}}"><a href="{{servlet-context}}/docs">Documentation</a></li> <li class="{{docs-selected}}"><a href="{{servlet-context}}/docs">Documentation</a></li>
</ul> </ul>
@ -37,12 +39,12 @@
<div id="main-container" class="container"> <div id="main-container" class="container">
{% if message %} {% if message %}
<div id="announcement"> <div id="message">
<p class="message">{{message}}</p> <p class="message">{{message}}</p>
</div> </div>
{% endif %} {% endif %}
{% if error %} {% if error %}
<div id="announcement"> <div id="error">
<p class="error">{{error}}</p> <p class="error">{{error}}</p>
</div> </div>
{% endif %} {% endif %}

View file

@ -1,21 +1,48 @@
(ns mw-ui.routes.home (ns mw-ui.routes.home
(:use clojure.walk (:use clojure.walk
compojure.core compojure.core)
[mw-engine.utils :as engine-utils] (:require [clojure.pprint :only [pprint]]
[mw-ui.routes.rules :as rules] [hiccup.core :refer [html]]
[mw-ui.routes.params :as params]) [mw-engine.utils :as engine-utils]
(:require [hiccup.core :refer [html]]
[mw-ui.layout :as layout] [mw-ui.layout :as layout]
[mw-ui.util :as util]
[mw-ui.render-world :as world] [mw-ui.render-world :as world]
[mw-ui.routes.load :as load]
[mw-ui.routes.rules :as rules]
[mw-ui.routes.params :as params]
[mw-ui.routes.save :as save]
[mw-ui.util :as util]
[noir.io :as io]
[noir.session :as session] [noir.session :as session]
[ring.util.response :as response])) [ring.util.response :as response]))
(defn list-states []
(sort
(filter #(not (nil? %))
(map #(first (rest (re-matches #"([0-9a-z-]+).png" (.getName %))))
(file-seq (clojure.java.io/file "resources/public/img/tiles"))))))
(defn about-page []
(layout/render "trusted-content.html"
{:title "About MicroWorld"
:about-selected "active"
:content (util/md->html "/md/about.md")}))
(defn docs-page []
(layout/render "docs.html" {:title "Documentation"
:parser (util/md->html "/md/mw-parser.md" )
:states (util/list-resources "/img/tiles" #"([0-9a-z-_]+).png")
:lessons (util/list-resources "/md/lesson-plans" #"([0-9a-z-_]+).md")
:components ["mw-engine" "mw-parser" "mw-ui"]}))
(defn home-page [] (defn home-page []
(layout/render "trusted-content.html" {:title "Welcome to MicroWorld" "Render the home page."
(layout/render "trusted-content.html" {:title "Welcome to MicroWorld"
:content (util/md->html "/md/mw-ui.md")})) :content (util/md->html "/md/mw-ui.md")}))
(defn inspect-page [request] (defn inspect-page [request]
"Open an inspector on the cell at the co-ordinates specified in this request"
(let [params (keywordize-keys (:params request)) (let [params (keywordize-keys (:params request))
xs (:x params) xs (:x params)
ys (:y params) ys (:y params)
@ -35,53 +62,41 @@
:cell cell :cell cell
:x (:x cell) :x (:x cell)
:y (:y cell) :y (:y cell)
:states (util/list-resources :states (util/list-resources
"/img/tiles" #"([0-9a-z-_]+).png")})))) "/img/tiles" #"([0-9a-z-_]+).png")}))))
(defn world-page []
(layout/render "trusted-content.html"
{:title "Watch your world grow"
:world-selected "active"
:content (html (world/render-world-table))
:pause (or (session/get :pause) 5)
:maybe-refresh "refresh"}))
(defn about-page [] (defn md-page
(layout/render "trusted-content.html" "Render the markdown page specified in this request, if any. Probably undesirable,
{:title "About MicroWorld" should be removed."
:about-selected "active" [request]
:content (util/md->html "/md/about.md")}))
(defn md-page [request]
(let [params (keywordize-keys (:params request)) (let [params (keywordize-keys (:params request))
content (or (:content params) "missing.md")] content (or (:content params) "missing.md")]
(layout/render "trusted-content.html" (layout/render "trusted-content.html"
{:title "Welcome to MicroWorld" {:title "Welcome to MicroWorld"
:content (util/md->html (str "/md/" content))}))) :content (util/md->html (str "/md/" content))})))
(defn list-states [] (defn world-page []
(sort "Render the world in the current session (or a default one if none)."
(filter #(not (nil? %)) (layout/render "trusted-content.html"
(map #(first (rest (re-matches #"([0-9a-z-]+).png" (.getName %)))) {:title "Watch your world grow"
(file-seq (clojure.java.io/file "resources/public/img/tiles")))))) :world-selected "active"
:content (html (world/render-world-table))
(defn docs-page [] :pause (or (session/get :pause) 5)
(layout/render "docs.html" {:title "Documentation" :maybe-refresh "refresh"}))
:parser (util/md->html "/md/mw-parser.md" )
:states (util/list-resources "/img/tiles" #"([0-9a-z-_]+).png")
:lessons (util/list-resources "/md/lesson-plans" #"([0-9a-z-_]+).md")
:components ["mw-engine" "mw-parser" "mw-ui"]}))
(defroutes home-routes (defroutes home-routes
(GET "/" [] (home-page)) (GET "/" [] (home-page))
(GET "/about" [] (about-page)) (GET "/about" [] (about-page))
(GET "/docs" [] (docs-page)) (GET "/docs" [] (docs-page))
(GET "/world" [] (world-page)) (GET "/inspect" request (inspect-page request))
(GET "/params" [] (params/params-page))
(GET "/md" request (md-page request))
(POST "/params" request (params/params-page request))
(GET "/rules" request (rules/rules-page request))
(POST "/rules" request (rules/rules-page request))
(GET "/inspect" request (inspect-page request))
(POST "/inspect" request (inspect-page request)) (POST "/inspect" request (inspect-page request))
(GET "/load" [] (load/load-page))
(POST "/load" request (load/load-page request))
(GET "/md" request (md-page request))
(GET "/params" [] (params/params-page))
(POST "/params" request (params/params-page request))
(GET "/rules" request (rules/rules-page request))
(POST "/rules" request (rules/rules-page request))
(GET "/saved-map.mwm" [] (save/save-page))
(GET "/world" [] (world-page))
) )

39
src/mw_ui/routes/load.clj Normal file
View file

@ -0,0 +1,39 @@
(ns mw-ui.routes.load
(:use clojure.walk
compojure.core)
(:require [hiccup.core :refer [html]]
[noir.io :as io]
[noir.session :as session]
[ring.util.response :as response]))
(defn- upload [file]
(io/upload-file "/tmp/" file)
(cond
(session/put! :world
(with-open [eddi (java.io.FileReader. (:tempfile file))] (read)))
(str "Successfully loaded your world from " (:filename file))))
(defn load-page
"If no args, show the load form; with args, load a world file from the client.
*NOTE* that this reads a Clojure form from an untrusted client and should almost
certainly NOT be enabled on a public-facing site, especially not on the Internet.
*TODO* doesn't work yet."
([]
(load-page nil))
([request]
(let [params (keywordize-keys (:params request))
file (:file request)]
(try
(layout/render "load.html"
{:title "Load World"
:message (upload file)})
(catch Exception any
(layout/render "load.html"
{:title "Load World"
:message "Failed to load your world"
:error (str (.getName (.getClass any)) ": " (.getMessage any))}))))))

15
src/mw_ui/routes/save.clj Normal file
View file

@ -0,0 +1,15 @@
(ns mw-ui.routes.save
(:require [clojure.pprint :as pretty :only [pprint]]
[noir.session :as session]
[ring.util.response :as response]))
(defn save-page []
"Save the current world to the browser, using our own custom mime-type in
an attempt to prevent the browser trying to do anything clever with it.
Note that it is saved as a raw Clojure data structure, not as XML or
any proprietary format."
(response/header
(response/response
(with-out-str (pretty/pprint (session/get :world))))
"Content-Type" "application/journeyman-mwm; charset=utf-8"))