diff --git a/resources/public/css/phone.css b/resources/public/css/phone.css index 6b32ce8..fd3cac6 100644 --- a/resources/public/css/phone.css +++ b/resources/public/css/phone.css @@ -37,7 +37,7 @@ body { #nav:hover #nav-menu { display: inline; } - + #nav-icon { padding: 0.25em; } @@ -52,7 +52,7 @@ body { display: inline; } -#nav ul li a { +#nav ul li a { color: white; text-decoration: none; font-weight: bold; @@ -68,6 +68,12 @@ li.nav-item a:active { background: gray; 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 { margin: 0; padding: 0.25em 1em; diff --git a/resources/public/css/standard.css b/resources/public/css/standard.css index db66b45..131a881 100644 --- a/resources/public/css/standard.css +++ b/resources/public/css/standard.css @@ -6,7 +6,7 @@ body { /* Overall container div, holds all content of page. Yes, I know it shouldn't have fixed width */ #main-container{ clear: both; - width:100%; +/* width:100%; */ } /* footer of the document */ @@ -54,7 +54,7 @@ body { display: inline; } -#nav ul li a { +#nav ul li a { color: white; text-decoration: none; font-weight: bold; diff --git a/resources/public/css/tablet.css b/resources/public/css/tablet.css index 6a7e71d..f34e510 100644 --- a/resources/public/css/tablet.css +++ b/resources/public/css/tablet.css @@ -53,7 +53,7 @@ body { #nav:hover #nav-menu { display: inline; } - + #nav-icon { padding: 0.25em; } @@ -68,7 +68,7 @@ body { display: inline; } -#nav ul li a { +#nav ul li a { color: white; text-decoration: none; font-weight: bold; @@ -84,6 +84,12 @@ li.nav-item a:active { background: gray; 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 { margin: 0; padding: 0.25em 1em; diff --git a/resources/public/img/heightmaps/test.heightmap.png b/resources/public/img/heightmaps/test.heightmap.png new file mode 100644 index 0000000..0065257 Binary files /dev/null and b/resources/public/img/heightmaps/test.heightmap.png differ diff --git a/resources/templates/base.html b/resources/templates/base.html index 611a3d0..7e85c99 100644 --- a/resources/templates/base.html +++ b/resources/templates/base.html @@ -23,9 +23,11 @@ Menu @@ -37,12 +39,12 @@
{% if message %} -
+

{{message}}

{% endif %} {% if error %} -
+

{{error}}

{% endif %} diff --git a/src/mw_ui/routes/home.clj b/src/mw_ui/routes/home.clj index 18a9544..a5f5441 100644 --- a/src/mw_ui/routes/home.clj +++ b/src/mw_ui/routes/home.clj @@ -1,21 +1,48 @@ (ns mw-ui.routes.home (:use clojure.walk - compojure.core - [mw-engine.utils :as engine-utils] - [mw-ui.routes.rules :as rules] - [mw-ui.routes.params :as params]) - (:require [hiccup.core :refer [html]] + compojure.core) + (:require [clojure.pprint :only [pprint]] + [hiccup.core :refer [html]] + [mw-engine.utils :as engine-utils] [mw-ui.layout :as layout] - [mw-ui.util :as util] [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] [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 [] - (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")})) (defn inspect-page [request] + "Open an inspector on the cell at the co-ordinates specified in this request" (let [params (keywordize-keys (:params request)) xs (:x params) ys (:y params) @@ -35,53 +62,41 @@ :cell cell :x (:x cell) :y (:y cell) - :states (util/list-resources + :states (util/list-resources "/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 [] - (layout/render "trusted-content.html" - {:title "About MicroWorld" - :about-selected "active" - :content (util/md->html "/md/about.md")})) - -(defn md-page [request] +(defn md-page + "Render the markdown page specified in this request, if any. Probably undesirable, + should be removed." + [request] (let [params (keywordize-keys (:params request)) content (or (:content params) "missing.md")] - (layout/render "trusted-content.html" - {:title "Welcome to MicroWorld" + (layout/render "trusted-content.html" + {:title "Welcome to MicroWorld" :content (util/md->html (str "/md/" content))}))) -(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 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 world-page [] + "Render the world in the current session (or a default one if none)." + (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"})) (defroutes home-routes - (GET "/" [] (home-page)) - (GET "/about" [] (about-page)) - (GET "/docs" [] (docs-page)) - (GET "/world" [] (world-page)) - (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)) + (GET "/" [] (home-page)) + (GET "/about" [] (about-page)) + (GET "/docs" [] (docs-page)) + (GET "/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)) ) diff --git a/src/mw_ui/routes/load.clj b/src/mw_ui/routes/load.clj new file mode 100644 index 0000000..e3efe99 --- /dev/null +++ b/src/mw_ui/routes/load.clj @@ -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))})))))) + diff --git a/src/mw_ui/routes/save.clj b/src/mw_ui/routes/save.clj new file mode 100644 index 0000000..26f3688 --- /dev/null +++ b/src/mw_ui/routes/save.clj @@ -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")) +