From e458ffe355361c0868d07f28fc63a77480ab3ff1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 17 Dec 2015 17:32:06 +0200 Subject: [PATCH] Reorganize workspace namespace. --- frontend/uxbox/data/workspace.cljs | 1 - frontend/uxbox/router.cljs | 1 + frontend/uxbox/ui/workspace.cljs | 9 +- frontend/uxbox/ui/workspace/base.cljs | 252 +------------------ frontend/uxbox/ui/workspace/header.cljs | 79 ++++++ frontend/uxbox/ui/workspace/leftsidebar.cljs | 131 ++++++++++ frontend/uxbox/ui/workspace/toolbar.cljs | 53 ++++ frontend/uxbox/ui/workspace/workarea.cljs | 5 +- 8 files changed, 273 insertions(+), 258 deletions(-) create mode 100644 frontend/uxbox/ui/workspace/header.cljs create mode 100644 frontend/uxbox/ui/workspace/leftsidebar.cljs create mode 100644 frontend/uxbox/ui/workspace/toolbar.cljs diff --git a/frontend/uxbox/data/workspace.cljs b/frontend/uxbox/data/workspace.cljs index 4269fa4d0..fd90f10a7 100644 --- a/frontend/uxbox/data/workspace.cljs +++ b/frontend/uxbox/data/workspace.cljs @@ -26,7 +26,6 @@ (reify rs/UpdateEvent (-apply-update [_ state] - (println "toggle-grid") (update-in state [:workspace :grid-enabled] (fnil not false))) IPrintWithWriter diff --git a/frontend/uxbox/router.cljs b/frontend/uxbox/router.cljs index 7cd88ed1b..3df27fa8d 100644 --- a/frontend/uxbox/router.cljs +++ b/frontend/uxbox/router.cljs @@ -11,6 +11,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Events ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (defn update-location [{:keys [handler route-params] :as params}] (reify diff --git a/frontend/uxbox/ui/workspace.cljs b/frontend/uxbox/ui/workspace.cljs index 98f1151dc..34aecf0e7 100644 --- a/frontend/uxbox/ui/workspace.cljs +++ b/frontend/uxbox/ui/workspace.cljs @@ -7,6 +7,9 @@ [uxbox.data.projects :as dp] [uxbox.ui.util :as util] [uxbox.ui.workspace.base :as wb] + [uxbox.ui.workspace.toolbar :as wt] + [uxbox.ui.workspace.leftsidebar :as wl] + [uxbox.ui.workspace.header :as wh] [uxbox.ui.workspace.rules :as wr] [uxbox.ui.workspace.workarea :as wa])) @@ -19,13 +22,13 @@ (println "workspace-render") (html [:div - (wb/header) + (wh/header) [:main.main-content [:section.workspace-content ;; Toolbar - (wb/toolbar) + (wt/toolbar) ;; Project bar - (wb/project-sidebar) + (wl/left-sidebar) ;; Rules (wr/h-rule) (wr/v-rule) diff --git a/frontend/uxbox/ui/workspace/base.cljs b/frontend/uxbox/ui/workspace/base.cljs index ae7bd0831..d8d53d2ac 100644 --- a/frontend/uxbox/ui/workspace/base.cljs +++ b/frontend/uxbox/ui/workspace/base.cljs @@ -1,23 +1,10 @@ (ns uxbox.ui.workspace.base - (:require [sablono.core :as html :refer-macros [html]] - [rum.core :as rum] - [beicon.core :as rx] + (:require [beicon.core :as rx] [cats.labs.lens :as l] - [cuerdas.core :as str] - [uxbox.router :as r] [uxbox.rstore :as rs] [uxbox.state :as s] [uxbox.data.projects :as dp] - [uxbox.data.workspace :as dw] - [uxbox.util.lens :as ul] - [uxbox.ui.icons.dashboard :as icons] - [uxbox.ui.icons :as i] - [uxbox.ui.lightbox :as lightbox] - [uxbox.ui.keyboard :as k] - [uxbox.ui.users :as ui.u] - [uxbox.ui.navigation :as nav] - [uxbox.ui.dom :as dom] - [uxbox.ui.util :as util])) + [uxbox.util.lens :as ul])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Lenses @@ -61,238 +48,3 @@ (def document-start-x 50) (def document-start-y 50) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Header -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defn on-download-clicked - [event page] - (let [content (.-innerHTML (.getElementById js/document "page-layout")) - width (:width page) - height (:height page) - html (str "" content "") - data (js/Blob. #js [html] #js {:type "application/octet-stream"}) - url (.createObjectURL (.-URL js/window) data)] - (set! (.-href (.-currentTarget event)) url))) - -(defn header-render - [own] - (letfn [(toggle-pagesbar [e] - (rs/emit! (dw/toggle-pagesbar))) - (toggle-grid [e] - (rs/emit! (dw/toggle-grid)))] - (let [page (rum/react page-state)] - (html - [:header#workspace-bar.workspace-bar - [:div.main-icon - (nav/link (r/route-for :dashboard/projects) i/logo-icon)] - [:div.project-tree-btn - {:on-click toggle-pagesbar} - i/project-tree - [:span (:name page)]] - [:div.workspace-options - [:ul.options-btn - [:li.tooltip.tooltip-bottom {:alt "Undo (Ctrl + Z)"} - i/undo] - [:li.tooltip.tooltip-bottom {:alt "Redo (Ctrl + Shift + Z)"} - i/redo]] - [:ul.options-btn - ;; TODO: refactor - [:li.tooltip.tooltip-bottom - {:alt "Export (Ctrl + E)"} - ;; page-title - [:a {:download (str (:name page) ".svg") - :href "#" :on-click on-download-clicked} - i/export]] - [:li.tooltip.tooltip-bottom - {:alt "Image (Ctrl + I)"} - i/image]] - [:ul.options-btn - [:li.tooltip.tooltip-bottom - {:alt "Ruler (Ctrl + R)"} - i/ruler] - [:li.tooltip.tooltip-bottom - {:alt "Grid (Ctrl + G)" - :class (when false "selected") - :on-click toggle-grid} - i/grid] - [:li.tooltip.tooltip-bottom - {:alt "Align (Ctrl + A)"} - i/alignment] - [:li.tooltip.tooltip-bottom - {:alt "Organize (Ctrl + O)"} - i/organize]]] - (ui.u/user)])))) - -(def header - (util/component - {:render header-render - :name "workspace-header" - :mixins [rum/reactive]})) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Toolbar -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(def ^:static toolbar-state - (as-> (l/in [:workspace :toolbars]) $ - (l/focus-atom $ s/state))) - -(defn- toggle-toolbox - [state item] - (update state item (fnil not false))) - -(defn toolbar-render - [own] - (let [state (rum/react toolbar-state)] - (html - [:div#tool-bar.tool-bar - [:div.tool-bar-inside - [:ul.main-tools - [:li.tooltip - {:alt "Shapes (Ctrl + Shift + F)" - :class (when (:tools state) "current") - :on-click #(swap! toolbar-state toggle-toolbox :tools)} - i/shapes] - [:li.tooltip - {:alt "Icons (Ctrl + Shift + I)" - :class (when (:icons state) "current") - :on-click #(swap! toolbar-state toggle-toolbox :icons)} - i/icon-set] - [:li.tooltip - {:alt "Elements (Ctrl + Shift + L)" - :class (when (:layers state) - "current") - :on-click #(swap! toolbar-state toggle-toolbox :layers)} - i/layers] - [:li.tooltip - {:alt "Feedback (Ctrl + Shift + M)"} - i/chat]]]]))) - -(def ^:static toolbar - (util/component - {:render toolbar-render - :name "toolbar" - :mixins [rum/reactive]})) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Project Bar -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defn- project-sidebar-pageitem-render - [own parent page numpages] - (letfn [(on-edit [e] - (let [data {:edit true :form page}] - (reset! parent data)))] - (let [curpage (rum/react page-state) - active? (= (:id curpage) (:id page)) - deletable? (> numpages 1) - navigate #(rs/emit! (dp/go-to-project (:project page) (:id page))) - delete #(rs/emit! (dp/delete-page (:id page)))] - (html - [:li.single-page - {:class (when active? "current") - :on-click navigate} - [:div.tree-icon i/page] - [:span (:name page)] - [:div.options - [:div {:on-click on-edit} i/pencil] - [:div {:class (when-not deletable? "hide") - :on-click delete} - i/trash]]])))) - -(def project-sidebar-pageitem - (util/component - {:render project-sidebar-pageitem-render - :name "project-sidebar-pageitem" - :mixins [rum/reactive]})) - -(defn- project-sidebar-pagelist-render - [own parent] - (let [project (rum/react project-state) - pages (rum/react pages-state) - name (:name project)] - (html - [:div.project-bar-inside - [:span.project-name name] - [:ul.tree-view - (for [page pages] - (let [component (project-sidebar-pageitem parent page (count pages))] - (rum/with-key component (str (:id page)))))] - [:button.btn-primary.btn-small - {:on-click #(reset! parent {:edit true :form {}})} - "+ Add new page"]]))) - -(def project-sidebar-pagelist - (util/component - {:render project-sidebar-pagelist-render - :name "project-sidebar-pagelist" - :mixins [rum/reactive]})) - -(defn- project-sidebar-form-render - [own parent] - (let [form (:form @parent) - project @project-state] - (letfn [(on-change [e] - (let [value (dom/event->value e)] - (swap! parent assoc-in [:form :name] value))) - (persist [] - (if (nil? (:id form)) - (let [data {:project (:id project) - :width (:width project) - :height (:height project) - :name (:name form)}] - (rs/emit! (dp/create-page data)) - (reset! parent {:edit false})) - (do - (rs/emit! (dp/update-page-name (:id form) (:name form))) - (reset! parent {:edit false})))) - (on-save [e] - (persist)) - (on-key-up [e] - (when (k/enter? e) - (persist))) - (on-cancel [e] - (reset! parent {:edit false}))] - (html - [:div.project-bar-inside - [:input.input-text - {:name "test" - :auto-focus true - :placeholder "Page title" - :type "text" - :value (get-in @parent [:form :name] "") - :on-change on-change - :on-key-up on-key-up}] - [:button.btn-primary.btn-small - {:disabled (str/empty? (str/trim (get-in @parent [:form :name] ""))) - :on-click on-save} - "Save"] - [:button.btn-delete.btn-small - {:on-click on-cancel} - "Cancel"]])))) - -(def project-sidebar-form - (util/component - {:render project-sidebar-form-render - :name "project-sidebar-form" - :mixins [rum/reactive]})) - -(defn project-sidebar-render - [own] - (let [local (:rum/local own) - workspace (rum/react workspace-state) - project (rum/react project-state)] - (html - [:div#project-bar.project-bar - (when-not (:pagesbar-enabled workspace false) - {:class "toggle"}) - (if (:edit @local) - (project-sidebar-form local) - (project-sidebar-pagelist local))]))) - -(def project-sidebar - (util/component - {:render project-sidebar-render - :name "project-sidebar" - :mixins [rum/reactive (rum/local {:edit false :form {}})]})) diff --git a/frontend/uxbox/ui/workspace/header.cljs b/frontend/uxbox/ui/workspace/header.cljs new file mode 100644 index 000000000..f1ad0f1b0 --- /dev/null +++ b/frontend/uxbox/ui/workspace/header.cljs @@ -0,0 +1,79 @@ +(ns uxbox.ui.workspace.header + (:require [sablono.core :as html :refer-macros [html]] + [rum.core :as rum] + [beicon.core :as rx] + [uxbox.router :as r] + [uxbox.rstore :as rs] + [uxbox.data.workspace :as dw] + [uxbox.ui.workspace.base :as wb] + [uxbox.ui.icons :as i] + [uxbox.ui.users :as ui.u] + [uxbox.ui.navigation :as nav] + [uxbox.ui.util :as util])) + +(defn on-download-clicked + [event page] + (let [content (.-innerHTML (.getElementById js/document "page-layout")) + width (:width page) + height (:height page) + html (str "" content "") + data (js/Blob. #js [html] #js {:type "application/octet-stream"}) + url (.createObjectURL (.-URL js/window) data)] + (set! (.-href (.-currentTarget event)) url))) + +(defn header-render + [own] + (letfn [(toggle-pagesbar [e] + (rs/emit! (dw/toggle-pagesbar))) + (toggle-grid [e] + (rs/emit! (dw/toggle-grid)))] + (let [page (rum/react wb/page-state) + workspace (rum/react wb/workspace-state)] + (html + [:header#workspace-bar.workspace-bar + [:div.main-icon + (nav/link (r/route-for :dashboard/projects) i/logo-icon)] + [:div.project-tree-btn + {:on-click toggle-pagesbar} + i/project-tree + [:span (:name page)]] + [:div.workspace-options + [:ul.options-btn + [:li.tooltip.tooltip-bottom {:alt "Undo (Ctrl + Z)"} + i/undo] + [:li.tooltip.tooltip-bottom {:alt "Redo (Ctrl + Shift + Z)"} + i/redo]] + [:ul.options-btn + ;; TODO: refactor + [:li.tooltip.tooltip-bottom + {:alt "Export (Ctrl + E)"} + ;; page-title + [:a {:download (str (:name page) ".svg") + :href "#" :on-click on-download-clicked} + i/export]] + [:li.tooltip.tooltip-bottom + {:alt "Image (Ctrl + I)"} + i/image]] + [:ul.options-btn + [:li.tooltip.tooltip-bottom + {:alt "Ruler (Ctrl + R)"} + i/ruler] + [:li.tooltip.tooltip-bottom + {:alt "Grid (Ctrl + G)" + :class (when (:grid-enabled workspace) "selected") + :on-click toggle-grid} + i/grid] + [:li.tooltip.tooltip-bottom + {:alt "Align (Ctrl + A)"} + i/alignment] + [:li.tooltip.tooltip-bottom + {:alt "Organize (Ctrl + O)"} + i/organize]]] + (ui.u/user)])))) + +(def header + (util/component + {:render header-render + :name "workspace-header" + :mixins [rum/reactive]})) + diff --git a/frontend/uxbox/ui/workspace/leftsidebar.cljs b/frontend/uxbox/ui/workspace/leftsidebar.cljs new file mode 100644 index 000000000..dad3aba9d --- /dev/null +++ b/frontend/uxbox/ui/workspace/leftsidebar.cljs @@ -0,0 +1,131 @@ +(ns uxbox.ui.workspace.leftsidebar + (:require [sablono.core :as html :refer-macros [html]] + [rum.core :as rum] + [cuerdas.core :as str] + [uxbox.rstore :as rs] + [uxbox.data.projects :as dp] + [uxbox.ui.icons :as i] + [uxbox.ui.keyboard :as k] + [uxbox.ui.mixins :as mx] + [uxbox.ui.workspace.base :as wb] + [uxbox.ui.dom :as dom] + [uxbox.ui.util :as util])) + +(defn- project-sidebar-pageitem-render + [own parent page numpages] + (letfn [(on-edit [e] + (let [data {:edit true :form page}] + (reset! parent data)))] + + (let [curpage (rum/react wb/page-state) + active? (= (:id curpage) (:id page)) + deletable? (> numpages 1) + navigate #(rs/emit! (dp/go-to-project (:project page) (:id page))) + delete #(rs/emit! (dp/delete-page (:id page)))] + (html + [:li.single-page + {:class (when active? "current") + :on-click navigate} + [:div.tree-icon i/page] + [:span (:name page)] + [:div.options + [:div {:on-click on-edit} i/pencil] + [:div {:class (when-not deletable? "hide") + :on-click delete} + i/trash]]])))) + +(def project-sidebar-pageitem + (util/component + {:render project-sidebar-pageitem-render + :name "project-sidebar-pageitem" + :mixins [rum/reactive]})) + +(defn- project-sidebar-pagelist-render + [own parent] + (let [project (rum/react wb/project-state) + pages (rum/react wb/pages-state) + name (:name project)] + (html + [:div.project-bar-inside + [:span.project-name name] + [:ul.tree-view + (for [page pages] + (let [component (project-sidebar-pageitem parent page (count pages))] + (rum/with-key component (str (:id page)))))] + [:button.btn-primary.btn-small + {:on-click #(reset! parent {:edit true :form {}})} + "+ Add new page"]]))) + +(def project-sidebar-pagelist + (util/component + {:render project-sidebar-pagelist-render + :name "project-sidebar-pagelist" + :mixins [rum/reactive]})) + +(defn- project-sidebar-form-render + [own parent] + (let [form (:form @parent) + project @wb/project-state] + (letfn [(on-change [e] + (let [value (dom/event->value e)] + (swap! parent assoc-in [:form :name] value))) + (persist [] + (if (nil? (:id form)) + (let [data {:project (:id project) + :width (:width project) + :height (:height project) + :name (:name form)}] + (rs/emit! (dp/create-page data)) + (reset! parent {:edit false})) + (do + (rs/emit! (dp/update-page-name (:id form) (:name form))) + (reset! parent {:edit false})))) + (on-save [e] + (persist)) + (on-key-up [e] + (when (k/enter? e) + (persist))) + (on-cancel [e] + (reset! parent {:edit false}))] + (html + [:div.project-bar-inside + [:input.input-text + {:name "test" + :auto-focus true + :placeholder "Page title" + :type "text" + :value (get-in @parent [:form :name] "") + :on-change on-change + :on-key-up on-key-up}] + [:button.btn-primary.btn-small + {:disabled (str/empty? (str/trim (get-in @parent [:form :name] ""))) + :on-click on-save} + "Save"] + [:button.btn-delete.btn-small + {:on-click on-cancel} + "Cancel"]])))) + +(def project-sidebar-form + (util/component + {:render project-sidebar-form-render + :name "project-sidebar-form" + :mixins [rum/reactive]})) + +(defn left-sidebar-render + [own] + (let [local (:rum/local own) + workspace (rum/react wb/workspace-state) + project (rum/react wb/project-state)] + (html + [:div#project-bar.project-bar + (when-not (:pagesbar-enabled workspace false) + {:class "toggle"}) + (if (:edit @local) + (project-sidebar-form local) + (project-sidebar-pagelist local))]))) + +(def left-sidebar + (util/component + {:render left-sidebar-render + :name "left-sidebar" + :mixins [rum/reactive (mx/local {:edit false :form {}})]})) diff --git a/frontend/uxbox/ui/workspace/toolbar.cljs b/frontend/uxbox/ui/workspace/toolbar.cljs new file mode 100644 index 000000000..d559b006f --- /dev/null +++ b/frontend/uxbox/ui/workspace/toolbar.cljs @@ -0,0 +1,53 @@ +(ns uxbox.ui.workspace.toolbar + (:require [sablono.core :as html :refer-macros [html]] + [rum.core :as rum] + [cats.labs.lens :as l] + [uxbox.rstore :as rs] + [uxbox.state :as s] + [uxbox.ui.icons :as i] + [uxbox.ui.util :as util])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Toolbar +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(def ^:static toolbar-state + (as-> (l/in [:workspace :toolbars]) $ + (l/focus-atom $ s/state))) + +(defn- toggle-toolbox + [state item] + (update state item (fnil not false))) + +(defn toolbar-render + [own] + (let [state (rum/react toolbar-state)] + (html + [:div#tool-bar.tool-bar + [:div.tool-bar-inside + [:ul.main-tools + [:li.tooltip + {:alt "Shapes (Ctrl + Shift + F)" + :class (when (:tools state) "current") + :on-click #(swap! toolbar-state toggle-toolbox :tools)} + i/shapes] + [:li.tooltip + {:alt "Icons (Ctrl + Shift + I)" + :class (when (:icons state) "current") + :on-click #(swap! toolbar-state toggle-toolbox :icons)} + i/icon-set] + [:li.tooltip + {:alt "Elements (Ctrl + Shift + L)" + :class (when (:layers state) + "current") + :on-click #(swap! toolbar-state toggle-toolbox :layers)} + i/layers] + [:li.tooltip + {:alt "Feedback (Ctrl + Shift + M)"} + i/chat]]]]))) + +(def ^:static toolbar + (util/component + {:render toolbar-render + :name "toolbar" + :mixins [rum/reactive]})) diff --git a/frontend/uxbox/ui/workspace/workarea.cljs b/frontend/uxbox/ui/workspace/workarea.cljs index 9dfbff67b..9b519da60 100644 --- a/frontend/uxbox/ui/workspace/workarea.cljs +++ b/frontend/uxbox/ui/workspace/workarea.cljs @@ -58,7 +58,6 @@ (defn grid-render [own enabled? width height start-width start-height zoom] - (println "grid-render") (letfn [(vertical-line [position value padding] (let [ticks-mod (/ 100 zoom) step-size (/ 10 zoom)] @@ -193,7 +192,6 @@ [] (let [workspace (rum/react wb/workspace-state) zoom 1] - (println "viewport-render" (:grid-enabled workspace true)) (html [:svg#viewport {:width wb/viewport-height @@ -208,7 +206,7 @@ :viewport-width wb/viewport-width :document-start-x wb/document-start-x :document-start-y wb/document-start-y}) - (grid (:grid-enabled workspace true) + (grid (:grid-enabled workspace false) wb/viewport-width wb/viewport-height wb/document-start-x @@ -227,7 +225,6 @@ (defn working-area-render [own] - (println "working-area-render") (html [:section.workspace-canvas {:class "no-tool-bar"}