Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dashboard skeleton #4

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
70c5fca
Update shadow-cljs configuration
kaffein Apr 19, 2020
fb97f63
Implement app entrypoint in index.html
kaffein Apr 19, 2020
28373a9
Add logging library
kaffein Apr 25, 2020
1f451ba
Add npm deps for bulma, bloomer and a few utils
kaffein Apr 25, 2020
a6b16cc
Implement top nav bar
kaffein Apr 25, 2020
f1f44d7
Implement left pane menu UI
kaffein Apr 25, 2020
36811c6
Make code less verbose when referring to external components
kaffein Apr 26, 2020
50fcb0a
Implement content container with no components
kaffein Apr 26, 2020
be38525
Add re-frame and re-graph dependencies
kaffein Jun 5, 2020
4ab94c3
Add re-frame-10x tooling and configuration
kaffein Jun 5, 2020
85899c0
WIP: Initiate graphql setup and configuration with re-graph
kaffein Jun 5, 2020
f275bb2
Move tooling to :dev dependencies
kaffein Jun 5, 2020
ca89ad4
Upgrade re-graph lib
kaffein Jun 8, 2020
c062247
Refactor code for dashboard statistics fetching
kaffein Jun 8, 2020
f3148a2
Add transit-cljs lib as a dependency for json encoding/decoding
kaffein Jun 9, 2020
f8676b7
Provide an explicit impl parameter for CORS Access-Control-Allow-Cred…
kaffein Jun 9, 2020
7344da8
Refactor code to use re-frame (instead of plain vanilla cljs) for re-…
kaffein Jun 9, 2020
b085f1b
Merge pull request #1 from kaffein/graphql-init
kaffein Jun 9, 2020
928ebc9
Kebab-case incoming data to be more Clojure(script)-compliant
kaffein Jun 9, 2020
1aea3fc
Add subscriptions for dashboard.stats
kaffein Jun 9, 2020
91da706
WIP Implement components for dashboard
kaffein Jun 9, 2020
bcdeac2
Refactor dashboard stat metrics display component
kaffein Jun 10, 2020
f478b07
Fix UI component id
kaffein Jun 10, 2020
0253092
Fix menu nested markup
kaffein Jun 10, 2020
bdd36b9
Refactor content-body
kaffein Jun 10, 2020
dea7e6a
Refactor menu component
kaffein Jun 10, 2020
1a6b415
Update dependencies version to avoid conflicts
kaffein Jul 14, 2020
13ed910
Add leiningen aliases to encapsulate shadow-cljs-related commands
kaffein Jul 14, 2020
a19778a
Rename aliases to avoid shadowing leiningen default commands
kaffein Jul 14, 2020
e0e9161
Update the README file
kaffein Jul 14, 2020
a17cb7f
Refactor component with init code as re-agent 2nd component form
kaffein Jul 24, 2020
65bc46e
Format code
kaffein Jul 24, 2020
8517f67
WIP
kaffein Sep 11, 2020
42ebc30
Refactor project.clj : update lein dependencies
kaffein Dec 4, 2020
b906b4b
Refactor project.clj : add lein-shadow plugin (for shadow-cljs)
kaffein Dec 4, 2020
ccce438
Refactor project.clj : add npm deps (managed by lein-shadow)
kaffein Dec 4, 2020
459f4f2
Move shadow-cljs config to project.clj
kaffein Dec 4, 2020
04c8873
Update profile config and deps
kaffein Dec 4, 2020
1029d43
Remove shadow.cljs.edn from project
kaffein Dec 4, 2020
0b7591d
Remove leiningen from the build pipeline
kaffein Feb 5, 2021
de83c60
Upgrade npm deps
kaffein Feb 5, 2021
e500a26
Update .gitignore following the reverting to a pure shadow-cljs build…
kaffein Feb 5, 2021
1f3421b
Update documentation : shadow-cljs is used for building the project
kaffein Mar 2, 2021
33cd60b
Add metadata on hot-reloading entrypoint
kaffein Mar 2, 2021
ee93524
Add shadow-cljs as dev deps
kaffein Oct 23, 2022
2385200
Fix audit vulnerability issues
kaffein Oct 23, 2022
856cbe6
Add entries to .gitignore
kaffein Oct 23, 2022
c712ecf
Git ignore shadow-cljs compilation outputs
kaffein Oct 23, 2022
0cc0954
Bump dependencies version
kaffein Oct 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 117 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,120 @@ The new (as of 2020) CLJS frontend dashboard for Yetibot

We chose `shadow-cljs` as our main build tool for the project. `shadow-cljs` is easy to use and configure and comes with a very good integration with the other tools that we already use on the other sub-projects under `Yetibot`, for e.g `Leiningen`.

See the `shadow-cljs` _user-guide_ on how to install it.
See the [`shadow-cljs` _user-guide_](https://shadow-cljs.github.io/docs/UsersGuide.html "Shadow-cljs user guide") on how to install it.

## Leiningen

`Leiningen` is the Clojure build tool that `Yetibot` uses. For `dashboard`, `shadow-cljs` delegates the _dependency management_ to `leiningen`.
`Leiningen` is the Clojure build tool that `Yetibot` uses. For `dashboard`, `shadow-cljs` delegates the _dependency management_ and _build entrypoint_ to `leiningen`. Using this tool is the easiest way to get started with the project.

See the [`Leiningen` _installation docs_](https://leiningen.org/#install "Leiningen installation instructions") on how to install it.


# Development workflow using Leiningen (the easy way)

## Running a watch process

To start a `watch` process, which will monitor changes and automatically recompile the `dashboard` code base, run the following command from the termimal:

`$ lein watch`

a `watch` will implicitly start a _server process_ which will be re-used by all commands sent by the `shadow-cljs CLI`, instead of starting a new JVM.

```shell script
added 43 packages from 380 contributors and audited 44 packages in 0.988s
found 0 vulnerabilities

[:dashboard] Compiling ...
[:dashboard] Build completed. (562 files, 0 compiled, 0 warnings, 5,46s)
shadow-cljs - HTTP server available at http://localhost:8000
shadow-cljs - server version: 2.8.94 running at http://localhost:9630
shadow-cljs - nREPL server started on port 34945
shadow-cljs - watching build :dashboard
[:dashboard] Configuring build.
[:dashboard] Compiling ...
[:dashboard] Build completed. (582 files, 1 compiled, 0 warnings, 5,49s)

```

## Compiling the project

To `compile` the project, run the following command :

`$ lein compile-cljs`


```shell script
audited 44 packages in 0.6s
found 0 vulnerabilities

[:dashboard] Compiling ...
[:dashboard] Build completed. (562 files, 0 compiled, 0 warnings, 5,45s)

```

## Releasing for production

When ready for a deployment in `production`, run the following command :

`$ lein release-cljs`

This phase will produce a `minified` version of the code for each module thanks to the `Google Closure Compiler`.

```shell script
[:dashboard] Compiling ...
[:dashboard] Build completed. (562 files, 0 compiled, 0 warnings, 5,45s)
[:dashboard] Compiling ...
[:dashboard] Build completed. (223 files, 0 compiled, 0 warnings, 17,65s)

```

## Starting a CLJS REPL

To start a `cljs repl`, run the following command :

`$ lein cljs-repl`

The output of the command should indicate the address at which to access the application.

```shell script
audited 44 packages in 0.548s
found 0 vulnerabilities
[:dashboard] Compiling ...
[:dashboard] Build completed. (562 files, 0 compiled, 0 warnings, 5,65s)
[2020-07-13 18:08:13.196 - WARNING] TCP Port 9630 in use.
[2020-07-13 18:08:14.207 - WARNING] TCP Port 8000 in use.
shadow-cljs - HTTP server available at http://localhost:8001
shadow-cljs - server version: 2.8.94 running at http://localhost:9631
shadow-cljs - nREPL server started on port 35103

```
you can then open your browser at the address exposed by the `shadow-cljs HTTP server` (here, `http://localhost:8001`).

To make sure that the `cljs repl` is correctly connected to your JS runtime (here the _browser_), you can try to open a popup by `eval`-ing the following form to the repl :

```shell script
$ cljs.user=> (js/alert "Hey Yeti!!")
nil
```

a popup should be displayed in the browser tab/window containing the application.

Otherwise an explicit error is displayed in the `repl` if the JS runtime has not loaded our Clojurescript compiled code.

```shell script
cljs.user=> (js/alert "Hey Yeti!!")
No application has connected to the REPL server. Make sure your JS environment has loaded your compiled ClojureScript code.
```

At this point, simply opening the browser at the correct address should solve the issue.

---
**NOTE**

Depending on your workflow, it is also possible to use `shadow-cljs` directly via its `CLI` or programmatically through its `api` as detailed below.

---

See the `Leiningen` Installation docs to install it.

# Development workflow using the shadow-cljs CLI

Expand Down Expand Up @@ -75,7 +182,12 @@ cljs.user=>

We also provide a `dev.clj` namespace in `dev/dev.clj` which allows for a more Clojure-_friendly_ workflow during development.
This namespace contains a few utility functions for _programmatically_ interacting with `shadow-cljs` through its Clojure API.
The first step is to `eval` those functions in your REPL.

The first step is to start a regular `Clojure repl` from your terminal (or using your IDE) using :

`$ lein repl`

and then `eval` the content of the `dev.clj` in the newly-started REPL :

```clojure
...
Expand Down Expand Up @@ -156,4 +268,4 @@ shadow-cljs - nREPL server started on port 42915
[:dashboard] Compiling ...
[:dashboard] Build completed. (59 files, 0 compiled, 0 warnings, 0,58s)
=> :done
```
```
29 changes: 29 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "dashboard",
"version": "1.0.0",
"description": "The new (as of 2020) CLJS frontend dashboard for Yetibot",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/kaffein/dashboard.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/kaffein/dashboard/issues"
},
"homepage": "https://github.com/kaffein/dashboard#readme",
"dependencies": {
"bloomer": "^0.6.5",
"bulma": "^0.8.2",
"bulma-checkradio": "^1.1.1",
"create-react-class": "^15.6.3",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2"
}
}
43 changes: 37 additions & 6 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,48 @@

:min-lein-version "2.9.1"

:dependencies [[org.clojure/clojure "1.10.0"]
[org.clojure/clojurescript "1.10.520"]
[binaryage/devtools "1.0.0"]
:dependencies [[org.clojure/clojure "1.10.1"]

;; clojurescript and tooling
[org.clojure/clojurescript "1.10.597" :scope "provided"]
[thheller/shadow-cljs "2.8.94"]

;; react
[reagent "0.10.0"]
[re-frame "0.12.0"]

;; logging
[com.taoensso/timbre "4.10.0"]

;; graphql
[re-graph "0.1.13" :exclusions [re-graph.hato]]
[district0x/graphql-query "1.0.5"]

;; utils
[com.cognitect/transit-cljs "0.8.264"]
[camel-snake-kebab "0.4.1"]

;; These has to be explicitly specified as lein does not
;; properly manage dependency version conflicts :
;; https://github.com/thheller/shadow-cljs/issues/488#issuecomment-486732296
[com.google.javascript/closure-compiler-unshaded "v20190325"]
[org.clojure/google-closure-library "0.0-20190213-2033d5d9"]]
[com.google.javascript/closure-compiler-unshaded "v20191027"]
[org.clojure/google-closure-library "0.0-20191016-6ae1f72f"]]

:plugins [[lein-shell "0.5.0"]]

:source-paths ["src"]

:profiles {:dev {}})
:aliases {"compile-cljs" ["do"
["shell" "npm" "install"]
["run" "-m" "shadow.cljs.devtools.cli" "compile" ":dashboard"]]
"watch" ["do"
["run" "-m" "shadow.cljs.devtools.cli" "watch" ":dashboard"]]
"cljs-repl" ["do"
["run" "-m" "shadow.cljs.devtools.cli" "cljs-repl" ":dashboard"]]
"release-cljs" ["do"
["run" "-m" "shadow.cljs.devtools.cli" "release" ":dashboard"]]}

:profiles {:dev
{:dependencies [[binaryage/devtools "1.0.0"]
[day8.re-frame/re-frame-10x "0.6.5"]
[day8.re-frame/tracing "0.5.5"]]}})
8 changes: 3 additions & 5 deletions resources/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/style.css" rel="stylesheet" type="text/css">
<link rel="icon" href="https://clojurescript.org/images/cljs-logo-icon-32.png">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
</head>
<body>
<div id="app">
<h2>Figwheel template</h2>
<p>Checkout your developer console.</p>
</div>
<script src="js/compiled/dashboard.js" type="text/javascript"></script>
<div id="app">If you see this then there must be an issue with the react rendering in dashboard.core/init</div>
<script src="/assets/js/dashboard.js" type="text/javascript"></script>
</body>
</html>
14 changes: 11 additions & 3 deletions shadow-cljs.edn
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@

:builds
{:dashboard {:target :browser
:output-dir "public/assets/app/js"
:asset-path "/assets/app/js"
:modules {:main {:entries [dashboard.core]}}}}}
:output-dir "resources/public/assets/js"
:asset-path "/assets/js"
:dev {:closure-defines {"re_frame.trace.trace_enabled_QMARK_" true
"day8.re_frame.tracing.trace_enabled_QMARK_" true}}
:modules {:dashboard {:init-fn dashboard.core/init}}
:devtools {:http-root "resources/public"
:http-handler shadow.http.push-state/handle
:http-port 8000
:after-load dashboard.core/start
:preloads [devtools.preload
day8.re-frame-10x.preload]}}}}
59 changes: 59 additions & 0 deletions src/dashboard/components/dashboard.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(ns dashboard.components.dashboard
(:require [reagent.core :as r]
[re-frame.core :as rf]
[reagent.dom :as rdom]
[taoensso.timbre :as log
:refer-macros [log trace debug info warn error fatal report
logf tracef debugf infof warnf errorf fatalf reportf
spy get-env]]
["bloomer" :refer (Tile Hero HeroBody Title Subtitle Notification)]
["react-router-dom" :refer (NavLink)]
[dashboard.components.search :refer [search]]
[dashboard.subs.dashboard]))

(defn display
[label value]
[:> Tile {:is-child "true" :class "box"}
[:> Title @value]
[:> Subtitle label]])

(defn expandable-stat-display
[label value path]
[:> NavLink {:class "tile is-parent is-4" :to path}
[display label value]])

(defn stat-display
[label value]
[:> Tile {:is-size 4 :is-parent "true"}
[display label value]])

(defn dashboard
[]
(let [_ (rf/dispatch [:dashboard.stats/fetch 120])
adapter-count (rf/subscribe [:dashboard.stats/adapter-count])
command-count (rf/subscribe [:dashboard.stats/command-count])
command-count-today (rf/subscribe [:dashboard.stats/command-count-today])
user-count (rf/subscribe [:dashboard.stats/user-count])
history-count (rf/subscribe [:dashboard.stats/history-count])
history-count-today (rf/subscribe [:dashboard.stats/history-count-today])
alias-count (rf/subscribe [:dashboard.stats/alias-count])
observer-count (rf/subscribe [:dashboard.stats/observer-count])
cront-count (rf/subscribe [:dashboard.stats/cron-count])
uptime (rf/subscribe [:dashboard.stats/uptime])]
(fn []
[:div
[:> Hero {:is-bold "true" :is-color "info" :is-size "small"}
[:> HeroBody
[:> Title "Dashboard"]
[:> Subtitle (str "Uptime " @uptime)]]]
[:div.tiles
[:> Tile {:is-ancestor "true" :has-text-align "centered"}
[expandable-stat-display "Adapters" adapter-count "/adapters"]
[expandable-stat-display "Commands" command-count "/history?co=1"]
[stat-display "Commands today" command-count-today]
[expandable-stat-display "User" user-count "/users"]
[expandable-stat-display "History items" history-count "/history"]
[stat-display "History items today" history-count-today]
[expandable-stat-display "Aliases" alias-count "/aliases"]
[expandable-stat-display "Observers" observer-count "/observers"]
[expandable-stat-display "Cron tasks" cront-count "/cron"]]]])))
19 changes: 19 additions & 0 deletions src/dashboard/components/history.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(ns dashboard.components.history
(:require [reagent.core :as r]
[re-frame.core :as rf]
["bloomer" :refer (Tile Hero HeroBody Title Subtitle Notification)]
["react-router-dom" :refer (NavLink)]))

(defn history
[]
(let [_ (rf/dispatch [:dashboard.history/fetch 480])]
(fn []
[:div
[:> Hero {:is-bold "true" :is-color "info" :is-size "small"}
[:> HeroBody
[:> Title "History"]
[:> Subtitle (str "Total items")]]]
[:div.tiles
[:> Tile {:is-ancestor "true" :has-text-align "centered"}
]]])))

21 changes: 21 additions & 0 deletions src/dashboard/components/search.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(ns dashboard.components.search
(:require [taoensso.timbre :as log
:refer-macros [log trace debug info warn error fatal report
logf tracef debugf infof warnf errorf fatalf reportf
spy get-env]]
["bloomer" :as bloomer]))

(defn search
"Search component skeleton"
[]
[:> bloomer/Control {:is-expanded true
:has-icons "left"}
[:input {:type :text
:value ""
:placeholder "Search history"
:iscolor "light"
:on-change (fn [e]
(info "changed this to stuff"))}]
[:> bloomer/Icon {:is-size "small"
:is-align "left"
:class "fa fa-search"}]])
Loading