Browse Source

added empty reframe frontend

Brandon Wong 4 years ago
parent
commit
2ebca8839b

+ 15 - 0
frontend/.gitignore

@@ -0,0 +1,15 @@
+/out/
+/resources/public/js/compiled/
+/target/
+/*-init.clj
+/*.log
+
+# Leiningen
+/.lein-*
+/.nrepl-port
+
+# Node.js dependencies
+/node_modules/
+
+# shadow-cljs cache, port files
+/.shadow-cljs/

+ 203 - 0
frontend/README.md

@@ -0,0 +1,203 @@
+# microtables-frontend
+
+A [re-frame](https://github.com/day8/re-frame) application designed to ... well, that part is up to
+you.
+
+## Getting Started
+
+### Project Overview
+
+* Architecture:
+[Single Page Application (SPA)](https://en.wikipedia.org/wiki/Single-page_application)
+* Languages
+  - Front end ([re-frame](https://github.com/day8/re-frame)): [ClojureScript](https://clojurescript.org/) (CLJS)
+* Dependencies
+  - UI framework: [re-frame](https://github.com/day8/re-frame)
+  ([docs](https://github.com/day8/re-frame/blob/master/docs/README.md),
+  [FAQs](https://github.com/day8/re-frame/blob/master/docs/FAQs/README.md)) ->
+  [Reagent](https://github.com/reagent-project/reagent) ->
+  [React](https://github.com/facebook/react)
+* Build tools
+  - Project task & dependency management: [Leiningen](https://github.com/technomancy/leiningen)
+  - CLJS compilation, REPL, & hot reload: [`shadow-cljs`](https://github.com/thheller/shadow-cljs)
+* Development tools
+  - Debugging: [CLJS DevTools](https://github.com/binaryage/cljs-devtools)
+
+#### Directory structure
+
+* [`/`](/../../): project config files
+* [`dev/`](dev/): source files compiled only with the [dev](#running-the-app) profile
+  - [`cljs/user.cljs`](dev/cljs/user.cljs): symbols for use during development in the
+[ClojureScript REPL](#connecting-to-the-browser-repl-from-a-terminal)
+* [`resources/public/`](resources/public/): SPA root directory;
+[dev](#running-the-app) / [prod](#production) profile depends on the most recent build
+  - [`index.html`](resources/public/index.html): SPA home page
+    - Dynamic SPA content rendered in the following `div`:
+        ```html
+        <div id="app"></div>
+        ```
+    - Customizable; add headers, footers, links to other scripts and styles, etc.
+  - Generated directories and files
+    - Created on build with either the [dev](#running-the-app) or [prod](#production) profile
+    - Deleted on `lein clean` (run by all `lein` aliases before building)
+    - `js/compiled/`: compiled CLJS (`shadow-cljs`)
+      - Not tracked in source control; see [`.gitignore`](.gitignore)
+* [`src/cljs/microtables_frontend/`](src/cljs/microtables_frontend/): SPA source files (ClojureScript,
+[re-frame](https://github.com/Day8/re-frame))
+  - [`core.cljs`](src/cljs/microtables_frontend/core.cljs): contains the SPA entry point, `init`
+
+### Editor/IDE
+
+Use your preferred editor or IDE that supports Clojure/ClojureScript development. See
+[Clojure tools](https://clojure.org/community/resources#_clojure_tools) for some popular options.
+
+### Environment Setup
+
+1. Install [JDK 8 or later](https://openjdk.java.net/install/) (Java Development Kit)
+2. Install [Leiningen](https://leiningen.org/#install) (Clojure/ClojureScript project task &
+dependency management)
+3. Install [Node.js](https://nodejs.org/) (JavaScript runtime environment)
+7. Clone this repo and open a terminal in the `microtables-frontend` project root directory
+8. Download project dependencies:
+    ```sh
+    lein deps && npm install
+    ```
+
+### Browser Setup
+
+Browser caching should be disabled when developer tools are open to prevent interference with
+[`shadow-cljs`](https://github.com/thheller/shadow-cljs) hot reloading.
+
+Custom formatters must be enabled in the browser before
+[CLJS DevTools](https://github.com/binaryage/cljs-devtools) can display ClojureScript data in the
+console in a more readable way.
+
+#### Chrome/Chromium
+
+1. Open [DevTools](https://developers.google.com/web/tools/chrome-devtools/) (Linux/Windows: `F12`
+or `Ctrl-Shift-I`; macOS: `⌘-Option-I`)
+2. Open DevTools Settings (Linux/Windows: `?` or `F1`; macOS: `?` or `Fn+F1`)
+3. Select `Preferences` in the navigation menu on the left, if it is not already selected
+4. Under the `Network` heading, enable the `Disable cache (while DevTools is open)` option
+5. Under the `Console` heading, enable the `Enable custom formatters` option
+
+#### Firefox
+
+1. Open [Developer Tools](https://developer.mozilla.org/en-US/docs/Tools) (Linux/Windows: `F12` or
+`Ctrl-Shift-I`; macOS: `⌘-Option-I`)
+2. Open [Developer Tools Settings](https://developer.mozilla.org/en-US/docs/Tools/Settings)
+(Linux/macOS/Windows: `F1`)
+3. Under the `Advanced settings` heading, enable the `Disable HTTP Cache (when toolbox is open)`
+option
+
+Unfortunately, Firefox does not yet support custom formatters in their devtools. For updates, follow
+the enhancement request in their bug tracker:
+[1262914 - Add support for Custom Formatters in devtools](https://bugzilla.mozilla.org/show_bug.cgi?id=1262914).
+
+## Development
+
+### Running the App
+
+Start a temporary local web server, build the app with the `dev` profile, and serve the app with
+hot reload:
+
+```sh
+lein dev
+```
+
+Please be patient; it may take over 20 seconds to see any output, and over 40 seconds to complete.
+
+When `[:app] Build completed` appears in the output, browse to
+[http://localhost:8280/](http://localhost:8280/).
+
+[`shadow-cljs`](https://github.com/thheller/shadow-cljs) will automatically push ClojureScript code
+changes to your browser on save. To prevent a few common issues, see
+[Hot Reload in ClojureScript: Things to avoid](https://code.thheller.com/blog/shadow-cljs/2019/08/25/hot-reload-in-clojurescript.html#things-to-avoid).
+
+Opening the app in your browser starts a
+[ClojureScript browser REPL](https://clojurescript.org/reference/repl#using-the-browser-as-an-evaluation-environment),
+to which you may now connect.
+
+#### Connecting to the browser REPL from your editor
+
+See
+[Shadow CLJS User's Guide: Editor Integration](https://shadow-cljs.github.io/docs/UsersGuide.html#_editor_integration).
+Note that `lein dev` runs `shadow-cljs watch` for you, and that this project's running build id is
+`app`, or the keyword `:app` in a Clojure context.
+
+Alternatively, search the web for info on connecting to a `shadow-cljs` ClojureScript browser REPL
+from your editor and configuration.
+
+For example, in Vim / Neovim with `fireplace.vim`
+1. Open a `.cljs` file in the project to activate `fireplace.vim`
+2. In normal mode, execute the `Piggieback` command with this project's running build id, `:app`:
+    ```vim
+    :Piggieback :app
+    ```
+
+#### Connecting to the browser REPL from a terminal
+
+1. Connect to the `shadow-cljs` nREPL:
+    ```sh
+    lein repl :connect localhost:8777
+    ```
+    The REPL prompt, `shadow.user=>`, indicates that is a Clojure REPL, not ClojureScript.
+
+2. In the REPL, switch the session to this project's running build id, `:app`:
+    ```clj
+    (shadow.cljs.devtools.api/nrepl-select :app)
+    ```
+    The REPL prompt changes to `cljs.user=>`, indicating that this is now a ClojureScript REPL.
+3. See [`user.cljs`](dev/cljs/user.cljs) for symbols that are immediately accessible in the REPL
+without needing to `require`.
+
+### Running `shadow-cljs` Actions
+
+See a list of [`shadow-cljs CLI`](https://shadow-cljs.github.io/docs/UsersGuide.html#_command_line)
+actions:
+```sh
+lein run -m shadow.cljs.devtools.cli --help
+```
+
+Please be patient; it may take over 10 seconds to see any output. Also note that some actions shown
+may not actually be supported, outputting "Unknown action." when run.
+
+Run a shadow-cljs action on this project's build id (without the colon, just `app`):
+```sh
+lein run -m shadow.cljs.devtools.cli <action> app
+```
+### Debug Logging
+
+The `debug?` variable in [`config.cljs`](src/cljs/microtables_frontend/config.cljs) defaults to `true` in
+[`dev`](#running-the-app) builds, and `false` in [`prod`](#production) builds.
+
+Use `debug?` for logging or other tasks that should run only on `dev` builds:
+
+```clj
+(ns microtables-frontend.example
+  (:require [microtables-frontend.config :as config])
+
+(when config/debug?
+  (println "This message will appear in the browser console only on dev builds."))
+```
+
+## Production
+
+Build the app with the `prod` profile:
+
+```sh
+lein prod
+```
+
+Please be patient; it may take over 15 seconds to see any output, and over 30 seconds to complete.
+
+The `resources/public/js/compiled` directory is created, containing the compiled `app.js` and
+`manifest.edn` files.
+
+The [`resources/public`](resources/public/) directory contains the complete, production web front
+end of your app.
+
+Always inspect the `resources/public/js/compiled` directory prior to deploying the app. Running any
+`lein` alias in this project after `lein dev` will, at the very least, run `lein clean`, which
+deletes this generated directory. Further, running `lein dev` will generate many, much larger
+development versions of the files in this directory.

+ 8 - 0
frontend/dev/cljs/user.cljs

@@ -0,0 +1,8 @@
+(ns cljs.user
+  "Commonly used symbols for easy access in the ClojureScript REPL during
+  development."
+  (:require
+    [cljs.repl :refer (Error->map apropos dir doc error->str ex-str ex-triage
+                       find-doc print-doc pst source)]
+    [clojure.pprint :refer (pprint)]
+    [clojure.string :as str]))

+ 28 - 0
frontend/karma.conf.js

@@ -0,0 +1,28 @@
+module.exports = function (config) {
+  var junitOutputDir = process.env.CIRCLE_TEST_REPORTS || "target/junit"
+
+  config.set({
+    browsers: ['ChromeHeadless'],
+    basePath: 'target',
+    files: ['karma-test.js'],
+    frameworks: ['cljs-test'],
+    plugins: [
+        'karma-cljs-test',
+        'karma-chrome-launcher',
+        'karma-junit-reporter'
+    ],
+    colors: true,
+    logLevel: config.LOG_INFO,
+    client: {
+      args: ['shadow.test.karma.init'],
+      singleRun: true
+    },
+
+    // the default configuration
+    junitReporter: {
+      outputDir: junitOutputDir + '/karma', // results will be saved as outputDir/browserName.xml
+      outputFile: undefined, // if included, results will be saved as outputDir/browserName/outputFile
+      suite: '' // suite will become the package name attribute in xml testsuite element
+    }
+  })
+}

+ 5 - 0
frontend/package.json

@@ -0,0 +1,5 @@
+{
+  "devDependencies": {
+    "shadow-cljs": "2.8.83"
+  }
+}

+ 43 - 0
frontend/project.clj

@@ -0,0 +1,43 @@
+(defproject microtables-frontend "0.1.0-SNAPSHOT"
+  :dependencies [[org.clojure/clojure "1.10.1"]
+                 [org.clojure/clojurescript "1.10.597"
+                  :exclusions [com.google.javascript/closure-compiler-unshaded
+                               org.clojure/google-closure-library
+                               org.clojure/google-closure-library-third-party]]
+                 [thheller/shadow-cljs "2.8.83"]
+                 [reagent "0.9.1"]
+                 [re-frame "0.11.0"]]
+
+  :plugins [
+            [lein-shell "0.5.0"]]
+
+  :min-lein-version "2.5.3"
+
+  :source-paths ["src/clj" "src/cljs"]
+
+  :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
+
+
+  :shell {:commands {"open" {:windows ["cmd" "/c" "start"]
+                             :macosx  "open"
+                             :linux   "xdg-open"}}}
+
+  :aliases {"dev"          ["with-profile" "dev" "do"
+                            ["run" "-m" "shadow.cljs.devtools.cli" "watch" "app"]]
+            "prod"         ["with-profile" "prod" "do"
+                            ["run" "-m" "shadow.cljs.devtools.cli" "release" "app"]]
+            "build-report" ["with-profile" "prod" "do"
+                            ["run" "-m" "shadow.cljs.devtools.cli" "run" "shadow.cljs.build-report" "app" "target/build-report.html"]
+                            ["shell" "open" "target/build-report.html"]]
+            "karma"        ["with-profile" "prod" "do"
+                            ["run" "-m" "shadow.cljs.devtools.cli" "compile" "karma-test"]
+                            ["shell" "karma" "start" "--single-run" "--reporters" "junit,dots"]]}
+
+  :profiles
+  {:dev
+   {:dependencies [[binaryage/devtools "1.0.0"]]
+    :source-paths ["dev"]}
+
+   :prod { }}
+
+  :prep-tasks [])

+ 15 - 0
frontend/resources/public/index.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset='utf-8'>
+    <meta name="viewport" content="width=device-width,initial-scale=1">
+    <title>microtables-frontend</title>
+  </head>
+  <body>
+    <noscript>
+      microtables-frontend is a JavaScript app. Please enable JavaScript to continue.
+    </noscript>
+    <div id="app"></div>
+    <script src="js/compiled/app.js"></script>
+  </body>
+</html>

+ 12 - 0
frontend/shadow-cljs.edn

@@ -0,0 +1,12 @@
+{:lein   true
+
+ :nrepl {:port 8777}
+
+ :builds {:app {:target          :browser
+                :output-dir      "resources/public/js/compiled"
+                :asset-path      "/js/compiled"
+                :modules         {:app {:init-fn microtables-frontend.core/init
+                                        :preloads [devtools.preload]}}
+                :devtools        {:http-root    "resources/public"
+                                  :http-port    8280
+                                  }}}}

+ 4 - 0
frontend/src/cljs/microtables_frontend/config.cljs

@@ -0,0 +1,4 @@
+(ns microtables-frontend.config)
+
+(def debug?
+  ^boolean goog.DEBUG)

+ 23 - 0
frontend/src/cljs/microtables_frontend/core.cljs

@@ -0,0 +1,23 @@
+(ns microtables-frontend.core
+  (:require
+   [reagent.core :as reagent]
+   [re-frame.core :as re-frame]
+   [microtables-frontend.events :as events]
+   [microtables-frontend.views :as views]
+   [microtables-frontend.config :as config]
+   ))
+
+
+(defn dev-setup []
+  (when config/debug?
+    (println "dev mode")))
+
+(defn ^:dev/after-load mount-root []
+  (re-frame/clear-subscription-cache!)
+  (reagent/render [views/main-panel]
+                  (.getElementById js/document "app")))
+
+(defn init []
+  (re-frame/dispatch-sync [::events/initialize-db])
+  (dev-setup)
+  (mount-root))

+ 4 - 0
frontend/src/cljs/microtables_frontend/db.cljs

@@ -0,0 +1,4 @@
+(ns microtables-frontend.db)
+
+(def default-db
+  {:name "re-frame"})

+ 10 - 0
frontend/src/cljs/microtables_frontend/events.cljs

@@ -0,0 +1,10 @@
+(ns microtables-frontend.events
+  (:require
+   [re-frame.core :as re-frame]
+   [microtables-frontend.db :as db]
+   ))
+
+(re-frame/reg-event-db
+ ::initialize-db
+ (fn [_ _]
+   db/default-db))

+ 8 - 0
frontend/src/cljs/microtables_frontend/subs.cljs

@@ -0,0 +1,8 @@
+(ns microtables-frontend.subs
+  (:require
+   [re-frame.core :as re-frame]))
+
+(re-frame/reg-sub
+ ::name
+ (fn [db]
+   (:name db)))

+ 11 - 0
frontend/src/cljs/microtables_frontend/views.cljs

@@ -0,0 +1,11 @@
+(ns microtables-frontend.views
+  (:require
+   [re-frame.core :as re-frame]
+   [microtables-frontend.subs :as subs]
+   ))
+
+(defn main-panel []
+  (let [name (re-frame/subscribe [::subs/name])]
+    [:div
+     [:h1 "Hello from " @name]
+     ]))