Skip to content

Commit

Permalink
Updated to recent Reagent and Fluent UI (formerly Fabric)
Browse files Browse the repository at this point in the history
  • Loading branch information
dfuenzalida committed Nov 5, 2020
1 parent a3605ff commit 1ae3e95
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 106 deletions.
53 changes: 40 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# Fabric TODOs

An implementation of the classical TODO MVC application using ClojureScript, [Reagent](http://reagent-project.github.io/), React and [Microsoft UI Fabric React](https://developer.microsoft.com/en-us/fabric#/get-started).
An implementation of the classical TODO MVC application using ClojureScript, [Reagent](http://reagent-project.github.io/), React and [Microsoft Fluent UI](https://fluent-ui.com).

Based on the UI Fabric component library demo from the Microsoft [Frontend Bootcamp](https://microsoft.github.io/frontend-bootcamp/step2-02/demo/).

### Requirements

* [Java](https://adoptopenjdk.net/)
* [Leiningen](https://leiningen.org/)
* [NodeJS](https://nodejs.org/)
* [Shadow-cljs](https://shadow-cljs.org/)
* [Yarn](https://yarnpkg.com/)

### Screenshot

Expand All @@ -18,29 +19,55 @@ Based on the UI Fabric component library demo from the Microsoft [Frontend Bootc

Navigate to the project folder and run the following commands in the terminal.

To download both the Clojure and NodeJS dependencies run:
To download the NodeJS dependencies run:

```
lein deps
yarn install
```

To start the Figwheel compiler run the following command:
Copy the static HTML file to the target folder with:

```
lein figwheel
yarn html
```

Figwheel will automatically push cljs changes to the browser.
Once Figwheel starts up, you should be able to open the `public/index.html` page in the browser.
To start the compiler in watch mode:

```
yarn watch
```

Shadow-cljs will automatically push cljs changes to the browser.
Once the ClojureScript code is compiled, visit http://localhost:8080/

### REPL

The project is setup to start nREPL on port `7002` once Figwheel starts.
Once you connect to the nREPL, run `(cljs)` to switch to the ClojureScript REPL.
On watch mode a nREPL will be started on port 37117:

```
$ yarn watch
yarn run v1.22.10
$ shadow-cljs watch app
shadow-cljs - config: /home/denis/Projects/ClojureScript/fabric-todos/shadow-cljs.edn
shadow-cljs - HTTP server available at http://localhost:8080
shadow-cljs - server version: 2.11.7 running at http://localhost:9630
shadow-cljs - nREPL server started on port 37117
shadow-cljs - watching build :app
```

### Building for production
Once you connect to the nREPL, you can run functions from the REPL, like the following bit to create a new TODO:

```
lein clean
lein package
(ns fabric-todos.state) ;; Change to the namespace where 'add-todo' is defined
(add-todo "This task was created from the REPL")
```

You should see the new task created at the end of the list.


### License

MIT


2 changes: 1 addition & 1 deletion assets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<link href="https://unpkg.com/office-ui-fabric-react@6.195.3/dist/css/fabric.min.css" rel="stylesheet" type="text/css">
<link href="https://unpkg.com/@fluentui/react@7.149.4/dist/css/fabric.min.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="app">
Expand Down
52 changes: 27 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
{
"name": "fabric-todos",
"version": "1.0.0",
"description": "TODOs application in CLJS, Reagent and Microsoft UI Fabric React",
"main": "index.js",
"scripts": {
"watch": "shadow-cljs watch app",
"compile": "shadow-cljs compile app",
"release": "shadow-cljs release app",
"html": "mkdir -p target && cp assets/index.html target/",
"serve": "yarn html && http-server target/",
"del": "rm -r target/*",
"build": "yarn release && yarn html && yarn serve"
},
"author": "Denis Fuenzalida",
"license": "MIT",
"devDependencies": {
"http-server": "^0.11.1",
"shadow-cljs": "^2.8.40"
},
"dependencies": {
"create-react-class": "^15.6.3",
"office-ui-fabric-react": "^6.195.3",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}
"name": "fabric-todos",
"version": "1.0.0",
"description": "TODOs application in ClojureScript, Reagent and Microsoft Fluent UI",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"http-server": "^0.12.3",
"shadow-cljs": "^2.11.7"
},
"dependencies": {
"@fluentui/react": "^7.149.3",
"@uifabric/icons": "^7.5.15",
"create-react-class": "^15.7.0",
"react": "^16.13.0",
"react-dom": "^16.13.0"
},
"author": "Denis Fuenzalida",
"license": "MIT",
"scripts": {
"watch": "shadow-cljs watch app",
"compile": "shadow-cljs compile app",
"release": "shadow-cljs release app",
"html": "mkdir -p target && cp assets/index.html target/",
"serve": "yarn html && http-server target/",
"del": "rm -r target/*",
"build": "yarn release && yarn html && yarn serve"
}
}
11 changes: 4 additions & 7 deletions shadow-cljs.edn
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{:source-paths ["src"]
:dependencies [[reagent "0.8.1"]
[thheller/shadow-cljsjs "0.0.18"]]
:dependencies [[reagent "1.0.0-alpha2"]]
:dev-http {8080 "target/"}
:builds {:app {:output-dir "target/"
:builds {:app {:target :browser
:output-dir "target"
:asset-path "."
:target :browser
:compiler-options {:infer-externs :auto}
:modules {:main {:init-fn fabric-todos.core/init!}}
:devtools {:after-load fabric-todos.core/reload!}}}}
:modules {:main {:init-fn fabric-todos.core/main!}}}}}
29 changes: 17 additions & 12 deletions src/fabric_todos/core.cljs
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
(ns fabric-todos.core
(:require [fabric-todos.fabric :as fab]
(:require ["@fluentui/react" :as f]
["@uifabric/icons" :as ui]
[reagent.dom :as rdom]
[fabric-todos.header :as header]
[fabric-todos.todo-list :as todo-list]
[fabric-todos.footer :as footer]
[reagent.core :as r]))
[fabric-todos.footer :as footer]))

;; Main application ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defn todo-app []
[:> fab/Stack {:horizontalAlign "center"}
[:> fab/Stack {:style {:width 400} :gap 25}
[:> f/Stack {:horizontalAlign "center"}
[:> f/Stack {:style {:width 400} :tokens {:childrenGap 25}}
(header/todo-header)
(todo-list/todo-list)
(footer/todo-footer)]])

;; App initialization ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defn mount-root []
(r/render [todo-app] (.getElementById js/document "app")))
(rdom/render [todo-app] (.getElementById js/document "app")))

(defn init! []
(mount-root)
(fab/init-icons!)
(header/focus-new-todo))
(defn init-ui []
(mount-root))

(defn reload! []
(println "reloading..."))
(defn main! []
(println "starting...")
(ui/initializeIcons)
(init-ui))

(defn ^:dev/after-load reload! []
(println "reloading...")
(init-ui))
20 changes: 0 additions & 20 deletions src/fabric_todos/fabric.cljs

This file was deleted.

8 changes: 4 additions & 4 deletions src/fabric_todos/footer.cljs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
(ns fabric-todos.footer
(:require [fabric-todos.fabric :as fab]
(:require ["@fluentui/react" :as f]
[fabric-todos.state :as state]))

(defn todo-footer []
(let [remaining (count (state/remaining-todos))
label (str remaining " item" (when-not (= 1 remaining) "s") " left")]
[:> fab/Stack {:horizontal true :horizontalAlign "space-between"}
[:> fab/Text label]
[:> fab/DefaultButton {:onClick state/clear-completed} "Clear Completed"]]))
[:> f/Stack {:horizontal true :horizontalAlign "space-between"}
[:> f/Text label]
[:> f/DefaultButton {:onClick state/clear-completed} "Clear Completed"]]))
26 changes: 13 additions & 13 deletions src/fabric_todos/header.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(ns fabric-todos.header
(:require [clojure.string :refer [blank?]]
[fabric-todos.fabric :as fab]
["@fluentui/react" :as f]
[fabric-todos.state :as state]))

(defn focus-new-todo []
Expand All @@ -20,19 +20,19 @@
(focus-new-todo))))

(defn todo-header []
[:> fab/Stack
[:> fab/Stack {:horizontal true :horizontalAlign "center"}
[:> fab/Stack.Item {:align "center"}
[:> fab/Text {:variant "xxLarge"} "todos"]]]
[:> fab/Stack {:horizontal "horizontal"}
[:> fab/Stack.Item {:grow true}
[:> fab/TextField {:id "newTodo"
[:> f/Stack
[:> f/Stack {:horizontal true :horizontalAlign "center"}
[:> f/Stack.Item {:align "center"}
[:> f/Text {:variant "xxLarge"} "todos"]]]
[:> f/Stack {:horizontal "horizontal"}
[:> f/Stack.Item {:grow true}
[:> f/TextField {:id "newTodo"
:placeholder "What needs to be done?"
:value (state/new-todo-value)
:onKeyDown #(when (= 13 (.-which %)) (add-btn-handler))
:onChange textfield-change}]]
[:> fab/PrimaryButton {:onClick add-btn-handler} "Add"]]
[:> fab/Pivot {:onLinkClick pivot-filter}
[:> fab/PivotItem {:headerText "all"}]
[:> fab/PivotItem {:headerText "active"}]
[:> fab/PivotItem {:headerText "completed"}]]])
[:> f/PrimaryButton {:onClick add-btn-handler} "Add"]]
[:> f/Pivot {:onLinkClick pivot-filter}
[:> f/PivotItem {:headerText "all"}]
[:> f/PivotItem {:headerText "active"}]
[:> f/PivotItem {:headerText "completed"}]]])
22 changes: 11 additions & 11 deletions src/fabric_todos/todo_list.cljs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
(ns fabric-todos.todo-list
(:require [fabric-todos.fabric :as fab]
(:require ["@fluentui/react" :as f]
[fabric-todos.state :as state]
[reagent.core :refer [atom]]))

(defn todo-item [{:keys [id text editing done] :as item}]
[:div {:key (str "stack" id)}
[:> fab/Stack {:horizontal true :horizontalAlign "space-between" :verticalAlign "center"}
[:> f/Stack {:horizontal true :horizontalAlign "space-between" :verticalAlign "center"}
(if editing
(let [text-value (atom text)
update-fn (fn [ev val] (reset! text-value val))]
[:> fab/Stack.Item {:grow true}
[:> fab/Stack {:horizontal true}
[:> fab/Stack.Item {:grow true}
[:> fab/TextField {:value @text-value :onChange update-fn :onKeyDown update-fn}]]
[:> fab/DefaultButton {:onClick #(state/update-todo id @text-value)} "save"]]])
[:> f/Stack.Item {:grow true}
[:> f/Stack {:horizontal true}
[:> f/Stack.Item {:grow true}
[:> f/TextField {:value @text-value :onChange update-fn :onKeyDown update-fn}]]
[:> f/DefaultButton {:onClick #(state/update-todo id @text-value)} "save"]]])
;; else
[:<>
[:> fab/Checkbox {:label text :checked done :onChange #(state/toggle-done id)}]
[:> f/Checkbox {:label text :checked done :onChange #(state/toggle-done id)}]
[:div
[:> fab/IconButton {:iconProps {:iconName "Edit"} :className "clearButton" :onClick #(state/edit-todo id)}]
[:> fab/IconButton {:iconProps {:iconName "Cancel"} :className "clearButton" :onClick #(state/delete-todo id)}]]])
[:> f/IconButton {:iconProps {:iconName "Edit"} :className "clearButton" :onClick #(state/edit-todo id)}]
[:> f/IconButton {:iconProps {:iconName "Cancel"} :className "clearButton" :onClick #(state/delete-todo id)}]]])
]])

(defn todo-list []
[:> fab/Stack {:gap 10}
[:> f/Stack {:tokens {:childrenGap 10}}
(map todo-item (state/filtered-todos))])

0 comments on commit 1ae3e95

Please sign in to comment.