mirror of
https://github.com/penpot/penpot.git
synced 2025-05-31 00:56:12 +02:00
🚧 More work on dashboard base model refactor (frontend).
This commit is contained in:
parent
932d5bb004
commit
9bb5be306f
16 changed files with 563 additions and 522 deletions
|
@ -11,19 +11,25 @@
|
|||
[uxbox.main.ui.dashboard.colors :as colors]
|
||||
[uxbox.main.ui.messages :refer [messages-widget]]))
|
||||
|
||||
(defn- parse-route
|
||||
[{:keys [params data] :as route}]
|
||||
(let [{:keys [id type]} (:query params)
|
||||
id (cond
|
||||
(str/digits? id) (parse-int id)
|
||||
(uuid-str? id) (uuid id)
|
||||
:else nil)
|
||||
type (when (str/alpha? type) (keyword type))]
|
||||
[(:name data) type id]))
|
||||
|
||||
(mf/defc dashboard
|
||||
(mf/defc dashboard-projects
|
||||
[{:keys [route] :as props}]
|
||||
(let [[section type id] (parse-route route)]
|
||||
(let [id (get-in route [:params :query :project-id])
|
||||
id (when (uuid-str? id) (uuid id))]
|
||||
[:main.dashboard-main
|
||||
[:& messages-widget]
|
||||
[:& header {:section :dashboard/projects}]
|
||||
[:& projects/projects-page {:id id}]]))
|
||||
|
||||
(mf/defc dashboard-assets
|
||||
[{:keys [route] :as props}]
|
||||
(let [section (:name route)
|
||||
{:keys [id type]} (get-in route [:params :query])
|
||||
id (cond
|
||||
;; (str/digits? id) (parse-int id)
|
||||
(uuid-str? id) (uuid id)
|
||||
(str/empty-or-nil? id) nil
|
||||
:else id)
|
||||
type (when (str/alpha? type) (keyword type))]
|
||||
[:main.dashboard-main
|
||||
[:& messages-widget]
|
||||
[:& header {:section section}]
|
||||
|
@ -34,8 +40,5 @@
|
|||
:dashboard/images
|
||||
[:& images/images-page {:type type :id id}]
|
||||
|
||||
:dashboard/projects
|
||||
[:& projects/projects-page]
|
||||
|
||||
:dashboard/colors
|
||||
[:& colors/colors-page {:type type :id id}])]))
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
(-> (l/in [:dashboard :icons])
|
||||
(l/derive st/state)))
|
||||
|
||||
;; --- Page Title
|
||||
;; --- Component: Grid Header
|
||||
|
||||
(mf/defc grid-header
|
||||
[{:keys [coll] :as props}]
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
;; Copyright (c) 2015-2017 Juan de la Cruz <delacruzgarciajuan@gmail.com>
|
||||
|
||||
(ns uxbox.main.ui.dashboard.projects
|
||||
(:refer-clojure :exclude [sort-by])
|
||||
(:require
|
||||
[cuerdas.core :as str]
|
||||
[lentes.core :as l]
|
||||
|
@ -18,10 +19,11 @@
|
|||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.main.ui.confirm :refer [confirm-dialog]]
|
||||
[uxbox.main.ui.dashboard.projects-forms :refer [create-project-dialog]]
|
||||
[uxbox.main.ui.dashboard.common :as common]
|
||||
[uxbox.util.data :refer [read-string]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.i18n :as t :refer [tr]]
|
||||
[uxbox.util.router :as r]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.time :as dt]))
|
||||
|
||||
;; --- Helpers & Constants
|
||||
|
@ -33,7 +35,7 @@
|
|||
;; --- Refs
|
||||
|
||||
(def opts-iref
|
||||
(-> (l/in [:dashboard :projects])
|
||||
(-> (l/key :dashboard-projects)
|
||||
(l/derive st/state)))
|
||||
|
||||
(def projects-iref
|
||||
|
@ -42,160 +44,246 @@
|
|||
|
||||
;; --- Helpers
|
||||
|
||||
(defn sort-projects-by
|
||||
[ordering projs]
|
||||
(defn sort-by
|
||||
[ordering files]
|
||||
(case ordering
|
||||
:name (sort-by :name projs)
|
||||
:created (reverse (sort-by :created-at projs))
|
||||
projs))
|
||||
:name (cljs.core/sort-by :name files)
|
||||
:created (reverse (cljs.core/sort-by :created-at files))
|
||||
files))
|
||||
|
||||
(defn contains-term?
|
||||
[phrase term]
|
||||
(let [term (name term)]
|
||||
(str/includes? (str/lower phrase) (str/trim (str/lower term)))))
|
||||
|
||||
(defn filter-projects-by
|
||||
[term projs]
|
||||
(defn filter-by
|
||||
[term files]
|
||||
(if (str/blank? term)
|
||||
projs
|
||||
(filter #(contains-term? (:name %) term) projs)))
|
||||
files
|
||||
(filter #(contains-term? (:name %) term) files)))
|
||||
|
||||
;; --- Menu (Filter & Sort)
|
||||
|
||||
(mf/def menu
|
||||
:mixins #{mf/memo mf/reactive}
|
||||
:init
|
||||
(fn [own props]
|
||||
(assoc own ::num-projects (-> (comp (l/key :projects)
|
||||
(l/lens #(-> % vals count)))
|
||||
(l/derive st/state))))
|
||||
:render
|
||||
(fn [own {:keys [opts] :as props}]
|
||||
(let [ordering (:order opts :created)
|
||||
filtering (:filter opts "")
|
||||
num-projects (mf/react (::num-projects own))]
|
||||
(letfn [(on-term-change [event]
|
||||
(let [term (-> (dom/get-target event)
|
||||
(dom/get-value))]
|
||||
(st/emit! (udp/update-opts :filter term))))
|
||||
(on-ordering-change [event]
|
||||
(let [value (dom/event->value event)
|
||||
value (read-string value)]
|
||||
(st/emit! (udp/update-opts :order value))))
|
||||
(on-clear [event]
|
||||
(st/emit! (udp/update-opts :filter "")))]
|
||||
[:section.dashboard-bar
|
||||
[:div.dashboard-info
|
||||
(mf/defc menu
|
||||
[{:keys [opts files] :as props}]
|
||||
(let [ordering (:order opts :created)
|
||||
filtering (:filter opts "")
|
||||
|
||||
;; Counter
|
||||
[:span.dashboard-images (tr "ds.num-projects" (t/c num-projects))]
|
||||
on-term-change
|
||||
(fn [event]
|
||||
(let [term (-> (dom/get-target event)
|
||||
(dom/get-value))]
|
||||
(st/emit! (udp/update-opts :filter term))))
|
||||
|
||||
;; Sorting
|
||||
[:div
|
||||
[:span (tr "ds.ordering")]
|
||||
[:select.input-select
|
||||
{:on-change on-ordering-change
|
||||
:value (pr-str ordering)}
|
||||
(for [[key value] (seq +ordering-options+)]
|
||||
(let [key (pr-str key)]
|
||||
[:option {:key key :value key} (tr value)]))]]
|
||||
;; Search
|
||||
[:form.dashboard-search
|
||||
[:input.input-text
|
||||
{:key :images-search-box
|
||||
:type "text"
|
||||
:on-change on-term-change
|
||||
:auto-focus true
|
||||
:placeholder (tr "ds.search.placeholder")
|
||||
:value (or filtering "")}]
|
||||
[:div.clear-search {:on-click on-clear} i/close]]]]))))
|
||||
on-order-change
|
||||
(fn [event]
|
||||
(let [value (dom/event->value event)
|
||||
value (read-string value)]
|
||||
(st/emit! (udp/update-opts :order value))))
|
||||
|
||||
on-clear
|
||||
(fn [event]
|
||||
(st/emit! (udp/update-opts :filter "")))]
|
||||
|
||||
[:section.dashboard-bar.library-gap
|
||||
[:div.dashboard-info
|
||||
|
||||
;; Counter
|
||||
[:span.dashboard-images (tr "ds.num-files" (t/c (count files)))]
|
||||
|
||||
[:div
|
||||
;; Sorting
|
||||
;; TODO: convert to separate component?
|
||||
[:span (tr "ds.ordering")]
|
||||
[:select.input-select {:on-change on-order-change
|
||||
:value (pr-str ordering)}
|
||||
(for [[key value] (seq +ordering-options+)]
|
||||
(let [key (pr-str key)]
|
||||
[:option {:key key :value key} (tr value)]))]]
|
||||
|
||||
;; Search
|
||||
;; TODO: convert to separate component?
|
||||
[:form.dashboard-search
|
||||
[:input.input-text
|
||||
{:key :images-search-box
|
||||
:type "text"
|
||||
:on-change on-term-change
|
||||
:auto-focus true
|
||||
:placeholder (tr "ds.search.placeholder")
|
||||
:value (or filtering "")}]
|
||||
[:div.clear-search {:on-click on-clear} i/close]]]]))
|
||||
|
||||
;; --- Grid Item Thumbnail
|
||||
|
||||
(mf/defc grid-item-thumbnail
|
||||
[{:keys [project] :as props}]
|
||||
[:div.grid-item-th
|
||||
[:img.img-th {:src "/images/project-placeholder.svg"
|
||||
:alt (tr "ds.project-thumbnail.alt")}]])
|
||||
[:img.img-th {:src "/images/project-placeholder.svg"}]])
|
||||
|
||||
;; --- Grid Item
|
||||
|
||||
(mf/defc grid-item
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[{:keys [project] :as props}]
|
||||
[{:keys [file] :as props}]
|
||||
(let [local (mf/use-state {})
|
||||
on-navigate #(st/emit! (udp/go-to (:id project)))
|
||||
delete #(st/emit! (udp/delete-project project))
|
||||
on-delete #(do
|
||||
(dom/stop-propagation %)
|
||||
(modal/show! confirm-dialog {:on-accept delete}))
|
||||
on-blur #(let [target (dom/event->target %)
|
||||
name (dom/get-value target)
|
||||
id (:id project)]
|
||||
(swap! local assoc :edition false)
|
||||
(st/emit! (udp/rename-project id name)))
|
||||
on-key-down #(when (kbd/enter? %) (on-blur %))
|
||||
on-edit #(do
|
||||
(dom/stop-propagation %)
|
||||
(dom/prevent-default %)
|
||||
(swap! local assoc :edition true))]
|
||||
on-navigate #(st/emit! (udp/go-to (:id file)))
|
||||
;; delete #(st/emit! (udp/delete-project project))
|
||||
;; on-delete #(do
|
||||
;; (dom/stop-propagation %)
|
||||
;; (modal/show! confirm-dialog {:on-accept delete}))
|
||||
;; on-blur #(let [target (dom/event->target %)
|
||||
;; name (dom/get-value target)
|
||||
;; id (:id project)]
|
||||
;; (swap! local assoc :edition false)
|
||||
;; (st/emit! (udp/rename-project id name)))
|
||||
;; on-key-down #(when (kbd/enter? %) (on-blur %))
|
||||
;; on-edit #(do
|
||||
;; (dom/stop-propagation %)
|
||||
;; (dom/prevent-default %)
|
||||
;; (swap! local assoc :edition true))
|
||||
]
|
||||
[:div.grid-item.project-th {:on-click on-navigate}
|
||||
[:& grid-item-thumbnail {:project project
|
||||
:key (select-keys project [:id :page-id])}]
|
||||
[:& grid-item-thumbnail {:file file}]
|
||||
[:div.item-info
|
||||
(if (:edition @local)
|
||||
[:input.element-name {:type "text"
|
||||
:auto-focus true
|
||||
:on-key-down on-key-down
|
||||
:on-blur on-blur
|
||||
:on-click on-edit
|
||||
:default-value (:name project)}]
|
||||
[:h3 (:name project)])
|
||||
;; :on-key-down on-key-down
|
||||
;; :on-blur on-blur
|
||||
;; :on-click on-edit
|
||||
:default-value (:name file)}]
|
||||
[:h3 (:name file)])
|
||||
[:span.date
|
||||
(str (tr "ds.updated-at" (dt/timeago (:modified-at project))))]]
|
||||
(str (tr "ds.updated-at" (dt/timeago (:modified-at file))))]]
|
||||
|
||||
[:div.project-th-actions
|
||||
[:div.project-th-icon.pages
|
||||
i/page
|
||||
[:span (:total-pages project)]]
|
||||
#_[:span (:total-pages project)]]
|
||||
#_[:div.project-th-icon.comments
|
||||
i/chat
|
||||
[:span "0"]]
|
||||
[:div.project-th-icon.edit
|
||||
{:on-click on-edit}
|
||||
#_{:on-click on-edit}
|
||||
i/pencil]
|
||||
[:div.project-th-icon.delete
|
||||
{:on-click on-delete}
|
||||
#_{:on-click on-delete}
|
||||
i/trash]]]))
|
||||
|
||||
;; --- Grid
|
||||
|
||||
(mf/defc grid
|
||||
[{:keys [opts] :as props}]
|
||||
[{:keys [opts files] :as props}]
|
||||
(let [order (:order opts :created)
|
||||
filter (:filter opts "")
|
||||
projects (mf/deref projects-iref)
|
||||
projects (->> (vals projects)
|
||||
(filter-projects-by filter)
|
||||
(sort-projects-by order))
|
||||
files (->> files
|
||||
(filter-by filter)
|
||||
(sort-by order))
|
||||
on-click #(do
|
||||
(dom/prevent-default %)
|
||||
(modal/show! create-project-dialog {})
|
||||
#_(udl/open! :create-project))]
|
||||
#_(modal/show! create-project-dialog {})
|
||||
#_(udl/open! :create-project))
|
||||
]
|
||||
[:section.dashboard-grid
|
||||
[:h2 (tr "ds.project-title")]
|
||||
[:h2 (tr "ds.projects.file-name")]
|
||||
[:div.dashboard-grid-content
|
||||
[:div.dashboard-grid-row
|
||||
[:div.grid-item.add-project {:on-click on-click}
|
||||
[:span (tr "ds.project-new")]]
|
||||
[:div.grid-item.add-project #_{:on-click on-click}
|
||||
[:span (tr "ds.project-file")]]
|
||||
(for [item files]
|
||||
[:& grid-item {:file item :key (:id item)}])]]]))
|
||||
|
||||
;; --- Component: Nav
|
||||
|
||||
;; (letfn [(on-click [event]
|
||||
;; #_(let [type (or type :own)]
|
||||
;; (st/emit! (rt/nav :dashboard/icons {} {:type type :id id}))))
|
||||
;; (on-input-change [event]
|
||||
;; #_(-> (dom/get-target event)
|
||||
;; (dom/get-value)
|
||||
;; (swap! local assoc :name)))
|
||||
;; (on-cancel [event]
|
||||
;; #_(swap! local dissoc :name :edit))
|
||||
;; (on-double-click [event]
|
||||
;; #_(when editable?
|
||||
;; (swap! local assoc :edit true)))
|
||||
;; (on-input-keyup [event]
|
||||
;; #_(when (kbd/enter? event)
|
||||
;; (let [value (-> (dom/get-target event) (dom/get-value))]
|
||||
;; (st/emit! (di/rename-collection id (str/trim (:name @local))))
|
||||
;; (swap! local assoc :edit false))))]
|
||||
|
||||
(mf/defc nav-item
|
||||
[{:keys [id name selected?] :as props}]
|
||||
(let [local (mf/use-state {})
|
||||
editable? (not (nil? id))
|
||||
on-click (fn [event]
|
||||
(st/emit! (rt/nav :dashboard-projects {} {:project-id (str id)})))]
|
||||
[:li {:on-click on-click
|
||||
;; :on-double-click on-double-click
|
||||
:class-name (when selected? "current")}
|
||||
(if (:edit @local)
|
||||
[:div
|
||||
[:input.element-title #_{:value (if (:name @local)
|
||||
(:name @local)
|
||||
(if id name "Storage"))
|
||||
:on-change on-input-change
|
||||
:on-key-down on-input-keyup}]
|
||||
[:span.close #_{:on-click on-cancel} i/close]]
|
||||
[:span.element-title (if id name "Recent")])
|
||||
#_[:span.element-subtitle (tr "ds.num-elements" (t/c num-icons))]
|
||||
]))
|
||||
|
||||
|
||||
(mf/defc nav
|
||||
[{:keys [id] :as props}]
|
||||
(let [projects (->> (mf/deref projects-iref)
|
||||
(vals)
|
||||
(sort-by :created-at))]
|
||||
[:div.library-bar
|
||||
[:div.library-bar-inside
|
||||
[:ul.library-elements
|
||||
[:li
|
||||
[:a.btn-primary #_{:on-click #(st/emit! di/create-collection)}
|
||||
"new project +"]]
|
||||
|
||||
[:li {:style {:marginBottom "20px"}
|
||||
:on-click #(st/emit! (rt/nav :dashboard/projects {} {}))
|
||||
:class-name (when (nil? id) "current")}
|
||||
[:span.element-title "Recent"]]
|
||||
|
||||
(for [item projects]
|
||||
[:& grid-item {:project item :key (:id item)}])]]]))
|
||||
[:& nav-item {:id (:id item)
|
||||
:key (:id item)
|
||||
:name (:name item)
|
||||
:selected? (= (:id item) id)}])]]]))
|
||||
|
||||
;; --- Component: Content
|
||||
|
||||
(def files-ref
|
||||
(letfn [(selector [state]
|
||||
(let [id (get-in state [:dashboard-projects :id])
|
||||
ids (get-in state [:dashboard-projects :files id])]
|
||||
(mapv #(get-in state [:files %]) ids)))]
|
||||
(-> (l/lens selector)
|
||||
(l/derive st/state))))
|
||||
|
||||
(mf/defc content
|
||||
[{:keys [id] :as props}]
|
||||
(let [opts (mf/deref opts-iref)
|
||||
files (mf/deref files-ref)]
|
||||
[:*
|
||||
[:& menu {:opts opts :files files}]
|
||||
[:section.dashboard-grid.library
|
||||
[:& grid {:id id :opts opts :files files}]]]))
|
||||
|
||||
;; --- Projects Page
|
||||
|
||||
(mf/defc projects-page
|
||||
[_]
|
||||
(mf/use-effect #(st/emit! (udp/initialize)))
|
||||
(let [opts (mf/deref opts-iref)]
|
||||
[:section.dashboard-content
|
||||
[:& menu {:opts opts}]
|
||||
[:& grid {:opts opts}]]))
|
||||
[{:keys [id] :as props}]
|
||||
(mf/use-effect #(st/emit! udp/fetch-projects))
|
||||
(mf/use-effect {:fn #(st/emit! (udp/initialize id))
|
||||
:deps #js [id]})
|
||||
[:section.dashboard-content
|
||||
[:& nav {:id id}]
|
||||
[:& content {:id id}]])
|
||||
|
|
|
@ -22,12 +22,9 @@
|
|||
(s/def ::height ::fm/number-str)
|
||||
|
||||
(s/def ::project-form
|
||||
(s/keys :req-un [::name ::width ::height]))
|
||||
(s/keys :req-un [::name]))
|
||||
|
||||
(def defaults
|
||||
{:name ""
|
||||
:width "1366"
|
||||
:height "768"})
|
||||
(def defaults {:name ""})
|
||||
|
||||
;; --- Create Project Form
|
||||
|
||||
|
@ -57,33 +54,6 @@
|
|||
:on-blur (fm/on-input-blur form :name)
|
||||
:on-change (fm/on-input-change form :name)
|
||||
:auto-focus true}]
|
||||
[:div.project-size
|
||||
[:div.input-element.pixels
|
||||
[:span (tr "ds.width")]
|
||||
[:input#project-witdh.input-text
|
||||
{:placeholder (tr "ds.width")
|
||||
:name "width"
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 5000
|
||||
:class (fm/error-class form :width)
|
||||
:on-blur (fm/on-input-blur form :width)
|
||||
:on-change (fm/on-input-change form :width)
|
||||
:value (:width data)}]]
|
||||
[:a.toggle-layout {:on-click #(swap-size % form)} i/toggle]
|
||||
[:div.input-element.pixels
|
||||
[:span (tr "ds.height")]
|
||||
[:input#project-height.input-text
|
||||
{:placeholder (tr "ds.height")
|
||||
:type "number"
|
||||
:name "height"
|
||||
:min 0
|
||||
:max 5000
|
||||
:class (fm/error-class form :height)
|
||||
:on-blur (fm/on-input-blur form :height)
|
||||
:on-change (fm/on-input-change form :height)
|
||||
:value (:height data)}]]]
|
||||
|
||||
;; Submit
|
||||
[:input#project-btn.btn-primary
|
||||
{:value (tr "ds.go")
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
(scroll/scroll-to-point dom mouse-point scroll-position))))
|
||||
|
||||
(mf/defc workspace-content
|
||||
[{:keys [layout page] :as params}]
|
||||
[{:keys [layout page file] :as params}]
|
||||
(let [canvas (mf/use-ref nil)
|
||||
left-sidebar? (not (empty? (keep layout [:layers :sitemap
|
||||
:document-history])))
|
||||
|
@ -89,17 +89,26 @@
|
|||
|
||||
;; Aside
|
||||
(when left-sidebar?
|
||||
[:& left-sidebar {:page page :layout layout}])
|
||||
[:& left-sidebar {:file file :page page :layout layout}])
|
||||
(when right-sidebar?
|
||||
[:& right-sidebar {:page page :layout layout}])]))
|
||||
|
||||
(mf/defc workspace
|
||||
[{:keys [page-id] :as props}]
|
||||
(let [layout (mf/deref refs/workspace-layout)
|
||||
flags (mf/deref refs/selected-flags)
|
||||
page (mf/deref refs/workspace-page)]
|
||||
[{:keys [file-id page-id] :as props}]
|
||||
|
||||
[:*
|
||||
(mf/use-effect
|
||||
{:deps #js [file-id page-id]
|
||||
:fn (fn []
|
||||
(let [sub (shortcuts/init)]
|
||||
(st/emit! (udw/initialize file-id page-id))
|
||||
#(rx/cancel! sub)))})
|
||||
|
||||
(let [layout (mf/deref refs/workspace-layout)
|
||||
file (mf/deref refs/workspace-file)
|
||||
page (mf/deref refs/workspace-page)
|
||||
flags (mf/deref refs/selected-flags)]
|
||||
|
||||
[:> rdnd/provider {:backend rdnd/html5}
|
||||
[:& messages-widget]
|
||||
[:& header {:page page :flags flags}]
|
||||
|
||||
|
@ -107,17 +116,6 @@
|
|||
[:& colorpalette])
|
||||
|
||||
(when (and layout page)
|
||||
[:& workspace-content {:layout layout :page page}])]))
|
||||
|
||||
(mf/defc workspace-page
|
||||
[{:keys [project-id page-id] :as props}]
|
||||
|
||||
(mf/use-effect
|
||||
{:deps #js [page-id]
|
||||
:fn (fn []
|
||||
(let [sub (shortcuts/init)]
|
||||
(st/emit! (udw/initialize project-id page-id))
|
||||
#(rx/cancel! sub)))})
|
||||
|
||||
[:> rdnd/provider {:backend rdnd/html5}
|
||||
[:& workspace {:page-id page-id :key page-id}]])
|
||||
[:& workspace-content {:layout layout
|
||||
:file file
|
||||
:page page}])]))
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
]
|
||||
[:header#workspace-bar.workspace-bar
|
||||
[:div.main-icon
|
||||
[:a {:on-click #(st/emit! (rt/nav :dashboard/projects))} i/logo-icon]]
|
||||
[:a {:on-click #(st/emit! (rt/nav :dashboard-projects))} i/logo-icon]]
|
||||
[:div.project-tree-btn
|
||||
{:alt (tr "header.sitemap")
|
||||
:class (when (contains? flags :sitemap) "selected")
|
||||
|
|
|
@ -20,13 +20,11 @@
|
|||
|
||||
(mf/defc left-sidebar
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[{:keys [layout page] :as props}]
|
||||
[{:keys [layout page file] :as props}]
|
||||
[:aside.settings-bar.settings-bar-left
|
||||
[:div.settings-bar-inside
|
||||
(when (contains? layout :sitemap)
|
||||
[:& sitemap-toolbox {:project-id (:project-id page)
|
||||
:current-page-id (:id page)
|
||||
:page page}])
|
||||
[:& sitemap-toolbox {:file file :page page}])
|
||||
(when (contains? layout :document-history)
|
||||
[:& history-toolbox])
|
||||
(when (contains? layout :layers)
|
||||
|
|
|
@ -29,39 +29,36 @@
|
|||
|
||||
(mf/defc page-item
|
||||
[{:keys [page index deletable? selected?] :as props}]
|
||||
(letfn [(on-edit [event]
|
||||
(modal/show! page-form-dialog {:page page}))
|
||||
(delete []
|
||||
(st/emit! (dw/delete-page (:id page))))
|
||||
(on-delete [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! confirm-dialog {:on-accept delete}))
|
||||
(on-drop [item monitor]
|
||||
(prn "TODO"))
|
||||
(on-hover [item monitor]
|
||||
(st/emit! (dw/change-page-order {:id (:id item)
|
||||
:index index})))]
|
||||
(let [[dprops ref] (use-sortable {:type "page-item"
|
||||
:data {:id (:id page)
|
||||
:index index}
|
||||
:on-hover on-hover
|
||||
:on-drop on-drop})]
|
||||
[:li {:ref ref :class (classnames :selected selected?)}
|
||||
[:div.element-list-body
|
||||
{:class (classnames :selected selected?
|
||||
:dragging (:dragging? dprops))
|
||||
:on-click #(st/emit! (rt/nav :workspace/page {:project (:project-id page)
|
||||
:page (:id page)}))
|
||||
:on-double-click #(dom/stop-propagation %)
|
||||
:draggable true}
|
||||
(let [on-edit #(modal/show! page-form-dialog {:page page})
|
||||
delete-fn #(st/emit! (dw/delete-page (:id page)))
|
||||
on-delete #(do
|
||||
(dom/prevent-default %)
|
||||
(dom/stop-propagation %)
|
||||
(modal/show! confirm-dialog {:on-accept delete-fn}))
|
||||
on-drop #(do (prn "TODO"))
|
||||
on-hover #(st/emit! (dw/change-page-order {:id (:id page)
|
||||
:index index}))
|
||||
|
||||
[: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])]]])))
|
||||
navigate-fn #(st/emit! (dw/go-to-page (:id page)))
|
||||
[dprops ref] (use-sortable {:type "page-item"
|
||||
:data {:id (:id page)
|
||||
:index index}
|
||||
:on-hover on-hover
|
||||
:on-drop on-drop})]
|
||||
[:li {:ref ref :class (classnames :selected selected?)}
|
||||
[:div.element-list-body
|
||||
{:class (classnames :selected selected?
|
||||
:dragging (:dragging? dprops))
|
||||
:on-click navigate-fn
|
||||
:on-double-click #(dom/stop-propagation %)
|
||||
:draggable true}
|
||||
|
||||
[: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])]]]))
|
||||
|
||||
|
||||
;; --- Page Item Wrapper
|
||||
|
@ -84,8 +81,8 @@
|
|||
;; --- Pages List
|
||||
|
||||
(mf/defc pages-list
|
||||
[{:keys [project current-page-id] :as props}]
|
||||
(let [pages (enumerate (:pages project))
|
||||
[{:keys [file current-page] :as props}]
|
||||
(let [pages (enumerate (:pages file))
|
||||
deletable? (> (count pages) 1)]
|
||||
[:ul.element-list
|
||||
(for [[index page-id] pages]
|
||||
|
@ -93,31 +90,22 @@
|
|||
{:page-id page-id
|
||||
:index index
|
||||
:deletable? deletable?
|
||||
:selected? (= page-id current-page-id)
|
||||
:selected? (= page-id (:id current-page))
|
||||
:key page-id}])]))
|
||||
|
||||
;; --- Sitemap Toolbox
|
||||
|
||||
(def ^:private workspace-project
|
||||
(letfn [(selector [state]
|
||||
(let [project-id (get-in state [:workspace-page :project-id])]
|
||||
(get-in state [:projects project-id])))]
|
||||
(-> (l/lens selector)
|
||||
(l/derive st/state))))
|
||||
|
||||
(mf/defc sitemap-toolbox
|
||||
[{:keys [project-id current-page-id] :as props}]
|
||||
(let [project (mf/deref workspace-project)
|
||||
create #(modal/show! page-form-dialog {:page {:project-id project-id}})
|
||||
close #(st/emit! (dw/toggle-flag :sitemap))]
|
||||
[{:keys [file page] :as props}]
|
||||
(let [create-fn #(modal/show! page-form-dialog {:page {:file-id (:file-id page)}})
|
||||
close-fn #(st/emit! (dw/toggle-flag :sitemap))]
|
||||
[:div.sitemap.tool-window
|
||||
[:div.tool-window-bar
|
||||
[:div.tool-window-icon i/project-tree]
|
||||
[:span (tr "ds.settings.sitemap")]
|
||||
[:div.tool-window-close {:on-click close} i/close]]
|
||||
[:div.tool-window-close {:on-click close-fn} i/close]]
|
||||
[:div.tool-window-content
|
||||
[:div.project-title
|
||||
[:span (:name project)]
|
||||
[:div.add-page {:on-click create} i/close]]
|
||||
[:& pages-list {:project project
|
||||
:current-page-id current-page-id}]]]))
|
||||
#_[:span (:name project)]
|
||||
[:div.add-page {:on-click create-fn} i/close]]
|
||||
[:& pages-list {:file file :current-page page}]]]))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue