From 62c5c8d5c877627cd5bc7a8e5ae12e0652f23ae8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 17 Dec 2015 12:51:36 +0200 Subject: [PATCH] WIP: --- frontend/uxbox/core.cljs | 5 +- frontend/uxbox/data/workspace.cljs | 2 - frontend/uxbox/ui.cljs | 35 +-- frontend/uxbox/ui/workspace.cljs | 284 +-------------------- frontend/uxbox/ui/workspace/base.cljs | 285 ++++++++++++++++++++++ frontend/uxbox/ui/workspace/rules.cljs | 104 ++++++++ frontend/uxbox/ui/workspace/workarea.cljs | 76 ++++++ resources/public/index.html | 4 +- 8 files changed, 500 insertions(+), 295 deletions(-) create mode 100644 frontend/uxbox/ui/workspace/base.cljs create mode 100644 frontend/uxbox/ui/workspace/rules.cljs create mode 100644 frontend/uxbox/ui/workspace/workarea.cljs diff --git a/frontend/uxbox/core.cljs b/frontend/uxbox/core.cljs index 20f87198f..131db1b9c 100644 --- a/frontend/uxbox/core.cljs +++ b/frontend/uxbox/core.cljs @@ -11,10 +11,9 @@ (enable-console-print!) -(let [dom (dom/getElement "app")] - (ui/mount! dom)) - (defonce +setup+ (do + (println "BOOTSTRAP") + (ui/init) (rs/emit! (dl/load-data)) (rx/on-value s/stream #(dl/persist-state %)))) diff --git a/frontend/uxbox/data/workspace.cljs b/frontend/uxbox/data/workspace.cljs index f2b5e92c0..9c010f73e 100644 --- a/frontend/uxbox/data/workspace.cljs +++ b/frontend/uxbox/data/workspace.cljs @@ -21,5 +21,3 @@ IPrintWithWriter (-pr-writer [mv writer _] (-write writer "#")))) - - diff --git a/frontend/uxbox/ui.cljs b/frontend/uxbox/ui.cljs index 62a1cb385..cee5a616f 100644 --- a/frontend/uxbox/ui.cljs +++ b/frontend/uxbox/ui.cljs @@ -1,5 +1,6 @@ (ns uxbox.ui (:require [sablono.core :as html :refer-macros [html]] + [goog.dom :as gdom] [rum.core :as rum] [cats.labs.lens :as l] [uxbox.state :as s] @@ -19,25 +20,25 @@ (defn app-render [own] (let [{:keys [location location-params] :as state} (rum/react state)] - (html - [:section - (ui.lb/lightbox) - (case location - :auth/login (ui.users/login) - :dashboard/projects (ui.dashboard.projects/projects) - :dashboard/elements (ui.dashboard.elements/elements) - :dashboard/icons (ui.dashboard.elements/icons) - :dashboard/colors (ui.dashboard.elements/colors) - :workspace/page (let [projectid (:project-uuid location-params) - pageid (:page-uuid location-params)] - (ui.w/workspace projectid pageid)) - nil - )]))) + (case location + :auth/login (ui.users/login) + :dashboard/projects (ui.dashboard.projects/projects) + :dashboard/elements (ui.dashboard.elements/elements) + :dashboard/icons (ui.dashboard.elements/icons) + :dashboard/colors (ui.dashboard.elements/colors) + :workspace/page (let [projectid (:project-uuid location-params) + pageid (:page-uuid location-params)] + (ui.w/workspace projectid pageid)) + nil + ))) (def app (util/component {:render app-render :mixins [rum/reactive] :name "app"})) -(defn mount! - [el] - (rum/mount (app) el)) +(defn init + [] + (let [app-dom (gdom/getElement "app") + lb-dom (gdom/getElement "lightbox")] + (rum/mount (app) app-dom) + (rum/mount (ui.lb/lightbox) lb-dom))) diff --git a/frontend/uxbox/ui/workspace.cljs b/frontend/uxbox/ui/workspace.cljs index 93542d4bf..15e1e46c4 100644 --- a/frontend/uxbox/ui/workspace.cljs +++ b/frontend/uxbox/ui/workspace.cljs @@ -1,271 +1,14 @@ (ns uxbox.ui.workspace (:require [sablono.core :as html :refer-macros [html]] [rum.core :as rum] - [cats.labs.lens :as l] - [cuerdas.core :as str] [uxbox.util :as util] [uxbox.router :as r] [uxbox.rstore :as rs] [uxbox.state :as s] [uxbox.data.projects :as dp] - [uxbox.data.workspace :as dw] - [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])) - -(def ^:static project-state - (as-> (util/dep-in [:projects-by-id] [:workspace :project]) $ - (l/focus-atom $ s/state))) - -(def ^:static page-state - (as-> (util/dep-in [:pages-by-id] [:workspace :page]) $ - (l/focus-atom $ s/state))) - -(def ^:static pages-state - (as-> (util/getter #(let [pid (get-in % [:workspace :project])] - (dp/project-pages % pid))) $ - (l/focus-atom $ s/state))) - -(def ^:static workspace-state - (as-> (l/in [:workspace]) $ - (l/focus-atom $ s/state))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 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] - (let [page (rum/react page-state) - toggle #(rs/emit! (dw/toggle-pagesbar))] - (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} - 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 (constantly nil)} - 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-primary.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 (:visible-pagebar 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 {}})]})) + [uxbox.ui.workspace.base :as wb] + [uxbox.ui.workspace.rules :as wr] + [uxbox.ui.workspace.workarea :as wa])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Workspace @@ -275,18 +18,20 @@ [own projectid] (html [:div - (header) + (wb/header) [:main.main-content [:section.workspace-content ;; Toolbar - (toolbar) + (wb/toolbar) ;; Project bar - (project-sidebar) - ;; ;; Rules - ;; (horizontal-rule (rum/react ws/zoom)) - ;; (vertical-rule (rum/react ws/zoom)) - ;; ;; Working area - ;; (working-area conn @open-toolboxes page project shapes (rum/react ws/zoom) (rum/react ws/grid?)) + (wb/project-sidebar) + ;; Rules + (wr/h-rule) + (wr/v-rule) + + ;; Canvas + (wa/working-area) + ;; (working-area conn @open-toolboxes page project shapes (rum/react ws/zoom) (rum/react ws/grid?)) ;; ;; Aside ;; (when-not (empty? @open-toolboxes) ;; (aside conn open-toolboxes page shapes)) @@ -295,15 +40,12 @@ (defn workspace-will-mount [own] (let [[projectid pageid] (:rum/props own)] - (println "workspace-will-mount" projectid pageid) (rs/emit! (dp/initialize-workspace projectid pageid)) own)) (defn workspace-transfer-state [old-state state] (let [[projectid pageid] (:rum/props state)] - (println "workspace-transfer-state" old-state) - (println "workspace-transfer-state" state) (rs/emit! (dp/initialize-workspace projectid pageid)))) (def ^:static workspace diff --git a/frontend/uxbox/ui/workspace/base.cljs b/frontend/uxbox/ui/workspace/base.cljs new file mode 100644 index 000000000..bb2725050 --- /dev/null +++ b/frontend/uxbox/ui/workspace/base.cljs @@ -0,0 +1,285 @@ +(ns uxbox.ui.workspace.base + (:require [sablono.core :as html :refer-macros [html]] + [rum.core :as rum] + [beicon.core :as rx] + [cats.labs.lens :as l] + [cuerdas.core :as str] + [uxbox.util :as util] + [uxbox.router :as r] + [uxbox.rstore :as rs] + [uxbox.state :as s] + [uxbox.data.projects :as dp] + [uxbox.data.workspace :as dw] + [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])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Lenses +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(def ^:static project-state + (as-> (util/dep-in [:projects-by-id] [:workspace :project]) $ + (l/focus-atom $ s/state))) + +(def ^:static page-state + (as-> (util/dep-in [:pages-by-id] [:workspace :page]) $ + (l/focus-atom $ s/state))) + +(def ^:static pages-state + (as-> (util/getter #(let [pid (get-in % [:workspace :project])] + (dp/project-pages % pid))) $ + (l/focus-atom $ s/state))) + +(def ^:static workspace-state + (as-> (l/in [:workspace]) $ + (l/focus-atom $ s/state))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Streams +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defonce scroll-bus (rx/bus)) +(defonce top-scroll-s (rx/dedupe (rx/map :top scroll-bus))) +(defonce left-scroll-s (rx/dedupe (rx/map :left scroll-bus))) + +(defonce top-scroll (rx/to-atom top-scroll-s)) +(defonce left-scroll (rx/to-atom left-scroll-s)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 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] + (let [page (rum/react page-state) + toggle #(rs/emit! (dw/toggle-pagesbar))] + (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} + 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 (constantly nil)} + 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-primary.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 (:visible-pagebar 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/rules.cljs b/frontend/uxbox/ui/workspace/rules.cljs new file mode 100644 index 000000000..a1c57b796 --- /dev/null +++ b/frontend/uxbox/ui/workspace/rules.cljs @@ -0,0 +1,104 @@ +(ns uxbox.ui.workspace.rules + (:require [sablono.core :as html :refer-macros [html]] + [rum.core :as rum] + [cuerdas.core :as str] + [beicon.core :as rx] + [uxbox.util :as util] + [uxbox.state :as s] + [uxbox.ui.dom :as dom] + [uxbox.ui.workspace.base :as wd])) + +(def viewport-height 3000) +(def viewport-width 3000) + +(def document-start-x 50) +(def document-start-y 50) + +(defn h-rule-render + [zoom] + (let [left (rum/react wd/left-scroll) + width viewport-width + start-width document-start-x + padding 20 + zoom 1 + big-ticks-mod (/ 100 zoom) + mid-ticks-mod (/ 50 zoom) + step-size 10 + ticks (concat (range (- padding start-width) 0 step-size) + (range 0 (- width start-width padding) step-size)) + lines (fn [position value padding] + (cond + (< (mod value big-ticks-mod) step-size) + (html + [:g + [:line {:x1 position :x2 position :y1 5 :y2 padding :stroke "#7f7f7f"}] + [:text {:x (+ position 2) :y 13 :fill "#7f7f7f" :style {:font-size "12px"}} value]]) + (< (mod value mid-ticks-mod) step-size) + (html + [:line {:key position :x1 position :x2 position :y1 10 :y2 padding :stroke "#7f7f7f"}]) + :else + (html + [:line {:key position :x1 position :x2 position :y1 15 :y2 padding :stroke "#7f7f7f"}])))] + (html + [:svg.horizontal-rule + {:width 3000 + :height 3000 + :style {:left (str (- (- left 50)) "px")}} + [:g + [:rect {:x padding :y 0 :width width :height padding :fill "#bab7b7"}] + [:rect {:x 0 :y 0 :width padding :height padding :fill "#bab7b7"}]] + [:g + (for [tick ticks] + (let [position (* (+ tick start-width) zoom)] + (rum/with-key (lines position tick padding) (str tick))))]]))) + +(def h-rule + (util/component + {:render h-rule-render + :name "h-rule" + :mixins [rum/reactive]})) + + +(defn v-rule-render + [zoom] + (let [height viewport-height + start-height document-start-y + top (rum/react wd/top-scroll) + zoom 1 + padding 20 + big-ticks-mod (/ 100 zoom) + mid-ticks-mod (/ 50 zoom) + step-size 10 + ticks (concat (range (- padding start-height) 0 step-size) + (range 0 (- height start-height padding) step-size)) + lines (fn [position value padding] + (cond + (< (mod value big-ticks-mod) step-size) + (html + [:g {:key position} + [:line {:y1 position :y2 position :x1 5 :x2 padding :stroke "#7f7f7f"}] + [:text {:y position :x 5 :transform (str/format "rotate(90 0 %s)" position) :fill "#7f7f7f" :style {:font-size "12px"}} value]]) + + (< (mod value mid-ticks-mod) step-size) + (html + [:line {:key position :y1 position :y2 position :x1 10 :x2 padding :stroke "#7f7f7f"}]) + + :else + (html + [:line {:key position :y1 position :y2 position :x1 15 :x2 padding :stroke "#7f7f7f"}])))] + (html + [:svg.vertical-rule + {:width 3000 + :height 3000 + :style {:top (str (- top) "px")}} + [:g + [:rect {:x 0 :y padding :height height :width padding :fill "#bab7b7"}] + (for [tick ticks] + (let [position (* (+ tick start-height) zoom)] + (rum/with-key (lines position tick padding) (str tick))))]]))) + +(def v-rule + (util/component + {:render v-rule-render + :name "v-rule" + :mixins [rum/reactive]})) diff --git a/frontend/uxbox/ui/workspace/workarea.cljs b/frontend/uxbox/ui/workspace/workarea.cljs new file mode 100644 index 000000000..60c8cc25b --- /dev/null +++ b/frontend/uxbox/ui/workspace/workarea.cljs @@ -0,0 +1,76 @@ +(ns uxbox.ui.workspace.workarea + (:require [sablono.core :as html :refer-macros [html]] + [rum.core :as rum] + [uxbox.util :as util] + [uxbox.router :as r] + [uxbox.rstore :as rs] + [uxbox.state :as s] + [uxbox.data.projects :as dp] + [uxbox.ui.workspace.base :as wb] + [uxbox.ui.workspace.rules :as wr])) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Coordinates Debug +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defonce canvas-coordinates (atom {})) + +(defn coordenates-render + [] + (let [[x y] (rum/react canvas-coordinates)] + (html + [:div + {:style {:position "absolute" :left "80px" :top "20px"}} + [:table + [:tr + [:td "X:"] + [:td (or x 1)]] + [:tr + [:td "Y:"] + [:td y]]]]))) + +(def coordinates + (util/component + {:render coordenates-render + :name "coordenates" + :mixins [rum/reactive]})) + +(defn background-render + [] + (html + [:rect + {:x 0 :y 0 :width "100%" :height "100%" :fill "white"}])) + +(def background + (util/component + {:render background-render + :name "background" + :mixins [rum/static]})) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Work Area +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn working-area-render + [own] + (html + [:section.workspace-canvas + #_{:class (when (empty? open-setting-boxes) + "no-tool-bar") + :on-scroll (constantly nil)} + #_(when (:selected page) + (element-options conn + page-cursor + project-cursor + zoom-cursor + shapes-cursor)) + (coordinates) + #_(viewport conn page shapes zoom grid?)])) + +(def working-area + (util/component + {:render working-area-render + :name "working-area" + :mixins []})) + diff --git a/resources/public/index.html b/resources/public/index.html index 1f9b6f2d1..c4806ce05 100644 --- a/resources/public/index.html +++ b/resources/public/index.html @@ -4,8 +4,8 @@ -
-
+
+