0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-06 14:50:20 -05:00

WIP: workspace toolbar and project/page state management.

This commit is contained in:
Andrey Antukh 2015-12-15 13:00:10 +02:00
parent c62425cbc8
commit 688d94c1da
6 changed files with 264 additions and 141 deletions

View file

@ -3,6 +3,7 @@
[uxbox.router :as r]
[uxbox.state :as st]
[uxbox.schema :as sc]
[uxbox.time :as time]
[bouncer.validators :as v]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -39,14 +40,14 @@
(let [uuid (:id page)]
(update-in state [:pages-by-id] assoc uuid page)))
;; (defn project-pages
;; "Get a ordered list of pages that
;; belongs to a specified project."
;; [state projectid]
;; (let [xf (comp
;; (filter #(= projectid (:project %)))
;; (map #(get-in state [:pages-by-id %])))]
;; (into [] xf (:pages state))))
(defn project-pages
"Get a ordered list of pages that
belongs to a specified project."
[state projectid]
(->> (vals (:pages-by-id state))
(filter #(= projectid (:project %)))
(sort-by :created)
(into [])))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Events
@ -60,6 +61,7 @@
(-apply-update [_ state]
(let [page {:id (random-uuid)
:project project
:created (time/now :unix)
:name name
:width width
:height height}]
@ -79,6 +81,7 @@
(let [proj {:id uuid
:name name
:width width
:created (time/now :unix)
:height height
:layout layout}]
(assoc-project state proj)))
@ -99,7 +102,9 @@
(reify
rs/UpdateEvent
(-apply-update [_ state]
(assoc state :workspace {:project projectid :page pageid}))
(assoc state :workspace {:project projectid
:page pageid
:toolboxes {}}))
IPrintWithWriter
(-pr-writer [mv writer _]
@ -117,9 +122,10 @@
(if pageid
(rs/emit! (r/navigate :main/page {:project-uuid projectid
:page-uuid pageid}))
(let [pages (get-in state [:projects-by-id projectid :pages])]
(let [pages (project-pages state projectid)
pageid (:id (first pages))]
(rs/emit! (r/navigate :main/page {:project-uuid projectid
:page-uuid (first pages)})))))
:page-uuid pageid})))))
IPrintWithWriter
(-pr-writer [mv writer _]
(-write writer "#<event:u.s.p/go-to-project")))))

View file

@ -82,3 +82,13 @@
"Redirect the user to other url."
([name] (go name nil))
([name params] (rs/emit! (navigate name params))))
(defn route-for
"Given a location handler and optional parameter map, return the URI
for such handler and parameters."
([location]
(bidi/path-for routes location))
([location params]
(apply bidi/path-for routes location (into []
(mapcat (fn [[k v]] [k v]))
params))))

View file

@ -1,13 +1,37 @@
(ns uxbox.time
(:require cljsjs.moment))
(:require [cljsjs.moment]))
(defn parse
([v]
(js/moment v))
([v format]
(case format
:unix (js/moment.unix v)
(js/moment v format))))
(defn iso
[v]
(.toISOString v))
(defn unix
[v]
(.unix v))
(defn now
([]
(js/moment))
([format]
(case format
:unix (unix (now))
:iso (iso (now)))))
(defn ago
[time]
(.fromNow (js/moment time)))
(.fromNow (parse time)))
(defn day
[time]
(.calendar (js/moment. time)
(.calendar (parse time)
nil
#js {:sameDay "[Today]"
:sameElse "[Today]"

View file

@ -30,7 +30,6 @@
:main/colors (ui.elements/colors)
:main/page (let [projectid (:project-uuid location-params)
pageid (:page-uuid location-params)]
(rs/emit! (dp/initialize-workspace projectid pageid))
(ui.w/workspace projectid pageid))
nil
)])))

File diff suppressed because one or more lines are too long

View file

@ -10,92 +10,143 @@
[uxbox.data.projects :as dp]
[uxbox.ui.icons.dashboard :as icons]
[uxbox.ui.icons :as i]
[uxbox.ui.dom :as dom]
[uxbox.ui.header :as ui.h]
[uxbox.ui.lightbox :as lightbox]
[uxbox.time :refer [ago]]))
[uxbox.ui.header :as ui.h]
[uxbox.ui.users :as ui.u]
[uxbox.ui.navigation :as nav]
[uxbox.ui.dom :as dom]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Header
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (defn header-render
;; [conn page grid? project-bar-visible?]
;; (let [{page-title :page/title
;; page-width :page/width
;; page-height :page/height} page]
;; [:header#workspace-bar.workspace-bar
;; [:div.main-icon
;; (nav/link (nav/route-for :dashboard) icons/logo-icon)]
;; (project-tree page-title project-bar-visible?)
;; [:div.workspace-options
;; [:ul.options-btn
;; [:li.tooltip.tooltip-bottom {:alt "Undo (Ctrl + Z)"}
;; icons/undo]
;; [:li.tooltip.tooltip-bottom {:alt "Redo (Ctrl + Shift + Z)"}
;; icons/redo]]
;; [:ul.options-btn
;; ;; TODO: refactor
;; [:li.tooltip.tooltip-bottom
;; {:alt "Export (Ctrl + E)"}
;; ;; page-title
;; [:a {:download (str page-title ".svg")
;; :href "#"
;; :on-click (fn [e]
;; (let [innerHTML (.-innerHTML (.getElementById js/document "page-layout"))
;; width page-width
;; height page-height
;; html (str "<svg width='" width "' height='" height "'>" innerHTML "</svg>")
;; data (js/Blob. #js [html] #js {:type "application/octet-stream"})
;; url (.createObjectURL (.-URL js/window) data)]
;; (set! (.-href (.-currentTarget e)) url)))}
;; icons/export]]
;; [:li.tooltip.tooltip-bottom
;; {:alt "Image (Ctrl + I)"}
;; icons/image]]
;; [:ul.options-btn
;; [:li.tooltip.tooltip-bottom
;; {:alt "Ruler (Ctrl + R)"}
;; icons/ruler]
;; [:li.tooltip.tooltip-bottom
;; {:alt "Grid (Ctrl + G)"
;; :class (when (rum/react ws/grid?) "selected")
;; :on-click ws/toggle-grid!}
;; icons/grid]
;; [:li.tooltip.tooltip-bottom
;; {:alt "Align (Ctrl + A)"}
;; icons/alignment]
;; [:li.tooltip.tooltip-bottom
;; {:alt "Organize (Ctrl + O)"}
;; icons/organize]]]
;; (user conn)]))
;; (def header
;; (util/component
;; {:render header-render
;; :name "header"}))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Header
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def project-state
(def ^:static project-state
(as-> (util/dep-in [:projects-by-id] [:workspace :project]) $
(l/focus-atom $ s/state)))
(def page-state
(def ^:static page-state
(as-> (util/dep-in [:pages-by-id] [:workspace :page]) $
(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 "<svg width='" width "' height='" height "'>" content "</svg>")
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)]
(html
[:header#workspace-bar.workspace-bar
[:div.main-icon
(nav/link (r/route-for :dashboard) i/logo-icon)]
[:div.project-tree-btn
{:on-click (constantly nil)}
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 "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]}))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Header
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn workspace-render
[own projectid]
(html
[:div "hello world"
;; (header conn page ws/grid? project-bar-visible?)
;; [:main.main-content
;; [:section.workspace-content
;; ;; Toolbar
;; (toolbar open-toolboxes)
[:div
(header)
[:main.main-content
[:section.workspace-content
;; Toolbar
(toolbar)
;; ;; Project bar
;; (project-bar conn project page pages @project-bar-visible?)
;; ;; Rules
@ -106,11 +157,19 @@
;; ;; Aside
;; (when-not (empty? @open-toolboxes)
;; (aside conn open-toolboxes page shapes))
]))
]]]))
(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))
(def ^:static workspace
(util/component
{:render workspace-render
:will-mount workspace-will-mount
:name "workspace"
:mixins [rum/static]}))