From 50d4aa21303f6686a36e6e259914055fb98f8416 Mon Sep 17 00:00:00 2001 From: Tao Roa Lin Date: Sun, 29 Nov 2020 20:29:22 -0500 Subject: [PATCH] Middle of flight-scheduler. First commit --- .gitignore | 16 ++ .rebel_readline_history | 1 + LICENSE | 214 +++++++++++++++++++++++++ Procfile | 1 + README.md | 90 +++++++++++ env/dev/clj/seven_guis/middleware.clj | 12 ++ env/dev/clj/seven_guis/repl.clj | 33 ++++ env/dev/clj/user.clj | 11 ++ env/dev/cljs/seven_guis/dev.cljs | 15 ++ env/prod/clj/seven_guis/middleware.clj | 6 + env/prod/cljs/seven_guis/prod.cljs | 7 + project.clj | 110 +++++++++++++ resources/public/css/site.css | 34 ++++ src/clj/seven_guis/handler.clj | 47 ++++++ src/clj/seven_guis/server.clj | 10 ++ src/cljc/seven_guis/util.cljc | 6 + src/cljs/seven_guis/core.cljs | 153 ++++++++++++++++++ system.properties | 1 + 18 files changed, 767 insertions(+) create mode 100644 .gitignore create mode 100644 .rebel_readline_history create mode 100644 LICENSE create mode 100644 Procfile create mode 100644 README.md create mode 100644 env/dev/clj/seven_guis/middleware.clj create mode 100644 env/dev/clj/seven_guis/repl.clj create mode 100644 env/dev/clj/user.clj create mode 100644 env/dev/cljs/seven_guis/dev.cljs create mode 100644 env/prod/clj/seven_guis/middleware.clj create mode 100644 env/prod/cljs/seven_guis/prod.cljs create mode 100644 project.clj create mode 100644 resources/public/css/site.css create mode 100644 src/clj/seven_guis/handler.clj create mode 100644 src/clj/seven_guis/server.clj create mode 100644 src/cljc/seven_guis/util.cljc create mode 100644 src/cljs/seven_guis/core.cljs create mode 100644 system.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..493ee76 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +/target +/classes +/checkouts +profiles.clj +pom.xml +pom.xml.asc +*.jar +*.class +/.lein-* +/.nrepl-port +/out +/.repl +*.log +/.env +/.sass-cache +/node_modules diff --git a/.rebel_readline_history b/.rebel_readline_history new file mode 100644 index 0000000..7c09c09 --- /dev/null +++ b/.rebel_readline_history @@ -0,0 +1 @@ +1606697275092:(/ 9 5) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7689f30 --- /dev/null +++ b/LICENSE @@ -0,0 +1,214 @@ +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and +documentation distributed under this Agreement, and + +b) in the case of each subsequent Contributor: + +i) changes to the Program, and + +ii) additions to the Program; + +where such changes and/or additions to the Program originate from and are +distributed by that particular Contributor. A Contribution 'originates' from +a Contributor if it was added to the Program by such Contributor itself or +anyone acting on such Contributor's behalf. Contributions do not include +additions to the Program which: (i) are separate modules of software +distributed in conjunction with the Program under their own license +agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free copyright license to +reproduce, prepare derivative works of, publicly display, publicly perform, +distribute and sublicense the Contribution of such Contributor, if any, and +such derivative works, in source code and object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free patent license under +Licensed Patents to make, use, sell, offer to sell, import and otherwise +transfer the Contribution of such Contributor, if any, in source code and +object code form. This patent license shall apply to the combination of the +Contribution and the Program if, at the time the Contribution is added by the +Contributor, such addition of the Contribution causes such combination to be +covered by the Licensed Patents. The patent license shall not apply to any +other combinations which include the Contribution. No hardware per se is +licensed hereunder. + +c) Recipient understands that although each Contributor grants the licenses +to its Contributions set forth herein, no assurances are provided by any +Contributor that the Program does not infringe the patent or other +intellectual property rights of any other entity. Each Contributor disclaims +any liability to Recipient for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, each Recipient hereby +assumes sole responsibility to secure any other intellectual property rights +needed, if any. For example, if a third party patent license is required to +allow Recipient to distribute the Program, it is Recipient's responsibility +to acquire that license before distributing the Program. + +d) Each Contributor represents that to its knowledge it has sufficient +copyright rights in its Contribution, if any, to grant the copyright license +set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under +its own license agreement, provided that: + +a) it complies with the terms and conditions of this Agreement; and + +b) its license agreement: + +i) effectively disclaims on behalf of all Contributors all warranties and +conditions, express and implied, including warranties or conditions of title +and non-infringement, and implied warranties or conditions of merchantability +and fitness for a particular purpose; + +ii) effectively excludes on behalf of all Contributors all liability for +damages, including direct, indirect, special, incidental and consequential +damages, such as lost profits; + +iii) states that any provisions which differ from this Agreement are offered +by that Contributor alone and not by any other party; and + +iv) states that source code for the Program is available from such +Contributor, and informs licensees how to obtain it in a reasonable manner on +or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + +a) it must be made available under this Agreement; and + +b) a copy of this Agreement must be included with each copy of the Program. + +Contributors may not remove or alter any copyright notices contained within +the Program. + +Each Contributor must identify itself as the originator of its Contribution, +if any, in a manner that reasonably allows subsequent Recipients to identify +the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a +manner which does not create potential liability for other Contributors. +Therefore, if a Contributor includes the Program in a commercial product +offering, such Contributor ("Commercial Contributor") hereby agrees to defend +and indemnify every other Contributor ("Indemnified Contributor") against any +losses, damages and costs (collectively "Losses") arising from claims, +lawsuits and other legal actions brought by a third party against the +Indemnified Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the Program in +a commercial product offering. The obligations in this section do not apply +to any claims or Losses relating to any actual or alleged intellectual +property infringement. In order to qualify, an Indemnified Contributor must: +a) promptly notify the Commercial Contributor in writing of such claim, and +b) allow the Commercial Contributor tocontrol, and cooperate with the +Commercial Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any such claim +at its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If +that Commercial Contributor then makes performance claims, or offers +warranties related to Product X, those performance claims and warranties are +such Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON +AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER +EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR +CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A +PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the +appropriateness of using and distributing the Program and assumes all risks +associated with its exercise of rights under this Agreement , including but +not limited to the risks and costs of program errors, compliance with +applicable laws, damage to or loss of data, programs or equipment, and +unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION +LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE +EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this Agreement, and without further action by the +parties hereto, such provision shall be reformed to the minimum extent +necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Program itself +(excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted +under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and +does not cure such failure in a reasonable period of time after becoming +aware of such noncompliance. If all Recipient's rights under this Agreement +terminate, Recipient agrees to cease use and distribution of the Program as +soon as reasonably practicable. However, Recipient's obligations under this +Agreement and any licenses granted by Recipient relating to the Program shall +continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to +time. No one other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement Steward. The +Eclipse Foundation may assign the responsibility to serve as the Agreement +Steward to a suitable separate entity. Each new version of the Agreement will +be given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the +Agreement under which it was received. In addition, after a new version of +the Agreement is published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as expressly +stated in Sections 2(a) and 2(b) above, Recipient receives no rights or +licenses to the intellectual property of any Contributor under this +Agreement, whether expressly, by implication, estoppel or otherwise. All +rights in the Program not expressly granted under this Agreement are +reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial +in any resulting litigation. diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..9fa2759 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: java $JVM_OPTS -cp target/seven-guis.jar clojure.main -m seven-guis.server diff --git a/README.md b/README.md new file mode 100644 index 0000000..2d709cc --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ +# seven-guis + +This is the seven-guis project. + +## Development mode + +To start the Figwheel compiler, navigate to the project folder and run the following command in the terminal: + +``` +lein figwheel +``` + +Figwheel will automatically push cljs changes to the browser. The server will be available at [http://localhost:3449](http://localhost:3449) once Figwheel starts up. + +Figwheel also starts `nREPL` using the value of the `:nrepl-port` in the `:figwheel` +config found in `project.clj`. By default the port is set to `7002`. + +The figwheel server can have unexpected behaviors in some situations such as when using +websockets. In this case it's recommended to run a standalone instance of a web server as follows: + +``` +lein do clean, run +``` + +The application will now be available at [http://localhost:3000](http://localhost:3000). + + +### Optional development tools + +Start the browser REPL: + +``` +$ lein repl +``` +The Jetty server can be started by running: + +```clojure +(start-server) +``` +and stopped by running: +```clojure +(stop-server) +``` + + +## Building for release + +``` +lein do clean, uberjar +``` + +## Deploying to Heroku + +Make sure you have [Git](http://git-scm.com/downloads) and [Heroku toolbelt](https://toolbelt.heroku.com/) installed, then simply follow the steps below. + +Optionally, test that your application runs locally with foreman by running. + +``` +foreman start +``` + +Now, you can initialize your git repo and commit your application. + +``` +git init +git add . +git commit -m "init" +``` +create your app on Heroku + +``` +heroku create +``` + +optionally, create a database for the application + +``` +heroku addons:add heroku-postgresql +``` + +The connection settings can be found at your [Heroku dashboard](https://dashboard.heroku.com/apps/) under the add-ons for the app. + +deploy the application + +``` +git push heroku master +``` + +Your application should now be deployed to Heroku! +For further instructions see the [official documentation](https://devcenter.heroku.com/articles/clojure). diff --git a/env/dev/clj/seven_guis/middleware.clj b/env/dev/clj/seven_guis/middleware.clj new file mode 100644 index 0000000..f8990ca --- /dev/null +++ b/env/dev/clj/seven_guis/middleware.clj @@ -0,0 +1,12 @@ +(ns seven-guis.middleware + (:require + [ring.middleware.content-type :refer [wrap-content-type]] + [ring.middleware.params :refer [wrap-params]] + [prone.middleware :refer [wrap-exceptions]] + [ring.middleware.reload :refer [wrap-reload]] + [ring.middleware.defaults :refer [site-defaults wrap-defaults]])) + +(def middleware + [#(wrap-defaults % site-defaults) + wrap-exceptions + wrap-reload]) diff --git a/env/dev/clj/seven_guis/repl.clj b/env/dev/clj/seven_guis/repl.clj new file mode 100644 index 0000000..f188af8 --- /dev/null +++ b/env/dev/clj/seven_guis/repl.clj @@ -0,0 +1,33 @@ +(ns seven-guis.repl + (:use seven-guis.handler + figwheel-sidecar.repl-api + ring.server.standalone + [ring.middleware file-info file])) + +(defonce server (atom nil)) + +(defn get-handler [] + ;; #'app expands to (var app) so that when we reload our code, + ;; the server is forced to re-resolve the symbol in the var + ;; rather than having its own copy. When the root binding + ;; changes, the server picks it up without having to restart. + (-> #'app + ; Makes static assets in $PROJECT_DIR/resources/public/ available. + (wrap-file "resources") + ; Content-Type, Content-Length, and Last Modified headers for files in body + (wrap-file-info))) + +(defn start-server + "used for starting the server in development mode from REPL" + [& [port]] + (let [port (if port (Integer/parseInt port) 3000)] + (reset! server + (serve (get-handler) + {:port port + :auto-reload? true + :join? false})) + (println (str "You can view the site at http://localhost:" port)))) + +(defn stop-server [] + (.stop @server) + (reset! server nil)) diff --git a/env/dev/clj/user.clj b/env/dev/clj/user.clj new file mode 100644 index 0000000..4ba997c --- /dev/null +++ b/env/dev/clj/user.clj @@ -0,0 +1,11 @@ +(ns user + (:require [figwheel-sidecar.repl-api :as ra])) + +(defn start-fw [] + (ra/start-figwheel!)) + +(defn stop-fw [] + (ra/stop-figwheel!)) + +(defn cljs [] + (ra/cljs-repl)) diff --git a/env/dev/cljs/seven_guis/dev.cljs b/env/dev/cljs/seven_guis/dev.cljs new file mode 100644 index 0000000..56d5de3 --- /dev/null +++ b/env/dev/cljs/seven_guis/dev.cljs @@ -0,0 +1,15 @@ +(ns ^:figwheel-no-load seven-guis.dev + (:require + [seven-guis.core :as core] + [devtools.core :as devtools])) + +(extend-protocol IPrintWithWriter + js/Symbol + (-pr-writer [sym writer _] + (-write writer (str "\"" (.toString sym) "\"")))) + +(devtools/install!) + +(enable-console-print!) + +(core/init!) diff --git a/env/prod/clj/seven_guis/middleware.clj b/env/prod/clj/seven_guis/middleware.clj new file mode 100644 index 0000000..d021996 --- /dev/null +++ b/env/prod/clj/seven_guis/middleware.clj @@ -0,0 +1,6 @@ +(ns seven-guis.middleware + (:require + [ring.middleware.defaults :refer [site-defaults wrap-defaults]])) + +(def middleware + [#(wrap-defaults % site-defaults)]) diff --git a/env/prod/cljs/seven_guis/prod.cljs b/env/prod/cljs/seven_guis/prod.cljs new file mode 100644 index 0000000..fe2e9f7 --- /dev/null +++ b/env/prod/cljs/seven_guis/prod.cljs @@ -0,0 +1,7 @@ +(ns seven-guis.prod + (:require [seven-guis.core :as core])) + +;;ignore println statements in prod +(set! *print-fn* (fn [& _])) + +(core/init!) diff --git a/project.clj b/project.clj new file mode 100644 index 0000000..ec4f4e0 --- /dev/null +++ b/project.clj @@ -0,0 +1,110 @@ +(defproject seven-guis "0.1.0-SNAPSHOT" + :description "FIXME: write description" + :url "http://example.com/FIXME" + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"} + + :dependencies [[org.clojure/clojure "1.10.1"] + [ring-server "0.5.0"] + [reagent "0.10.0"] + [reagent-utils "0.3.3"] + [ring "1.8.1"] + [ring/ring-defaults "0.3.2"] + [hiccup "1.0.5"] + [yogthos/config "1.1.7"] + [org.clojure/clojurescript "1.10.773" + :scope "provided"] + [metosin/reitit "0.5.1"] + [metosin/jsonista "0.2.6"] + [pez/clerk "1.0.0"] + [venantius/accountant "0.2.5" + :exclusions [org.clojure/tools.reader]]] + + :plugins [[lein-environ "1.1.0"] + [lein-cljsbuild "1.1.7"] + [lein-asset-minifier "0.4.6" + :exclusions [org.clojure/clojure]]] + + :ring {:handler seven-guis.handler/app + :uberwar-name "seven-guis.war"} + + :min-lein-version "2.5.0" + :uberjar-name "seven-guis.jar" + :main seven-guis.server + :clean-targets ^{:protect false} + [:target-path + [:cljsbuild :builds :app :compiler :output-dir] + [:cljsbuild :builds :app :compiler :output-to]] + + :source-paths ["src/clj" "src/cljc" "src/cljs"] + :resource-paths ["resources" "target/cljsbuild"] + + :minify-assets + [[:css {:source "resources/public/css/site.css" + :target "resources/public/css/site.min.css"}]] + + :cljsbuild + {:builds {:min + {:source-paths ["src/cljs" "src/cljc" "env/prod/cljs"] + :compiler + {:output-to "target/cljsbuild/public/js/app.js" + :output-dir "target/cljsbuild/public/js" + :source-map "target/cljsbuild/public/js/app.js.map" + :optimizations :advanced + :infer-externs true + :pretty-print false}} + :app + {:source-paths ["src/cljs" "src/cljc" "env/dev/cljs"] + :figwheel {:on-jsload "seven-guis.core/mount-root"} + :compiler + {:main "seven-guis.dev" + :asset-path "/js/out" + :output-to "target/cljsbuild/public/js/app.js" + :output-dir "target/cljsbuild/public/js/out" + :source-map true + :optimizations :none + :pretty-print true}} + + + + } + } + + :figwheel + {:http-server-root "public" + :server-port 3449 + :nrepl-port 7002 + :nrepl-middleware [cider.piggieback/wrap-cljs-repl + ] + :css-dirs ["resources/public/css"] + :ring-handler seven-guis.handler/app} + + + + :profiles {:dev {:repl-options {:init-ns seven-guis.repl} + :dependencies [[cider/piggieback "0.5.1"] + [binaryage/devtools "1.0.2"] + [ring/ring-mock "0.4.0"] + [ring/ring-devel "1.8.1"] + [prone "2020-01-17"] + [figwheel-sidecar "0.5.20"] + [nrepl "0.8.0"] + [pjstadig/humane-test-output "0.10.0"] + + ] + + :source-paths ["env/dev/clj"] + :plugins [[lein-figwheel "0.5.20"] +] + + :injections [(require 'pjstadig.humane-test-output) + (pjstadig.humane-test-output/activate!)] + + :env {:dev true}} + + :uberjar {:hooks [minify-assets.plugin/hooks] + :source-paths ["env/prod/clj"] + :prep-tasks ["compile" ["cljsbuild" "once" "min"]] + :env {:production true} + :aot :all + :omit-source true}}) diff --git a/resources/public/css/site.css b/resources/public/css/site.css new file mode 100644 index 0000000..f5bdfaf --- /dev/null +++ b/resources/public/css/site.css @@ -0,0 +1,34 @@ +.body-container { + font-family: 'Helvetica Neue', Verdana, Helvetica, Arial, sans-serif; + max-width: 640px; + margin: 0 auto; + padding-top: 72px; + -webkit-font-smoothing: antialiased; + font-size: 1.125em; + color: #333; + line-height: 1.5em; +} + +h1, h2, h3 { + color: #000; +} +h1 { + font-size: 2.5em +} + +h2 { + font-size: 2em +} + +h3 { + font-size: 1.5em +} + +a { + text-decoration: none; + color: #09f; +} + +a:hover { + text-decoration: underline; +} diff --git a/src/clj/seven_guis/handler.clj b/src/clj/seven_guis/handler.clj new file mode 100644 index 0000000..aac3ef8 --- /dev/null +++ b/src/clj/seven_guis/handler.clj @@ -0,0 +1,47 @@ +(ns seven-guis.handler + (:require + [reitit.ring :as reitit-ring] + [seven-guis.middleware :refer [middleware]] + [hiccup.page :refer [include-js include-css html5]] + [config.core :refer [env]])) + +(def mount-target + [:div#app + [:h2 "Welcome to seven-guis"] + [:p "please wait while Figwheel is waking up ..."] + [:p "(Check the js console for hints if nothing exciting happens.)"]]) + +(defn head [] + [:head + [:meta {:charset "utf-8"}] + [:meta {:name "viewport" + :content "width=device-width, initial-scale=1"}] + (include-css (if (env :dev) "/css/site.css" "/css/site.min.css"))]) + +(defn loading-page [] + (html5 + (head) + [:body {:class "body-container"} + mount-target + (include-js "/js/app.js")])) + + +(defn index-handler + [_request] + {:status 200 + :headers {"Content-Type" "text/html"} + :body (loading-page)}) + +(def app + (reitit-ring/ring-handler + (reitit-ring/router + [["/" {:get {:handler index-handler}}] + ["/items" + ["" {:get {:handler index-handler}}] + ["/:item-id" {:get {:handler index-handler + :parameters {:path {:item-id int?}}}}]] + ["/about" {:get {:handler index-handler}}]]) + (reitit-ring/routes + (reitit-ring/create-resource-handler {:path "/" :root "/public"}) + (reitit-ring/create-default-handler)) + {:middleware middleware})) diff --git a/src/clj/seven_guis/server.clj b/src/clj/seven_guis/server.clj new file mode 100644 index 0000000..7174c92 --- /dev/null +++ b/src/clj/seven_guis/server.clj @@ -0,0 +1,10 @@ +(ns seven-guis.server + (:require + [seven-guis.handler :refer [app]] + [config.core :refer [env]] + [ring.adapter.jetty :refer [run-jetty]]) + (:gen-class)) + +(defn -main [& args] + (let [port (or (env :port) 3000)] + (run-jetty #'app {:port port :join? false}))) diff --git a/src/cljc/seven_guis/util.cljc b/src/cljc/seven_guis/util.cljc new file mode 100644 index 0000000..351a03d --- /dev/null +++ b/src/cljc/seven_guis/util.cljc @@ -0,0 +1,6 @@ +(ns seven-guis.util) + +(defn foo-cljc [x] + "I don't do a whole lot." + [x] + (println x "Hello, World!")) diff --git a/src/cljs/seven_guis/core.cljs b/src/cljs/seven_guis/core.cljs new file mode 100644 index 0000000..2f16b35 --- /dev/null +++ b/src/cljs/seven_guis/core.cljs @@ -0,0 +1,153 @@ +(ns seven-guis.core + (:require + [reagent.core :as reagent :refer [atom]] + [reagent.dom :as rdom] + [reagent.session :as session] + [reitit.frontend :as reitit] + [clerk.core :as clerk] + [accountant.core :as accountant])) + +;; utils +(def event-value #(-> % .-target .-value)) + +;; components +;; + +(defn box [name contents] + [:div {:style {:border "1px solid black" :border-radius "4px" :padding "10px"}} [:h3 name] contents]) + +(defn counter [] + (let [click-count (atom 0)] + (fn [] + [:div + "The button has been clicked " @click-count " times." + [:input {:type "button" :value "Click me!" + :on-click #(swap! click-count inc)}]]))) + +(def celsius->fahrenheit #(+ 32 (* (/ 9 5) %))) +(def fahrenheit->celsius #(* (/ 5 9) (- % 32))) +(defn temperature-converter [] + (let [temperature (atom nil)] + (fn [] + [:div + [:input {:type "number" :on-change #(reset! temperature (event-value %)) :value (.round js/Math @temperature)}] "Celsius =" + [:input {:type "number" :on-change #(reset! temperature (fahrenheit->celsius (event-value %))) :value (.round js/Math (celsius->fahrenheit @temperature))}] "Fahrenheit"]))) + +(defn flight-scheduler [] + (let [flight-type (atom "one-way flight") + start (atom nil) + end (atom nil)] + (fn [] + (print @flight-type @start @end) + [:div {:style {:display "flex" :flex-direction "column" :max-width 200}} + [:select {:value @flight-type + :on-change #(reset! flight-type (event-value %))} + [:option "one-way flight"] + [:option "return flight"]] + [:input {:type "date" :on-change #(reset! start (-> % .-target .-valueAsDate))}] + [:input {:type "date" :value @end :on-change #() :disabled (= @flight-type "one-way flight")}] + [:button {:on-click #(print "You have booked a" @flight-type "on" @start (if (= @flight-type "return flight") (str "returning on" @end ".") "."))} "Book"]]))) + + +(defn home-page [] + (fn [] + [:span.main + [:h1 "Tao Lin's Seven GUIs"] + [box + "Counter" [counter]] + [box "Temperature Converter" [temperature-converter]] + [box "Flight Scheduler" [flight-scheduler]]])) +;; ------------------------- +;; Routes + +(def router + (reitit/router + [["/" :index] + ["/items" + ["" :items] + ["/:item-id" :item]] + ["/about" :about]])) + +(defn path-for [route & [params]] + (if params + (:path (reitit/match-by-name router route params)) + (:path (reitit/match-by-name router route)))) + +;; ------------------------- +;; Page components + + + +(defn items-page [] + (fn [] + [:span.main + [:h1 "The items of seven-guis"] + [:ul (map (fn [item-id] + [:li {:name (str "item-" item-id) :key (str "item-" item-id)} + [:a {:href (path-for :item {:item-id item-id})} "Item: " item-id]]) + (range 1 60))]])) + + +(defn item-page [] + (fn [] + (let [routing-data (session/get :route) + item (get-in routing-data [:route-params :item-id])] + [:span.main + [:h1 (str "Item " item " of seven-guis")] + [:p [:a {:href (path-for :items)} "Back to the list of items"]]]))) + + +(defn about-page [] + (fn [] [:span.main + [:h1 "About seven-guis"]])) + + +;; ------------------------- +;; Translate routes -> page components + +(defn page-for [route] + (case route + :index #'home-page + :about #'about-page + :items #'items-page + :item #'item-page)) + + +;; ------------------------- +;; Page mounting component + +(defn current-page [] + (fn [] + (let [page (:current-page (session/get :route))] + [:div + [:header + [:p [:a {:href (path-for :index)} "Home"] " | " + [:a {:href (path-for :about)} "About seven-guis"]]] + [page] + [:footer + [:p "seven-guis was generated by the " + [:a {:href "https://github.com/reagent-project/reagent-template"} "Reagent Template"] "."]]]))) + +;; ------------------------- +;; Initialize app + +(defn mount-root [] + (rdom/render [current-page] (.getElementById js/document "app"))) + +(defn init! [] + (clerk/initialize!) + (accountant/configure-navigation! + {:nav-handler + (fn [path] + (let [match (reitit/match-by-path router path) + current-page (:name (:data match)) + route-params (:path-params match)] + (reagent/after-render clerk/after-render!) + (session/put! :route {:current-page (page-for current-page) + :route-params route-params}) + (clerk/navigate-page! path))) + :path-exists? + (fn [path] + (boolean (reitit/match-by-path router path)))}) + (accountant/dispatch-current!) + (mount-root)) diff --git a/system.properties b/system.properties new file mode 100644 index 0000000..5e8606c --- /dev/null +++ b/system.properties @@ -0,0 +1 @@ +java.runtime.version=1.8