Merge branch 'master' into feature/extend-filter

This commit is contained in:
Saskia Lindner 2017-08-31 12:02:06 +02:00
commit 654925545e
8 changed files with 332 additions and 140 deletions

View File

@ -99,3 +99,26 @@ You need both the re-frame-trace project _and_ a test project to develop it agai
```
- Now run your test project however you usually run it, and re-frame-trace should be in there. \o/
- Additionally, if modifying the `.less` CSS files, compile the css by running within the re-frame-trace directory:
```
lein less auto
```
to watch for changes, or one time by running:
```
lein less once
```
### Developing CSS
The CSS for the trace panel are defined both inline and within `src/day8/re_frame/less`. To develop the styles, run
```
lein less auto
```
and the .less file will automatically compile to css on file changes. Don't edit the file within `src/day8/re_frame/css` directly, or it will be overwriten. We are using css preprocessing because in order to isolate the panel styles, we are namespacing the panel styles with the id `#--re-frame-trace--`.

View File

@ -1,4 +1,4 @@
(defproject day8.re-frame/trace "0.1.4-SNAPSHOT"
(defproject day8.re-frame/trace "0.1.6-SNAPSHOT"
:description "Tracing and developer tools for re-frame apps"
:url "https://github.com/Day8/re-frame-trace"
:license {:name "MIT"}
@ -7,6 +7,23 @@
[reagent "0.6.0"]
[re-frame "0.9.0"]
[cljsjs/d3 "4.2.2-0"]]
:plugins [[lein-less "1.7.5"]]
:deploy-repositories {"releases" :clojars
"snapshots" :clojars}
:release-tasks [["vcs" "assert-committed"]
["change" "version" "leiningen.release/bump-version" "release"]
["less" "once"]
["vcs" "commit"]
["vcs" "tag"]
["deploy"]
["change" "version" "leiningen.release/bump-version"]
["vcs" "commit"]
["vcs" "push"]]
:figwheel {:css-dirs ["resources/day8/re_frame/trace"]}
:less {:source-paths ["resources/day8/re_frame/trace"]
:target-path "resources/day8/re_frame/trace"}
:profiles {:dev {:dependencies [[binaryage/dirac "RELEASE"]]}})

View File

@ -0,0 +1,100 @@
#--re-frame-trace-- {
background: white;
color: black;
font-family: 'courier new', monospace;
}
#--re-frame-trace-- tbody {
color: #aaa;
}
#--re-frame-trace-- tr:hover {
transition: all 0.1s ease-out;
background: aliceblue;
filter: brightness(90%);
}
#--re-frame-trace-- tr:nth-child(even) {
background: aliceblue;
}
#--re-frame-trace-- .button {
padding: 5px 5px 3px;
margin: 5px;
border-radius: 2px;
cursor: pointer;
}
#--re-frame-trace-- .text-button {
border-bottom: 1px dotted #888;
font-weight: normal;
}
#--re-frame-trace-- .button:focus,
#--re-frame-trace-- .text-button:focus {
border-radius: 2px 2px 0 0;
-webkit-box-shadow: inset 0px -5px 0px 0px rgba(0, 0, 0, 0.3);
-moz-box-shadow: inset 0px -5px 0px 0px rgba(0, 0, 0, 0.3);
box-shadow: inset 0px -5px 0px 0px rgba(0, 0, 0, 0.3);
}
#--re-frame-trace-- .icon-button {
font-size: 10px;
}
#--re-frame-trace-- .tab {
background: transparent;
border-radius: 0;
text-transform: uppercase;
font-family: monospace;
letter-spacing: 2px;
margin-bottom: 0;
padding-bottom: 4px;
vertical-align: bottom;
}
#--re-frame-trace-- .tab.active {
background: transparent;
border-bottom: 3px solid lightblue;
border-radius: 0;
padding-bottom: 1px;
}
#--re-frame-trace-- ul.filter-items {
list-style-type: none;
padding: 0;
margin: 0 -5px;
margin-top: 10px;
}
#--re-frame-trace-- .filter-items li {
color: #333;
background: #efefef;
display: inline-block;
font-size: 0.9em;
margin: 5px;
}
#--re-frame-trace-- .filter-items li .filter-item-string {
color: #616cdb;
}
#--re-frame-trace-- .icon {
display: inline-block;
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
}
#--re-frame-trace-- .icon-remove {
margin-left: 10px;
}
#--re-frame-trace-- select {
background: white;
font-family: 'courier new', monospace;
font-size: 1em;
}
#--re-frame-trace-- .nav {
background: #efeef1;
color: #222;
}
#--re-frame-trace-- .panel-content-top {
flex: 1;
}
#--re-frame-trace-- .panel-content-scrollable {
margin: 10px 0 0 10px;
flex: 1 0 auto;
height: 100%;
overflow: auto;
}
#--re-frame-trace-- .filter-control {
margin: 10px 0 0 10px;
}

View File

@ -0,0 +1,108 @@
#--re-frame-trace-- {
background: white;
color: black;
font-family: 'courier new', monospace;
tbody {
color: #aaa;
}
tr:hover {
transition: all 0.1s ease-out;
background: aliceblue;
filter: brightness(90%);
}
tr:nth-child(even) {
background: aliceblue;
}
.button {
padding: 5px 5px 3px;
margin: 5px;
border-radius: 2px;
cursor: pointer;
}
.text-button {
border-bottom: 1px dotted #888;
font-weight: normal;
}
.button:focus, .text-button:focus {
border-radius: 2px 2px 0 0;
-webkit-box-shadow: inset 0px -5px 0px 0px rgba(0,0,0,0.3);
-moz-box-shadow: inset 0px -5px 0px 0px rgba(0,0,0,0.3);
box-shadow: inset 0px -5px 0px 0px rgba(0,0,0,0.3);
}
.icon-button {
font-size: 10px;
}
button.tab {
}
.tab {
background: transparent;
border-radius: 0;
text-transform: uppercase;
font-family: monospace;
letter-spacing: 2px;
margin-bottom: 0;
padding-bottom: 4px;
vertical-align: bottom;
}
.tab.active {
background: transparent;
border-bottom: 3px solid lightblue;
border-radius: 0;
padding-bottom: 1px;
}
ul.filter-items {
list-style-type: none;
padding: 0;
margin: 0 -5px;
margin-top: 10px;
}
.filter-items li {
color: #333;
background: #efefef;
display: inline-block;
font-size: 0.9em;
margin: 5px;
}
.filter-items {
li {
.filter-item-string {
color: #616cdb;
}
}
}
.icon {
display: inline-block;
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
}
.icon-remove {
margin-left: 10px;
}
select {
background: white;
font-family: 'courier new', monospace;
font-size: 1em;
}
.nav {
background: #efeef1;
color: #222;
}
.panel-content-top {
flex: 1;
}
.panel-content-scrollable {
margin: 10px 0 0 10px;
flex: 1 0 auto;
height: 100%;
overflow: auto;
}
.filter-control {
margin: 10px 0 0 10px;
}
}

View File

@ -95,6 +95,7 @@
(def traces (interop/ratom []))
(defn log-trace? [trace]
(let [rendering? (= (:op-type trace) :render)]
(if-not rendering?
@ -252,29 +253,30 @@
(:filter-type item) ": " [:span.filter-item-string (:query item)]
[:span.icon-button [components/icon-remove]]]])
@filter-items)]]
[:div.panel-content-scrollable
[:table
{:cell-spacing "0" :width "100%"}
[:thead>tr
[:th [:button.text-button
{:style {:cursor "pointer"}
:on-click (fn [ev]
;; Always reset expansions
(swap! trace-detail-expansions assoc :overrides {})
;; Then toggle :show-all?
(swap! trace-detail-expansions update :show-all? not))}
(if (:show-all? @trace-detail-expansions) "-" "+")]]
[:th "operations"]
[:th
(when (pos? (count @filter-items))
(str (count showing-traces) " of "))
(when (pos? (count @traces))
(str (count @traces)))
" events "
(when (pos? (count @traces))
[:span "(" [:button.text-button {:on-click #(do (trace/reset-tracing!) (reset! traces []))} "clear"] ")"])]
[:th "meta"]]
[:tbody (render-traces showing-traces filter-items filter-input trace-detail-expansions)]]]]))))
[components/autoscroll-list {:class "panel-content-scrollable" :scroll? true}
[:table
{:style {:margin-bottom 10}
:cell-spacing "0" :width "100%"}
[:thead>tr
[:th [:button.text-button
{:style {:cursor "pointer"}
:on-click (fn [ev]
;; Always reset expansions
(swap! trace-detail-expansions assoc :overrides {})
;; Then toggle :show-all?
(swap! trace-detail-expansions update :show-all? not))}
(if (:show-all? @trace-detail-expansions) "-" "+")]]
[:th "operations"]
[:th
(when (pos? (count @filter-items))
(str (count showing-traces) " of "))
(when (pos? (count @traces))
(str (count @traces)))
" events "
(when (pos? (count @traces))
[:span "(" [:button.text-button {:on-click #(do (trace/reset-tracing!) (reset! traces []))} "clear"] ")"])]
[:th "meta"]]
[:tbody (render-traces showing-traces filter-items filter-input trace-detail-expansions)]]]]))))
(defn resizer-style [draggable-area]
{:position "absolute" :z-index 2 :opacity 0
@ -282,12 +284,17 @@
(def ease-transition "left 0.2s ease-out, top 0.2s ease-out, width 0.2s ease-out, height 0.2s ease-out")
(defn toggle-traces [showing?]
(if @showing?
(enable-tracing!)
(disable-tracing!)))
(defn devtools []
;; Add clear button
;; Filter out different trace types
(let [position (r/atom :right)
panel-width-ratio (r/atom (localstorage/get "panel-width-ratio" 0.35))
showing? (r/atom false)
showing? (r/atom (localstorage/get "show-panel" false))
dragging? (r/atom false)
pin-to-bottom? (r/atom true)
selected-tab (r/atom :traces)
@ -301,9 +308,7 @@
(cond
(and (= key "h") (.-ctrlKey e))
(do (swap! showing? not)
(if @showing?
(enable-tracing!)
(disable-tracing!))
(toggle-traces showing?)
(.preventDefault e))))))
handle-mousemove (fn [e]
(when @dragging?
@ -311,13 +316,17 @@
y (.-clientY e)]
(.preventDefault e)
(reset! panel-width-ratio (/ (- window-width x) window-width)))))]
(add-watch panel-width-ratio
:update-panel-width-ratio
(fn [_ _ _ new-state]
(localstorage/save! "panel-width-ratio" new-state)))
(add-watch showing?
:update-show-panel
(fn [_ _ _ new-state]
(localstorage/save! "show-panel" new-state)))
(r/create-class
{:component-will-mount (fn []
(toggle-traces showing?)
(js/window.addEventListener "keydown" handle-keys)
(js/window.addEventListener "mousemove" handle-mousemove))
:component-will-unmount (fn []

View File

@ -1,4 +1,6 @@
(ns day8.re-frame.trace.components)
(ns day8.re-frame.trace.components
(:require [reagent.core :as r]
[goog.fx.dom :as fx]))
(defn icon-add []
[:svg.icon.icon-add
@ -13,3 +15,36 @@
[:title "remove"]
[:path
{:d "M31.708 25.708c-0-0-0-0-0-0l-9.708-9.708 9.708-9.708c0-0 0-0 0-0 0.105-0.105 0.18-0.227 0.229-0.357 0.133-0.356 0.057-0.771-0.229-1.057l-4.586-4.586c-0.286-0.286-0.702-0.361-1.057-0.229-0.13 0.048-0.252 0.124-0.357 0.228 0 0-0 0-0 0l-9.708 9.708-9.708-9.708c-0-0-0-0-0-0-0.105-0.104-0.227-0.18-0.357-0.228-0.356-0.133-0.771-0.057-1.057 0.229l-4.586 4.586c-0.286 0.286-0.361 0.702-0.229 1.057 0.049 0.13 0.124 0.252 0.229 0.357 0 0 0 0 0 0l9.708 9.708-9.708 9.708c-0 0-0 0-0 0-0.104 0.105-0.18 0.227-0.229 0.357-0.133 0.355-0.057 0.771 0.229 1.057l4.586 4.586c0.286 0.286 0.702 0.361 1.057 0.229 0.13-0.049 0.252-0.124 0.357-0.229 0-0 0-0 0-0l9.708-9.708 9.708 9.708c0 0 0 0 0 0 0.105 0.105 0.227 0.18 0.357 0.229 0.356 0.133 0.771 0.057 1.057-0.229l4.586-4.586c0.286-0.286 0.362-0.702 0.229-1.057-0.049-0.13-0.124-0.252-0.229-0.357z"}]])
(defn scroll! [el start end time]
(.play (fx/Scroll. el (clj->js start) (clj->js end) time)))
(defn scrolled-to-end? [el tolerance]
;; at-end?: element.scrollHeight - element.scrollTop === element.clientHeight
(> tolerance (- (.-scrollHeight el) (.-scrollTop el) (.-clientHeight el))))
(defn autoscroll-list [{:keys [class scroll?]} child]
"Reagent component that enables scrolling for the elements of its child dom-node.
Scrolling is only enabled if the list is scrolled to the end.
Scrolling can be set as option for debugging purposes.
Thanks to Martin Klepsch! Original code can be found here:
https://gist.github.com/martinklepsch/440e6fd96714fac8c66d892e0be2aaa0"
(let [node (r/atom nil)
should-scroll (r/atom true)]
(r/create-class
{:display-name "autoscroll-list"
:component-did-mount
(fn [_]
(scroll! @node [0 (.-scrollTop @node)] [0 (.-scrollHeight @node)] 0))
:component-will-update
(fn [_]
(reset! should-scroll (scrolled-to-end? @node 100)))
:component-did-update
(fn [_]
(when (and scroll? @should-scroll)
(scroll! @node [0 (.-scrollTop @node)] [0 (.-scrollHeight @node)] 1600)))
:reagent-render
(fn [{:keys [class]} child]
[:div {:class class :ref (fn [dom-node]
(reset! node dom-node))}
child])})))

View File

@ -0,0 +1,7 @@
(ns day8.re-frame.trace.macros
(:require [clojure.java.io :as io]))
(defmacro slurp-macro
"Reads a file as a string. Slurp is wrapped in a macro so it can interact with local files before clojurescript compilation."
[path]
(slurp (io/resource path)))

View File

@ -1,111 +1,4 @@
(ns day8.re-frame.trace.styles)
(ns day8.re-frame.trace.styles
(:require-macros [day8.re-frame.trace.macros :as macros]))
(defonce panel-styles "
#--re-frame-trace-- {
background: white;
color: black;
font-family: 'courier new', monospace;
}
#--re-frame-trace-- tbody {
color: #aaa;
}
#--re-frame-trace-- tr:hover {
transition: all 0.1s ease-out;
background: aliceblue;
filter: brightness(90%);
}
#--re-frame-trace-- tr:nth-child(even) {
background: aliceblue;
}
#--re-frame-trace-- .button {
padding: 5px 5px 3px;
margin: 5px;
border-radius: 2px;
cursor: pointer;
}
#--re-frame-trace-- .text-button {
border-bottom: 1px dotted #888;
font-weight: normal;
}
#--re-frame-trace-- .button:focus, .text-button:focus {
border-radius: 2px 2px 0 0;
-webkit-box-shadow: inset 0px -5px 0px 0px rgba(0,0,0,0.3);
-moz-box-shadow: inset 0px -5px 0px 0px rgba(0,0,0,0.3);
box-shadow: inset 0px -5px 0px 0px rgba(0,0,0,0.3);
}
#--re-frame-trace-- .icon-button {
font-size: 10px;
}
#--re-frame-trace-- button.tab {
}
#--re-frame-trace-- .tab {
background: transparent;
border-radius: 0;
text-transform: uppercase;
font-family: monospace;
letter-spacing: 2px;
margin-bottom: 0;
padding-bottom: 4px;
vertical-align: bottom;
}
#--re-frame-trace-- .tab.active {
background: transparent;
border-bottom: 3px solid lightblue;
border-radius: 0;
padding-bottom: 1px;
}
#--re-frame-trace-- ul.filter-items {
list-style-type: none;
padding: 0;
margin: 0 -5px;
margin-top: 10px;
}
#--re-frame-trace-- .filter-items li {
color: #333;
background: #efefef;
display: inline-block;
font-size: 0.9em;
margin: 5px;
}
#--re-frame-trace-- .filter-items li .filter-item-string {
color: #616cdb;
}
#--re-frame-trace-- .op-string:hover {
cursor: pointer;
background-color: rgba(0, 0, 0, 0.08);
width: fit-content;
}
#--re-frame-trace-- .icon {
display: inline-block;
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
}
#--re-frame-trace-- .icon-remove {
margin-left: 10px;
}
#--re-frame-trace-- select {
background: white;
font-family: 'courier new', monospace;
font-size: 1em;
}
#--re-frame-trace-- .nav {
background: #efeef1;
color: #222;
}
#--re-frame-trace-- .panel-content-top {
flex: 1;
}
#--re-frame-trace-- .panel-content-scrollable {
margin: 10px 0 0 10px;
flex: 1 0 auto;
height: 100%;
overflow: auto;
}
#--re-frame-trace-- .filter-control {
margin: 10px 0 0 10px;
}
")
(def panel-styles (macros/slurp-macro "day8/re_frame/trace/main.css"))