0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-05 03:21:26 -05:00

feat(frontend): refactor many workspace components (rumext update)

This commit is contained in:
Andrey Antukh 2019-07-18 12:29:29 +02:00
parent c4d7d545ae
commit 9ddd9f317d
15 changed files with 504 additions and 526 deletions

View file

@ -2,78 +2,42 @@
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.workspace
(:require [beicon.core :as rx]
[lentes.core :as l]
[uxbox.main.store :as st]
[uxbox.main.constants :as c]
[uxbox.main.refs :as refs]
[uxbox.main.streams :as streams]
[uxbox.main.data.workspace :as dw]
[uxbox.main.data.pages :as udp]
[uxbox.main.data.history :as udh]
[uxbox.main.data.undo :as udu]
[uxbox.main.user-events :as uev]
[uxbox.main.ui.messages :refer [messages-widget]]
[uxbox.main.ui.confirm]
[uxbox.main.ui.workspace.images]
[uxbox.main.ui.keyboard :as kbd]
[uxbox.main.ui.workspace.scroll :as scroll]
[uxbox.main.ui.workspace.download]
[uxbox.main.ui.workspace.shortcuts :refer [shortcuts-mixin]]
[uxbox.main.ui.workspace.header :refer [header]]
[uxbox.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]]
[uxbox.main.ui.workspace.sidebar.history :refer [history-dialog]]
[uxbox.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
[uxbox.main.ui.workspace.colorpalette :refer [colorpalette]]
[uxbox.main.ui.workspace.canvas :refer [viewport]]
[uxbox.util.dom :as dom]
[uxbox.util.geom.point :as gpt]
[uxbox.util.data :refer [classnames]]
[rumext.core :as mx :include-macros true]))
(:require
[beicon.core :as rx]
[lentes.core :as l]
[rumext.core :as mx :include-macros true]
[uxbox.main.constants :as c]
[uxbox.main.data.history :as udh]
[uxbox.main.data.pages :as udp]
[uxbox.main.data.undo :as udu]
[uxbox.main.data.workspace :as dw]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.streams :as streams]
[uxbox.main.ui.confirm]
[uxbox.main.ui.keyboard :as kbd]
[uxbox.main.ui.messages :refer [messages-widget]]
[uxbox.main.ui.workspace.canvas :refer [viewport]]
[uxbox.main.ui.workspace.colorpalette :refer [colorpalette]]
[uxbox.main.ui.workspace.download]
[uxbox.main.ui.workspace.header :refer [header]]
[uxbox.main.ui.workspace.images]
[uxbox.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]]
[uxbox.main.ui.workspace.scroll :as scroll]
[uxbox.main.ui.workspace.shortcuts :refer [shortcuts-mixin]]
[uxbox.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
[uxbox.main.ui.workspace.sidebar.history :refer [history-dialog]]
[uxbox.main.user-events :as uev]
[uxbox.util.data :refer [classnames]]
[uxbox.util.dom :as dom]
[uxbox.util.geom.point :as gpt]))
;; --- Workspace
(defn- workspace-will-mount
[own]
(let [[projectid pageid] (:rum/args own)]
(st/emit! (dw/initialize projectid pageid))
own))
(defn- workspace-did-mount
[own]
(let [[projectid pageid] (:rum/args own)
dom (mx/ref-node own "workspace-canvas")
scroll-to-page-center #(scroll/scroll-to-page-center dom @refs/selected-page)
sub (rx/subscribe streams/page-id-ref-s scroll-to-page-center)]
(scroll-to-page-center)
(st/emit! (udp/watch-page-changes pageid)
(udu/watch-page-changes pageid))
(assoc own ::sub sub)))
(defn- workspace-will-unmount
[own]
(st/emit! ::udp/stop-page-watcher)
(rx/cancel! (::sub own))
(dissoc own ::sub))
(defn- workspace-did-remount
[old-state state]
(let [[projectid pageid] (:rum/args state)
[oldprojectid oldpageid] (:rum/args old-state)]
(when (not= pageid oldpageid)
(st/emit! (dw/initialize projectid pageid)
::udp/stop-page-watcher
(udp/watch-page-changes pageid)
(udu/watch-page-changes pageid)))
state))
(defn- on-scroll
[event]
(let [target (.-target event)
@ -99,52 +63,76 @@
(-> (l/key :page)
(l/derive refs/workspace)))
(mx/defcs workspace
{:did-remount workspace-did-remount
:will-mount workspace-will-mount
:will-unmount workspace-will-unmount
:did-mount workspace-did-mount
:mixins [mx/static
(mx/def workspace
:key-fn vector
:mixins #{mx/static
mx/reactive
shortcuts-mixin]}
[own project-id page-id]
(let [flags (mx/react refs/flags)
left-sidebar? (not (empty? (keep flags [:layers :sitemap
:document-history])))
right-sidebar? (not (empty? (keep flags [:icons :drawtools
:element-options])))
classes (classnames
:no-tool-bar-right (not right-sidebar?)
:no-tool-bar-left (not left-sidebar?)
:scrolling (:viewport-positionig workspace))]
[:div {}
(messages-widget)
(header)
(colorpalette)
shortcuts-mixin}
[:main.main-content {}
[:section.workspace-content
{:class classes
:on-scroll on-scroll
:on-wheel (partial on-wheel own)}
:init
(fn [own {:keys [project page] :as props}]
(st/emit! (dw/initialize project page))
(assoc own ::canvas (mx/create-ref)))
(history-dialog)
:did-mount
(fn [own]
(let [{:keys [project page]} (::mx/props own)
;; dom (mx/ref-node own "workspace-canvas")
dom (mx/ref-node (::canvas own))
scroll-to-page-center #(scroll/scroll-to-page-center dom @refs/selected-page)
sub (rx/subscribe streams/page-id-ref-s scroll-to-page-center)]
(scroll-to-page-center)
(st/emit! (udp/watch-page-changes page)
(udu/watch-page-changes page))
(assoc own ::sub sub)))
;; Rules
(when (contains? flags :rules)
(horizontal-rule))
:will-unmount
(fn [own]
(st/emit! ::udp/stop-page-watcher)
(rx/cancel! (::sub own))
(dissoc own ::sub))
(when (contains? flags :rules)
(vertical-rule))
:render
(fn [own props]
;; [own project-id page-id]
(let [flags (mx/react refs/flags)
project-id (get-in own [::mx/props :project])
page-id (get-in own [::mx/props :page])
left-sidebar? (not (empty? (keep flags [:layers :sitemap
:document-history])))
right-sidebar? (not (empty? (keep flags [:icons :drawtools
:element-options])))
classes (classnames
:no-tool-bar-right (not right-sidebar?)
:no-tool-bar-left (not left-sidebar?)
:scrolling (:viewport-positionig workspace))]
[:*
(messages-widget)
(header)
(colorpalette)
;; Canvas
[:section.workspace-canvas
{:id "workspace-canvas"
:ref "workspace-canvas"}
(viewport)]]
[:main.main-content
[:section.workspace-content
{:class classes
:on-scroll on-scroll
:on-wheel (partial on-wheel own)}
;; Aside
(when left-sidebar?
(left-sidebar flags page-id))
(when right-sidebar?
(right-sidebar flags page-id))]]))
(history-dialog)
;; Rules
(when (contains? flags :rules)
(horizontal-rule))
(when (contains? flags :rules)
(vertical-rule))
;; Canvas
[:section.workspace-canvas {:id "workspace-canvas"
:ref (::canvas own)}
(viewport)]]
;; Aside
(when left-sidebar?
(left-sidebar {:flags flags :page-id page-id}))
(when right-sidebar?
(right-sidebar {:flags flags :page-id page-id}))]])))

View file

@ -244,7 +244,7 @@
opts {:shift? shift?
:ctrl? ctrl?}]
(st/emit! (uev/mouse-event :double-click ctrl? shift?))))]
[:div {}
[:*
(coordinates)
[:div.tooltip-container {}
(when tooltip

View file

@ -30,13 +30,13 @@
(on-close [event]
(dom/prevent-default event)
(udl/close!))]
[:div.lightbox-body.clipboard {}
[:div.clipboard-list {}
[:div.lightbox-body.clipboard
[:div.clipboard-list
(for [item (mx/react clipboard-ref)]
[:div.clipboard-item
{:key (str (:id item))
:on-click (partial on-paste item)}
[:span.clipboard-icon {} i/box]
[:span.clipboard-icon i/box]
[:span {} (str "Copied (" (dt/timeago (:created-at item)) ")")]])]
[:a.close {:href "#" :on-click on-close} i/close]]))

View file

@ -46,7 +46,7 @@
[:span.color-text {} rgb-color]])))
(defn- palette-after-render
[{:keys [rum/local] :as own}]
[{:keys [::mx/local] :as own}]
(let [dom (mx/ref-node own "container")
width (.-clientWidth dom)]
(when (not= (:width @local) width)
@ -60,7 +60,7 @@
(mx/defcs palette
{:mixins [mx/static mx/reactive (mx/local)]
:after-render palette-after-render}
[{:keys [rum/local] :as own}]
[{:keys [::mx/local] :as own}]
(let [collections (->> (mx/react collections-ref)
(vals)
(filter :id)
@ -112,14 +112,14 @@
[:span.close-palette {:on-click close}
i/close]])))
(defn- colorpalette-will-mount
(defn- colorpalette-init
[own]
(st/emit! (dc/fetch-collections))
own)
(mx/defc colorpalette
{:mixins [mx/static mx/reactive]
:will-mount colorpalette-will-mount}
:init colorpalette-init}
[]
(let [flags (mx/react refs/flags)]
(when (contains? flags :colorpalette)

View file

@ -2,24 +2,25 @@
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) 2015-2017 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.workspace.images
(:require [lentes.core :as l]
[rumext.core :as mx :include-macros true]
[potok.core :as ptk]
[uxbox.builtins.icons :as i]
[uxbox.main.store :as st]
[uxbox.main.data.lightbox :as udl]
[uxbox.main.data.images :as udi]
[uxbox.main.data.workspace :as udw]
[uxbox.main.data.shapes :as uds]
[uxbox.main.ui.lightbox :as lbx]
[uxbox.util.i18n :as t :refer [tr]]
[uxbox.util.data :refer [read-string jscoll->vec]]
[uxbox.util.dom :as dom]
[uxbox.util.uuid :as uuid]))
(:require
[lentes.core :as l]
[potok.core :as ptk]
[rumext.core :as mx :include-macros true]
[uxbox.builtins.icons :as i]
[uxbox.main.data.images :as udi]
[uxbox.main.data.lightbox :as udl]
[uxbox.main.data.shapes :as uds]
[uxbox.main.data.workspace :as udw]
[uxbox.main.store :as st]
[uxbox.main.ui.lightbox :as lbx]
[uxbox.util.data :refer [read-string jscoll->vec]]
[uxbox.util.dom :as dom]
[uxbox.util.i18n :as t :refer [tr]]
[uxbox.util.uuid :as uuid]))
;; --- Refs
@ -113,9 +114,9 @@
(-> (image-item image)
(mx/with-key (str (:id image)))))])
(defn will-mount
(defn init
[own]
(let [local (:rum/local own)]
(let [local (::mx/local own)]
(st/emit! (udi/fetch-collections))
(st/emit! (udi/fetch-images nil))
(add-watch local ::key (fn [_ _ _ v]
@ -124,16 +125,16 @@
(defn will-unmount
[own]
(let [local (:rum/local own)]
(let [local (::mx/local own)]
(remove-watch local ::key)
own))
(mx/defcs image-collections-lightbox
{:mixins [mx/reactive (mx/local)]
:will-mount will-mount
:init init
:will-unmount will-unmount}
[own]
(let [local (:rum/local own)
(let [local (::mx/local own)
id (:id @local)
type (:type @local :own)
own? (= type :own)

View file

@ -6,13 +6,14 @@
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
(ns uxbox.main.ui.workspace.rules
(:require [cuerdas.core :as str]
[beicon.core :as rx]
[uxbox.main.store :as s]
[uxbox.main.constants :as c]
[uxbox.main.refs :as refs]
[uxbox.util.dom :as dom]
[rumext.core :as mx :include-macros true]))
(:require
[beicon.core :as rx]
[cuerdas.core :as str]
[rumext.core :as mx]
[uxbox.main.constants :as c]
[uxbox.main.refs :as refs]
[uxbox.main.store :as s]
[uxbox.util.dom :as dom]))
;; --- Constants & Helpers
@ -65,102 +66,103 @@
;; --- Horizontal Text Label
(mx/defc horizontal-text-label
[zoom value]
(let [big-ticks-mod (big-ticks-mod zoom)
pos (+ (* value zoom)
rule-padding
(* c/canvas-start-x zoom)
c/canvas-scroll-padding)]
(when (< (mod value big-ticks-mod) step-size)
[:text {:x (+ pos 2)
:y 13
:key (str pos)
:fill "#9da2a6"
:style {:font-size "12px"}}
value])))
(mx/def horizontal-text-label
:key-fn second
:render
(fn [own [zoom value]]
(let [big-ticks-mod (big-ticks-mod zoom)
pos (+ (* value zoom)
rule-padding
(* c/canvas-start-x zoom)
c/canvas-scroll-padding)]
(when (< (mod value big-ticks-mod) step-size)
[:text {:x (+ pos 2)
:y 13
:key (str pos)
:fill "#9da2a6"
:style {:font-size "12px"}}
value]))))
;; --- Horizontal Text Label
(mx/defc vertical-text-label
[zoom value]
(let [big-ticks-mod (big-ticks-mod zoom)
pos (+ (* value zoom)
(* c/canvas-start-x zoom)
;; c/canvas-start-x
c/canvas-scroll-padding)]
(when (< (mod value big-ticks-mod) step-size)
[:text {:y (- pos 3)
:x 5
:key (str pos)
:fill "#9da2a6"
:transform (str/format "rotate(90 0 %s)" pos)
:style {:font-size "12px"}}
value])))
(mx/def vertical-text-label
:key-fn second
:render
(fn [own [zoom value]]
(let [big-ticks-mod (big-ticks-mod zoom)
pos (+ (* value zoom)
(* c/canvas-start-x zoom)
c/canvas-scroll-padding)]
(when (< (mod value big-ticks-mod) step-size)
[:text {:y (- pos 3)
:x 5
:key (str pos)
:fill "#9da2a6"
:transform (str/format "rotate(90 0 %s)" pos)
:style {:font-size "12px"}}
value]))))
;; --- Horizontal Rule Ticks (Component)
(mx/defc horizontal-rule-ticks
{:mixins [mx/static]}
[zoom]
(let [zoom (or zoom 1)
path (reduce (partial make-vertical-tick zoom) [] +ticks+)
labels (->> (map (partial horizontal-text-label zoom) +ticks+)
(filterv identity))]
[:g {}
[:path {:d (str/join " " path)}]
(for [tick +ticks+]
(-> (horizontal-text-label zoom tick)
(mx/with-key (str tick))))]))
(mx/def horizontal-rule-ticks
:mixins #{mx/static}
:render
(fn [own zoom]
(let [zoom (or zoom 1)
path (reduce (partial make-vertical-tick zoom) [] +ticks+)]
[:g
[:path {:d (str/join " " path)}]
(for [tick +ticks+]
(horizontal-text-label [zoom tick]))])))
;; --- Vertical Rule Ticks (Component)
(mx/defc vertical-rule-ticks
{:mixins [mx/static]}
[zoom]
(let [zoom (or zoom 1)
path (reduce (partial make-horizontal-tick zoom) [] +ticks+)
labels (->> (map (partial vertical-text-label zoom) +ticks+)
(filterv identity))]
[:g {}
[:path {:d (str/join " " path)}]
(for [tick +ticks+]
(-> (vertical-text-label zoom tick)
(mx/with-key (str tick))))]))
(mx/def vertical-rule-ticks
:mixins #{mx/static}
:render
(fn [own zoom]
(let [zoom (or zoom 1)
path (reduce (partial make-horizontal-tick zoom) [] +ticks+)]
[:g
[:path {:d (str/join " " path)}]
(for [tick +ticks+]
(vertical-text-label [zoom tick]))])))
;; --- Horizontal Rule (Component)
(mx/defc horizontal-rule
{:mixins [mx/static mx/reactive]}
[]
(let [scroll (mx/react refs/workspace-scroll)
zoom (mx/react refs/selected-zoom)
scroll-x (:x scroll)
translate-x (- (- c/canvas-scroll-padding) (:x scroll))]
[:svg.horizontal-rule
{:width c/viewport-width
:height 20}
[:rect {:height 20
:width c/viewport-width}]
[:g {:transform (str "translate(" translate-x ", 0)")}
(horizontal-rule-ticks zoom)]]))
(mx/def horizontal-rule
:mixins #{mx/static mx/reactive}
:render
(fn [own props]
(let [scroll (mx/react refs/workspace-scroll)
zoom (mx/react refs/selected-zoom)
scroll-x (:x scroll)
translate-x (- (- c/canvas-scroll-padding) (:x scroll))]
[:svg.horizontal-rule
{:width c/viewport-width
:height 20}
[:rect {:height 20
:width c/viewport-width}]
[:g {:transform (str "translate(" translate-x ", 0)")}
(horizontal-rule-ticks zoom)]])))
;; --- Vertical Rule (Component)
(mx/defc vertical-rule
{:mixins [mx/static mx/reactive]}
[]
(let [scroll (mx/react refs/workspace-scroll)
zoom (mx/react refs/selected-zoom)
scroll-y (:y scroll)
translate-y (- (- c/canvas-scroll-padding) (:y scroll))]
[:svg.vertical-rule
{:width 20
:height c/viewport-height}
(mx/def vertical-rule
:mixins #{mx/static mx/reactive}
:render
(fn [own props]
(let [scroll (mx/react refs/workspace-scroll)
zoom (mx/react refs/selected-zoom)
scroll-y (:y scroll)
translate-y (- (- c/canvas-scroll-padding) (:y scroll))]
[:svg.vertical-rule
{:width 20
:height c/viewport-height}
[:g {:transform (str "translate(0, " translate-y ")")}
(vertical-rule-ticks zoom)]
[:rect {:x 0
:y 0
:height 20
:width 20}]]))
[:g {:transform (str "translate(0, " translate-y ")")}
(vertical-rule-ticks zoom)]
[:rect {:x 0
:y 0
:height 20
:width 20}]])))

View file

@ -98,7 +98,7 @@
;; --- Mixin
(defn- will-mount
(defn- init
[own]
(assoc own ::sub (initialize)))
@ -108,5 +108,5 @@
(dissoc own ::sub))
(def shortcuts-mixin
{:will-mount will-mount
{:init init
:will-unmount will-unmount})

View file

@ -18,10 +18,9 @@
;; --- Left Sidebar (Component)
(mx/defc left-sidebar
{:mixins [mx/static]}
[flags page-id]
[:aside#settings-bar.settings-bar.settings-bar-left {}
[:div.settings-bar-inside {}
[{:keys [flags page-id] :as props}]
[:aside#settings-bar.settings-bar.settings-bar-left
[:div.settings-bar-inside
(when (contains? flags :sitemap)
(sitemap-toolbox page-id))
(when (contains? flags :document-history)
@ -32,10 +31,9 @@
;; --- Right Sidebar (Component)
(mx/defc right-sidebar
{:mixins [mx/static]}
[flags page-id]
[:aside#settings-bar.settings-bar {}
[:div.settings-bar-inside {}
[{:keys [flags page-id] :as props}]
[:aside#settings-bar.settings-bar
[:div.settings-bar-inside
(when (contains? flags :drawtools)
(draw-toolbox flags))
(when (contains? flags :element-options)

View file

@ -21,125 +21,115 @@
;; --- History Item (Component)
(mx/defc history-item
{:mixins [mx/static]}
[item selected]
(letfn [(on-select [event]
(dom/prevent-default event)
(st/emit! (udh/select-page-history (:version item))))
(on-pinned [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(let [item (assoc item
:label "no label"
:pinned (not (:pinned item)))]
(st/emit! (udh/update-history-item item))))]
[:li {:class (when (= selected (:version item)) "current")
:on-click on-select}
[:div.pin-icon {:on-click on-pinned
:class (when (:pinned item) "selected")}
i/pin]
[:span {} (str "Version " (:version item)
" (" (dt/timeago (:created-at item)) ")")]]))
(mx/def history-item
:mixins [mx/static]
:key-fn :id
:render
(fn [own {:keys [::selected] :as item}]
(letfn [(on-select [event]
(dom/prevent-default event)
(st/emit! (udh/select-page-history (:version item))))
(on-pinned [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(let [item (assoc item
:label "no label"
:pinned (not (:pinned item)))]
(st/emit! (udh/update-history-item item))))]
[:li {:class (when (= selected (:version item)) "current")
:on-click on-select}
[:div.pin-icon {:on-click on-pinned
:class (when (:pinned item) "selected")}
i/pin]
[:span (str "Version " (:version item)
" (" (dt/timeago (:created-at item)) ")")]])))
;; --- History List (Component)
(mx/defc history-list
{:mixins [mx/static mx/reactive]}
[{:keys [selected items min-version] :as history}]
(let [items (reverse (sort-by :version items))
page (mx/react refs/selected-page)
show-more? (pos? min-version)
load-more #(st/emit! (udh/load-more))]
[:ul.history-content {}
(for [item items]
(let [current? (= (:version item) (:version page))]
(-> (history-item item selected current?)
(mx/with-key (str (:id item))))))
(when show-more?
[:li {:on-click load-more}
[:a.btn-primary.btn-small {}
"view more"]])]))
(mx/def history-list
:mixins [mx/static mx/reactive]
:render
(fn [own {:keys [selected items min-version] :as history}]
(let [items (reverse (sort-by :version items))
page (mx/react refs/selected-page)
show-more? (pos? min-version)
load-more #(st/emit! (udh/load-more))]
[:ul.history-content
(for [item items]
(history-item (assoc item ::selectd selected)))
(when show-more?
[:li {:on-click load-more}
[:a.btn-primary.btn-small
"view more"]])])))
;; --- History Pinned List (Component)
(mx/defc history-pinned-list
{:mixins [mx/static]}
[{:keys [pinned selected] :as history}]
[:ul.history-content {}
(for [item (reverse (sort-by :version pinned))]
(let [selected? (= (:version item) selected)]
(-> (history-item item selected?)
(mx/with-key (str (:id item))))))])
(mx/def history-pinned-list
:mixins [mx/static]
:render
(fn [own {:keys [pinned selected] :as history}]
[:ul.history-content
(for [item (reverse (sort-by :version pinned))]
(let [selected (= (:version item) selected)]
(history-item (assoc item ::selected selected))))]))
;; --- History Toolbox (Component)
(mx/def history-toolbox
:mixins [mx/static mx/reactive]
(defn- history-toolbox-will-mount
[own]
(let [[page-id] (:rum/args own)]
:init
(fn [own page-id]
(st/emit! (udh/initialize page-id))
own))
own)
(defn- history-toolbox-did-remount
[oldown own]
(let [[old-page-id] (:rum/args oldown)
[new-page-id] (:rum/args own)]
(when-not (= old-page-id new-page-id)
(st/emit! ::udh/stop-changes-watcher
(udh/initialize new-page-id)))
own))
:will-unmount
(fn [own]
(st/emit! ::udh/stop-changes-watcher)
own)
(defn- history-toolbox-will-unmount
[own]
(st/emit! ::udh/stop-changes-watcher)
own)
:render
(fn [own page-id]
(let [history (mx/react refs/history)
section (:section history :main)
(mx/defc history-toolbox
{:mixins [mx/static mx/reactive]
:will-mount history-toolbox-will-mount
:will-unmount history-toolbox-will-unmount
:did-remount history-toolbox-did-remount}
[_]
(let [history (mx/react refs/history)
section (:section history :main)
close #(st/emit! (dw/toggle-flag :document-history))
main? (= section :main)
pinned? (= section :pinned)
close #(st/emit! (dw/toggle-flag :document-history))
main? (= section :main)
pinned? (= section :pinned)
show-main #(st/emit! (udh/select-section :main))
show-pinned #(st/emit! (udh/select-section :pinned))]
[:div.document-history.tool-window {}
[:div.tool-window-bar {}
[:div.tool-window-icon {} i/undo-history]
[:span {} (tr "ds.document-history")]
[:div.tool-window-close {:on-click close} i/close]]
[:div.tool-window-content {}
[:ul.history-tabs {}
[:li {:on-click show-main
:class (when main? "selected")}
"History"]
[:li {:on-click show-pinned
:class (when pinned? "selected")}
"Pinned"]]
(if (= section :pinned)
(history-pinned-list history)
(history-list history))]]))
show-main #(st/emit! (udh/select-section :main))
show-pinned #(st/emit! (udh/select-section :pinned))]
[:div.document-history.tool-window {}
[:div.tool-window-bar {}
[:div.tool-window-icon {} i/undo-history]
[:span {} (tr "ds.document-history")]
[:div.tool-window-close {:on-click close} i/close]]
[:div.tool-window-content {}
[:ul.history-tabs {}
[:li {:on-click show-main
:class (when main? "selected")}
"History"]
[:li {:on-click show-pinned
:class (when pinned? "selected")}
"Pinned"]]
(if (= section :pinned)
(history-pinned-list history)
(history-list history))]])))
;; --- History Dialog
(mx/defc history-dialog
{:mixins [mx/static mx/reactive]}
[]
(let [history (mx/react refs/history)
version (:selected history)
on-accept #(st/emit! (udh/apply-selected-history))
on-cancel #(st/emit! (udh/deselect-page-history))]
(when (or version (:deselecting history))
[:div.message-version
{:class (when (:deselecting history) "hide-message")}
[:span {} (tr "history.alert-message" (or version "00"))
[:div.message-action {}
[:a.btn-transparent {:on-click on-accept} "Accept"]
[:a.btn-transparent {:on-click on-cancel} "Cancel"]]]])))
(mx/def history-dialog
:mixins [mx/static mx/reactive]
:render
(fn [own]
(let [history (mx/react refs/history)
version (:selected history)
on-accept #(st/emit! (udh/apply-selected-history))
on-cancel #(st/emit! (udh/deselect-page-history))]
(when (or version (:deselecting history))
[:div.message-version
{:class (when (:deselecting history) "hide-message")}
[:span {} (tr "history.alert-message" (or version "00"))
[:div.message-action {}
[:a.btn-transparent {:on-click on-accept} "Accept"]
[:a.btn-transparent {:on-click on-cancel} "Cancel"]]]]))))

View file

@ -40,14 +40,14 @@
[icon]
(icon/icon-svg icon))
(defn- icons-toolbox-will-mount
(defn- icons-toolbox-init
[own]
(st/emit! (udw/initialize-icons-toolbox))
own)
(mx/defc icons-toolbox
{:mixins [mx/static mx/reactive]
:will-mount icons-toolbox-will-mount}
:init icons-toolbox-init}
[]
(let [drawing (mx/react drawing-shape-ref)
selected (mx/react icons-toolbox-ref)

View file

@ -89,43 +89,42 @@
;; --- Shape Name (Component)
(mx/defcs shape-name
"A generic component that displays the shape name
if it is available and allows inline edition of it."
{:mixins [mx/static (mx/local)]}
[{:keys [rum/local]} {:keys [id] :as shape}]
(letfn [(on-blur [event]
(let [target (dom/event->target event)
parent (.-parentNode target)
name (dom/get-value target)]
(set! (.-draggable parent) true)
(st/emit! (uds/rename-shape id name))
(swap! local assoc :edition false)))
(on-key-down [event]
(js/console.log event)
(when (kbd/enter? event)
(on-blur event)))
(on-click [event]
(dom/prevent-default event)
(let [parent (.-parentNode (.-target event))]
(set! (.-draggable parent) false))
(swap! local assoc :edition true))]
(if (:edition @local)
[:input.element-name
{:type "text"
:on-blur on-blur
:on-key-down on-key-down
:auto-focus true
:default-value (:name shape "")}]
[:span.element-name
{:on-double-click on-click}
(:name shape "")])))
(mx/def shape-name
:mixins [mx/static (mx/local)]
:render
(fn [{:keys [::mx/local] :as own} {:keys [id] :as shape}]
(letfn [(on-blur [event]
(let [target (dom/event->target event)
parent (.-parentNode target)
name (dom/get-value target)]
(set! (.-draggable parent) true)
(st/emit! (uds/rename-shape id name))
(swap! local assoc :edition false)))
(on-key-down [event]
(js/console.log event)
(when (kbd/enter? event)
(on-blur event)))
(on-click [event]
(dom/prevent-default event)
(let [parent (.-parentNode (.-target event))]
(set! (.-draggable parent) false))
(swap! local assoc :edition true))]
(if (:edition @local)
[:input.element-name
{:type "text"
:on-blur on-blur
:on-key-down on-key-down
:auto-focus true
:default-value (:name shape "")}]
[:span.element-name
{:on-double-click on-click}
(:name shape "")]))))
;; --- Layer Simple (Component)
(mx/defcs layer-simple
{:mixins [mx/static (mx/local)]}
[{:keys [rum/local]} item selected]
[{:keys [::mx/local]} item selected]
(let [selected? (contains? selected (:id item))
select #(select-shape selected item %)
toggle-visibility #(toggle-visibility selected item %)
@ -189,14 +188,14 @@
{:class (when (:blocked item) "selected")
:on-click toggle-blocking}
i/lock]]
[:div.element-icon {} (element-icon item)]
[:div.element-icon (element-icon item)]
(shape-name item)]])))
;; --- Layer Group (Component)
(mx/defcs layer-group
{:mixins [mx/static mx/reactive (mx/local)]}
[{:keys [rum/local]} {:keys [id] :as item} selected]
[{:keys [::mx/local]} {:keys [id] :as item} selected]
(let [selected? (contains? selected (:id item))
collapsed? (:collapsed item true)
shapes-map (mx/react refs/shapes-by-id)

View file

@ -8,27 +8,27 @@
(ns uxbox.main.ui.workspace.sidebar.options
(:require
[lentes.core :as l]
[uxbox.util.i18n :refer [tr]]
[uxbox.util.router :as r]
[potok.core :as ptk]
[uxbox.main.store :as st]
[uxbox.main.data.workspace :as udw]
[uxbox.main.data.shapes :as uds]
[rumext.core :as mx :include-macros true]
[uxbox.builtins.icons :as i]
[uxbox.main.data.shapes :as uds]
[uxbox.main.data.workspace :as udw]
[uxbox.main.geom :as geom]
[uxbox.main.store :as st]
[uxbox.main.ui.shapes.attrs :refer [shape-default-attrs]]
[uxbox.main.ui.workspace.sidebar.options.circle-measures :as options-circlem]
[uxbox.main.ui.workspace.sidebar.options.fill :as options-fill]
[uxbox.main.ui.workspace.sidebar.options.icon-measures :as options-iconm]
[uxbox.main.ui.workspace.sidebar.options.image-measures :as options-imagem]
[uxbox.main.ui.workspace.sidebar.options.circle-measures :as options-circlem]
[uxbox.main.ui.workspace.sidebar.options.rect-measures :as options-rectm]
[uxbox.main.ui.workspace.sidebar.options.fill :as options-fill]
[uxbox.main.ui.workspace.sidebar.options.text :as options-text]
[uxbox.main.ui.workspace.sidebar.options.stroke :as options-stroke]
[uxbox.main.ui.workspace.sidebar.options.page :as options-page]
[uxbox.main.ui.workspace.sidebar.options.interactions :as options-interactions]
[uxbox.main.geom :as geom]
[uxbox.util.dom :as dom]
[uxbox.main.ui.workspace.sidebar.options.page :as options-page]
[uxbox.main.ui.workspace.sidebar.options.rect-measures :as options-rectm]
[uxbox.main.ui.workspace.sidebar.options.stroke :as options-stroke]
[uxbox.main.ui.workspace.sidebar.options.text :as options-text]
[uxbox.util.data :as data]
[rumext.core :as mx :include-macros true]))
[uxbox.util.dom :as dom]
[uxbox.util.i18n :refer [tr]]
[uxbox.util.router :as r]))
;; --- Constants
@ -89,18 +89,10 @@
;; --- Options
(defn- options-did-remount
[old-own own]
(let [[prev-shape] (:rum/args old-own)
[curr-shape] (:rum/args own)]
(when-not (= (:id prev-shape) (:id curr-shape))
(reset! (:rum/local own) {}))
own))
(mx/defcs options
{:mixins [mx/static (mx/local)]
:did-remount options-did-remount}
[{:keys [rum/local] :as own} shape]
:key-fn #(pr-str (:id %1))}
[{:keys [::mx/local] :as own} shape]
(let [menus (get +menus-map+ (:type shape ::page))
contained-in? (into #{} menus)
active (:menu @local (first menus))]

View file

@ -2,24 +2,25 @@
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) 2015-2016 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.workspace.sidebar.options.interactions
(:require [lentes.core :as l]
[uxbox.builtins.icons :as i]
[uxbox.util.i18n :refer [tr]]
[uxbox.util.router :as r]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.data.shapes :as uds]
[uxbox.main.data.lightbox :as udl]
[uxbox.main.ui.lightbox :as lbx]
[uxbox.main.ui.colorpicker :as cp]
[uxbox.util.dom :as dom]
[uxbox.util.data :refer [read-string]]
[uxbox.util.spec :refer [color?]]
[rumext.core :as mx :include-macros true]))
(:require
[lentes.core :as l]
[rumext.core :as mx :include-macros true]
[uxbox.builtins.icons :as i]
[uxbox.main.data.lightbox :as udl]
[uxbox.main.data.shapes :as uds]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.ui.colorpicker :as cp]
[uxbox.main.ui.lightbox :as lbx]
[uxbox.util.data :refer [read-string]]
[uxbox.util.dom :as dom]
[uxbox.util.i18n :refer [tr]]
[uxbox.util.router :as r]
[uxbox.util.spec :refer [color?]]))
;; --- Helpers
@ -473,7 +474,7 @@
(mx/defcs interactions-menu
{:mixins [mx/static (mx/local)]}
[own menu shape]
(let [local (:rum/local own)
(let [local (::mx/local own)
form-ref (l/derive (l/key :form) local)
interactions (:interactions shape)
create-interaction #(reset! form-ref {})]

View file

@ -22,7 +22,7 @@
(mx/defcs stroke-menu
{:mixins [mx/static (mx/local)]}
[{:keys [rum/local]} menu {:keys [id] :as shape}]
[{:keys [::mx/local]} menu {:keys [id] :as shape}]
(letfn [(on-width-change [event]
(let [value (-> (dom/event->value event)
(parse-float 1))]

View file

@ -6,119 +6,126 @@
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
(ns uxbox.main.ui.workspace.sidebar.sitemap
(:require [lentes.core :as l]
[cuerdas.core :as str]
[uxbox.builtins.icons :as i]
[uxbox.main.store :as st]
[uxbox.main.refs :as refs]
[uxbox.main.data.projects :as dp]
[uxbox.main.data.pages :as udp]
[uxbox.main.data.workspace :as dw]
[uxbox.main.data.lightbox :as udl]
[uxbox.main.ui.workspace.sidebar.sitemap-pageform]
[uxbox.main.ui.lightbox :as lbx]
[uxbox.util.i18n :refer (tr)]
[uxbox.util.router :as r]
[uxbox.util.data :refer [classnames]]
[uxbox.util.dom.dnd :as dnd]
[uxbox.util.dom :as dom]
[rumext.core :as mx :include-macros true]))
(:require
[cuerdas.core :as str]
[lentes.core :as l]
[rumext.core :as mx :include-macros true]
[uxbox.builtins.icons :as i]
[uxbox.main.data.lightbox :as udl]
[uxbox.main.data.pages :as udp]
[uxbox.main.data.projects :as dp]
[uxbox.main.data.workspace :as dw]
[uxbox.main.refs :as refs]
[uxbox.main.store :as st]
[uxbox.main.ui.lightbox :as lbx]
[uxbox.main.ui.workspace.sidebar.sitemap-pageform]
[uxbox.util.data :refer [classnames]]
[uxbox.util.dom :as dom]
[uxbox.util.dom.dnd :as dnd]
[uxbox.util.i18n :refer (tr)]
[uxbox.util.router :as r]))
(mx/defcs page-item
{:mixins [(mx/local) mx/static mx/reactive]}
[{:keys [rum/local] :as own} page total active?]
(let [body-classes (classnames
:selected active?
:drag-active (:dragging @local)
:drag-top (= :top (:over @local))
:drag-bottom (= :bottom (:over @local))
:drag-inside (= :middle (:over @local)))
li-classes (classnames
:selected active?
:hide (:dragging @local))]
(letfn [(on-edit [event]
(udl/open! :page-form {:page page}))
(mx/def page-item
:mixins [(mx/local) mx/static mx/reactive]
:key-fn :id
(on-navigate [event]
(st/emit! (dp/go-to (:project page) (:id page))))
:render
(fn [{:keys [::mx/local] :as own}
{:keys [::deletable? ::selected?] :as page}]
(let [body-classes (classnames
:selected selected?
:drag-active (:dragging @local)
:drag-top (= :top (:over @local))
:drag-bottom (= :bottom (:over @local))
:drag-inside (= :middle (:over @local)))
li-classes (classnames
:selected selected?
:hide (:dragging @local))]
(letfn [(on-edit [event]
(udl/open! :page-form {:page page}))
(delete []
(let [next #(st/emit! (dp/go-to (:project page)))]
(st/emit! (udp/delete-page (:id page) next))))
(on-navigate [event]
(st/emit! (dp/go-to (:project page) (:id page))))
(on-delete [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(udl/open! :confirm {:on-accept delete}))
(delete []
(let [next #(st/emit! (dp/go-to (:project page)))]
(st/emit! (udp/delete-page (:id page) next))))
(on-drag-start [event]
(let [target (dom/event->target event)]
(dnd/set-allowed-effect! event "move")
(dnd/set-data! event (:id page))
(dnd/set-image! event target 50 10)
(swap! local assoc :dragging true)))
(on-drag-end [event]
(swap! local assoc :dragging false :over nil))
(on-drop [event]
(dom/stop-propagation event)
(let [id (dnd/get-data event)
over (:over @local)]
(case (:over @local)
:top (let [new-order (dec (get-in page [:metadata :order]))]
(st/emit! (udp/update-order id new-order)))
:bottom (let [new-order (inc (get-in page [:metadata :order]))]
(st/emit! (udp/update-order id new-order))))
(swap! local assoc :dragging false :over nil)))
(on-drag-over [event]
(dom/prevent-default event)
(dnd/set-drop-effect! event "move")
(let [over (dnd/get-hover-position event false)]
(swap! local assoc :over over)))
(on-drag-enter [event]
(swap! local assoc :over true))
(on-drag-leave [event]
(swap! local assoc :over false))]
[:li {:class li-classes}
[:div.element-list-body
{:class body-classes
:style {:opacity (if (:dragging @local)
"0.5"
"1")}
:on-click on-navigate
:on-double-click #(dom/stop-propagation %)
:on-drag-start on-drag-start
:on-drag-enter on-drag-enter
:on-drag-leave on-drag-leave
:on-drag-over on-drag-over
:on-drag-end on-drag-end
:on-drop on-drop
:draggable true}
(on-delete [event]
(dom/prevent-default event)
(dom/stop-propagation event)
(udl/open! :confirm {:on-accept delete}))
[:div.page-icon {} i/page]
[:span {} (:name page)]
[:div.page-actions {}
[:a {:on-click on-edit} i/pencil]
(when (> total 1)
[:a {:on-click on-delete} i/trash])]]])))
(on-drag-start [event]
(let [target (dom/event->target event)]
(dnd/set-allowed-effect! event "move")
(dnd/set-data! event (:id page))
(dnd/set-image! event target 50 10)
(swap! local assoc :dragging true)))
(on-drag-end [event]
(swap! local assoc :dragging false :over nil))
(on-drop [event]
(dom/stop-propagation event)
(let [id (dnd/get-data event)
over (:over @local)]
(case (:over @local)
:top (let [new-order (dec (get-in page [:metadata :order]))]
(st/emit! (udp/update-order id new-order)))
:bottom (let [new-order (inc (get-in page [:metadata :order]))]
(st/emit! (udp/update-order id new-order))))
(swap! local assoc :dragging false :over nil)))
(on-drag-over [event]
(dom/prevent-default event)
(dnd/set-drop-effect! event "move")
(let [over (dnd/get-hover-position event false)]
(swap! local assoc :over over)))
(on-drag-enter [event]
(swap! local assoc :over true))
(on-drag-leave [event]
(swap! local assoc :over false))]
[:li {:class li-classes}
[:div.element-list-body
{:class body-classes
:style {:opacity (if (:dragging @local)
"0.5"
"1")}
:on-click on-navigate
:on-double-click #(dom/stop-propagation %)
:on-drag-start on-drag-start
:on-drag-enter on-drag-enter
:on-drag-leave on-drag-leave
:on-drag-over on-drag-over
:on-drag-end on-drag-end
:on-drop on-drop
:draggable true}
(mx/defc sitemap-toolbox
{:mixins [mx/static mx/reactive]}
[current]
(let [project (mx/react refs/selected-project)
pages (mx/react refs/selected-project-pages)
create #(udl/open! :page-form {:page {:project (:id project)}})
close #(st/emit! (dw/toggle-flag :sitemap))]
[:div.sitemap.tool-window {}
[:div.tool-window-bar {}
[:div.tool-window-icon {} i/project-tree]
[:span {} (tr "ds.sitemap")]
[:div.tool-window-close {:on-click close} i/close]]
[:div.tool-window-content {}
[:div.project-title {}
[:span {} (:name project)]
[:div.add-page {:on-click create} i/close]]
[:ul.element-list {}
(for [page pages]
(let [active? (= (:id page) current)]
(-> (page-item page (count pages) active?)
(mx/with-key (:id page)))))]]]))
[:div.page-icon {} i/page]
[:span {} (:name page)]
[:div.page-actions {}
[:a {:on-click on-edit} i/pencil]
(when deletable?
[:a {:on-click on-delete} i/trash])]]]))))
(mx/def sitemap-toolbox
:mixins [mx/static mx/reactive]
:render
(fn [own current-page-id]
(let [project (mx/react refs/selected-project)
pages (mx/react refs/selected-project-pages)
create #(udl/open! :page-form {:page {:project (:id project)}})
close #(st/emit! (dw/toggle-flag :sitemap))
deletable? (> (count pages) 1)]
[:div.sitemap.tool-window
[:div.tool-window-bar
[:div.tool-window-icon i/project-tree]
[:span (tr "ds.sitemap")]
[:div.tool-window-close {:on-click close} i/close]]
[:div.tool-window-content
[:div.project-title
[:span (:name project)]
[:div.add-page {:on-click create} i/close]]
[:ul.element-list
(for [page pages]
(let [selected? (= (:id page) current-page-id)]
(page-item (assoc page ::deletable? deletable? ::selected? selected?))))]]])))