mirror of
https://github.com/penpot/penpot.git
synced 2025-01-25 07:58:49 -05:00
Merge pull request #1794 from penpot/palba-group-assets-by-drag-drop
✨ Group assets by drag and drop
This commit is contained in:
commit
81df2ca355
4 changed files with 671 additions and 124 deletions
|
@ -20,6 +20,7 @@
|
|||
|
||||
### :sparkles: New features
|
||||
|
||||
- Group assets by drag and drop [Taiga #2831](https://tree.taiga.io/project/penpot/us/2831)
|
||||
- Constraints are not well assigned when default and multiselection [Taiga #3069](https://tree.taiga.io/project/penpot/issue/3069)
|
||||
- Exporting big files flow [Taiga #2218](https://tree.taiga.io/project/penpot/us/2218)
|
||||
- Multiexport from main menu [Taiga #520](https://tree.taiga.io/project/penpot/us/28541)
|
||||
|
|
|
@ -323,12 +323,41 @@
|
|||
border: 2px solid $color-primary;
|
||||
}
|
||||
|
||||
.grid-placeholder {
|
||||
border: 2px solid $color-gray-20;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.drop-space {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.typography-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.drag-counter {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 4px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-color: $color-primary;
|
||||
border-radius: 50%;
|
||||
color: $color-black;
|
||||
font-size: $fs12;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.asset-title + .asset-enum {
|
||||
margin-top: $size-2;
|
||||
}
|
||||
|
||||
.asset-enum {
|
||||
.enum-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: $size-2;
|
||||
|
@ -370,6 +399,10 @@
|
|||
.enum-item.selected {
|
||||
color: $color-primary;
|
||||
}
|
||||
|
||||
.grid-placeholder {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: see if this is useful, or is better to leave only
|
||||
|
@ -390,6 +423,7 @@
|
|||
font-size: $fs12;
|
||||
color: $color-white;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
& span {
|
||||
margin-left: $size-1;
|
||||
|
@ -418,6 +452,15 @@
|
|||
background-color: $color-gray-60;
|
||||
}
|
||||
}
|
||||
|
||||
.dragging {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: color.adjust($color-primary, $alpha: -0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,23 +121,40 @@
|
|||
(update [_ state]
|
||||
(assoc-in state [:workspace-local :color-for-rename] nil))))
|
||||
|
||||
(defn- do-update-color
|
||||
[it state color file-id]
|
||||
(let [data (get state :workspace-data)
|
||||
[path name] (cph/parse-path-name (:name color))
|
||||
color (assoc color :path path :name name)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-color color))]
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/commit-changes changes)
|
||||
(sync-file (:current-file-id state) file-id)
|
||||
(dwu/commit-undo-transaction))))
|
||||
|
||||
(defn update-color
|
||||
[color file-id]
|
||||
(us/assert ::spec.color/color color)
|
||||
(us/assert ::us/uuid file-id)
|
||||
(ptk/reify ::update-color
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(do-update-color it state color file-id))))
|
||||
|
||||
(defn rename-color
|
||||
[file-id id new-name]
|
||||
(us/assert ::us/uuid file-id)
|
||||
(us/assert ::us/uuid id)
|
||||
(us/assert ::us/string new-name)
|
||||
(ptk/reify ::rename-color
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
[path name] (cph/parse-path-name (:name color))
|
||||
color (assoc color :path path :name name)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-color color))]
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/commit-changes changes)
|
||||
(sync-file (:current-file-id state) file-id)
|
||||
(dwu/commit-undo-transaction))))))
|
||||
object (get-in data [:colors id])
|
||||
new-object (assoc object :name new-name)]
|
||||
(do-update-color it state new-object file-id)))))
|
||||
|
||||
(defn delete-color
|
||||
[{:keys [id] :as params}]
|
||||
|
@ -178,6 +195,7 @@
|
|||
(pcb/update-media new-object))]
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
|
||||
(defn delete-media
|
||||
[{:keys [id] :as params}]
|
||||
(us/assert ::us/uuid id)
|
||||
|
@ -208,21 +226,40 @@
|
|||
edit?
|
||||
(assoc-in [:workspace-global :rename-typography] (:id typography))))))))))
|
||||
|
||||
(defn- do-update-tipography
|
||||
[it state typography file-id]
|
||||
(let [data (get state :workspace-data)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-typography typography))]
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/commit-changes changes)
|
||||
(sync-file (:current-file-id state) file-id)
|
||||
(dwu/commit-undo-transaction))))
|
||||
|
||||
(defn update-typography
|
||||
[typography file-id]
|
||||
(us/assert ::spec.typography/typography typography)
|
||||
(us/assert ::us/uuid file-id)
|
||||
(ptk/reify ::update-typography
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(do-update-tipography it state typography file-id))))
|
||||
|
||||
(defn rename-typography
|
||||
[file-id id new-name]
|
||||
(us/assert ::us/uuid file-id)
|
||||
(us/assert ::us/uuid id)
|
||||
(us/assert ::us/string new-name)
|
||||
(ptk/reify ::rename-typography
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-typography typography))]
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/commit-changes changes)
|
||||
(sync-file (:current-file-id state) file-id)
|
||||
(dwu/commit-undo-transaction))))))
|
||||
[path name] (cph/parse-path-name new-name)
|
||||
object (get-in data [:typographies id])
|
||||
new-object (assoc object :path path :name name)]
|
||||
(do-update-tipography it state new-object file-id)))))
|
||||
|
||||
|
||||
(defn delete-typography
|
||||
[id]
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
[app.util.keyboard :as kbd]
|
||||
[app.util.router :as rt]
|
||||
[app.util.strings :refer [matches-search]]
|
||||
[app.util.timers :as ts]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
|
@ -176,6 +177,104 @@
|
|||
:value (if create? (tr "labels.create") (tr "labels.rename"))
|
||||
:on-click on-accept}]]]]]))
|
||||
|
||||
|
||||
;; ---- Group assets by drag and drop ----
|
||||
|
||||
(defn- create-assets-group
|
||||
[rename components-to-group group-name]
|
||||
(st/emit! (dwu/start-undo-transaction))
|
||||
(apply st/emit!
|
||||
(->> components-to-group
|
||||
(map #(rename
|
||||
(:id %)
|
||||
(add-group % group-name)))))
|
||||
(st/emit! (dwu/commit-undo-transaction)))
|
||||
|
||||
|
||||
(defn- on-drop-asset
|
||||
[event asset dragging? selected-assets selected-assets-full selected-assets-paths rename]
|
||||
(let [create-typed-assets-group (partial create-assets-group rename)]
|
||||
(when (not (dnd/from-child? event))
|
||||
(reset! dragging? false)
|
||||
(when
|
||||
(and (not (contains? selected-assets (:id asset)))
|
||||
(every? #(= % (:path asset)) selected-assets-paths))
|
||||
(let [components-to-group (conj selected-assets-full asset)
|
||||
create-typed-assets-group (partial create-typed-assets-group components-to-group)]
|
||||
(modal/show! :name-group-dialog {:accept create-typed-assets-group}))))))
|
||||
|
||||
|
||||
|
||||
(defn- on-drag-enter-asset
|
||||
[event asset dragging? selected-assets selected-assets-paths]
|
||||
(when (and
|
||||
(not (dnd/from-child? event))
|
||||
(every? #(= % (:path asset)) selected-assets-paths)
|
||||
(not (contains? selected-assets (:id asset))))
|
||||
(reset! dragging? true)))
|
||||
|
||||
(defn- on-drag-leave-asset
|
||||
[event dragging?]
|
||||
(when (not (dnd/from-child? event))
|
||||
(reset! dragging? false)))
|
||||
|
||||
(defn- create-counter-element
|
||||
[asset-count]
|
||||
(let [counter-el (dom/create-element "div")]
|
||||
(dom/set-property! counter-el "class" "drag-counter")
|
||||
(dom/set-text! counter-el (str asset-count))
|
||||
counter-el))
|
||||
|
||||
(defn- set-drag-image
|
||||
[event item-ref num-selected]
|
||||
(let [offset (dom/get-offset-position (.-nativeEvent event))
|
||||
item-el (mf/ref-val item-ref)
|
||||
counter-el (create-counter-element num-selected)]
|
||||
|
||||
;; set-drag-image requires that the element is rendered and
|
||||
;; visible to the user at the moment of creating the ghost
|
||||
;; image (to make a snapshot), but you may remove it right
|
||||
;; afterwards, in the next render cycle.
|
||||
(dom/append-child! item-el counter-el)
|
||||
(dnd/set-drag-image! event item-el (:x offset) (:y offset))
|
||||
(ts/raf #(.removeChild ^js item-el counter-el))))
|
||||
|
||||
(defn- on-asset-drag-start
|
||||
[event asset selected-assets item-ref asset-type on-drag-start]
|
||||
(let [id-asset (:id asset)
|
||||
num-selected (if (contains? selected-assets id-asset)
|
||||
(count selected-assets)
|
||||
1)]
|
||||
(when (not (contains? selected-assets id-asset))
|
||||
(st/emit! (dw/unselect-all-assets)
|
||||
(dw/toggle-selected-assets id-asset asset-type)))
|
||||
(on-drag-start asset event)
|
||||
(when (> num-selected 1)
|
||||
(set-drag-image event item-ref num-selected))))
|
||||
|
||||
|
||||
|
||||
(defn- on-drag-enter-asset-group
|
||||
[event dragging? prefix selected-assets-paths]
|
||||
(dom/stop-propagation event)
|
||||
(when (and (not (dnd/from-child? event))
|
||||
(not (every? #(= % prefix) selected-assets-paths)))
|
||||
(reset! dragging? true)))
|
||||
|
||||
(defn- on-drop-asset-group
|
||||
[event dragging? prefix selected-assets-paths selected-assets-full rename]
|
||||
(dom/stop-propagation event)
|
||||
(when (not (dnd/from-child? event))
|
||||
(reset! dragging? false)
|
||||
(when (not (every? #(= % prefix) selected-assets-paths))
|
||||
(doseq [target-asset selected-assets-full]
|
||||
(st/emit!
|
||||
(rename
|
||||
(:id target-asset)
|
||||
(cph/merge-path-item prefix (:name target-asset))))))))
|
||||
|
||||
|
||||
|
||||
;; ---- Common blocks ----
|
||||
|
||||
(def auto-pos-menu-state {:open? false
|
||||
|
@ -268,59 +367,145 @@
|
|||
[(tr "workspace.assets.ungroup") #(on-ungroup path)]]}]])))
|
||||
|
||||
|
||||
;; ---- Components box ----
|
||||
;;---- Components box ----
|
||||
|
||||
(mf/defc components-item
|
||||
[{:keys [component renaming listing-thumbs? selected-components
|
||||
on-asset-click on-context-menu on-drag-start do-rename cancel-rename]}]
|
||||
[:div {:key (:id component)
|
||||
:class-name (dom/classnames
|
||||
:selected (contains? selected-components (:id component))
|
||||
:grid-cell @listing-thumbs?
|
||||
:enum-item (not @listing-thumbs?))
|
||||
:id (str "component-shape-id-" (:id component))
|
||||
:draggable true
|
||||
:on-click #(on-asset-click % (:id component) nil)
|
||||
:on-context-menu (on-context-menu (:id component))
|
||||
:on-drag-start (partial on-drag-start component)}
|
||||
[:& component-svg {:group (get-in component [:objects (:id component)])
|
||||
:objects (:objects component)}]
|
||||
(let [renaming? (= renaming (:id component))]
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
:cell-name @listing-thumbs?
|
||||
:item-name (not @listing-thumbs?)
|
||||
:editing renaming?)
|
||||
:value (cph/merge-path-item (:path component) (:name component))
|
||||
:tooltip (cph/merge-path-item (:path component) (:name component))
|
||||
:display-value (if @listing-thumbs?
|
||||
(:name component)
|
||||
(cph/compact-name (:path component)
|
||||
(:name component)))
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
:on-cancel cancel-rename}])])
|
||||
on-asset-click on-context-menu on-drag-start do-rename
|
||||
cancel-rename selected-components-full selected-components-paths]}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
|
||||
dragging? (mf/use-state false)
|
||||
|
||||
on-drop
|
||||
(mf/use-callback
|
||||
(mf/deps component dragging? selected-components selected-components-full selected-components-paths)
|
||||
(fn [event]
|
||||
(on-drop-asset event component dragging? selected-components selected-components-full
|
||||
selected-components-paths dwl/rename-component)))
|
||||
|
||||
on-drag-over
|
||||
(mf/use-callback #(dom/prevent-default %))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-callback
|
||||
(mf/deps component dragging? selected-components selected-components-paths)
|
||||
(fn [event]
|
||||
(on-drag-enter-asset event component dragging? selected-components selected-components-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-callback
|
||||
(mf/deps dragging?)
|
||||
(fn [event]
|
||||
(on-drag-leave-asset event dragging?)))
|
||||
|
||||
on-component-drag-start
|
||||
(mf/use-callback
|
||||
(mf/deps component selected-components item-ref on-drag-start)
|
||||
(fn [event]
|
||||
(on-asset-drag-start event component selected-components item-ref :components on-drag-start)))]
|
||||
|
||||
[:div {:key (:id component)
|
||||
:ref item-ref
|
||||
:class (dom/classnames
|
||||
:selected (contains? selected-components (:id component))
|
||||
:grid-cell @listing-thumbs?
|
||||
:enum-item (not @listing-thumbs?))
|
||||
:id (str "component-shape-id-" (:id component))
|
||||
:draggable true
|
||||
:on-click #(on-asset-click % (:id component) nil)
|
||||
:on-context-menu (on-context-menu (:id component))
|
||||
:on-drag-start on-component-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
|
||||
[:& component-svg {:group (get-in component [:objects (:id component)])
|
||||
:objects (:objects component)}]
|
||||
(let [renaming? (= renaming (:id component))]
|
||||
[:& editable-label
|
||||
{:class (dom/classnames
|
||||
:cell-name @listing-thumbs?
|
||||
:item-name (not @listing-thumbs?)
|
||||
:editing renaming?)
|
||||
:value (cph/merge-path-item (:path component) (:name component))
|
||||
:tooltip (cph/merge-path-item (:path component) (:name component))
|
||||
:display-value (if @listing-thumbs?
|
||||
(:name component)
|
||||
(cph/compact-name (:path component)
|
||||
(:name component)))
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
:on-cancel cancel-rename}]
|
||||
(when @dragging?
|
||||
[:div.dragging]))]))
|
||||
|
||||
(mf/defc components-group
|
||||
[{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected-components on-asset-click
|
||||
on-drag-start do-rename cancel-rename on-rename-group on-ungroup on-context-menu]}]
|
||||
(let [group-open? (get open-groups prefix true)]
|
||||
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
|
||||
selected-components-full]}]
|
||||
(let [group-open? (get open-groups prefix true)
|
||||
|
||||
[:*
|
||||
dragging? (mf/use-state false)
|
||||
|
||||
selected-components-paths (->> selected-components-full
|
||||
(map #(:path %))
|
||||
(map #(if (nil? %) "" %)))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-callback
|
||||
(mf/deps dragging? prefix selected-components-paths)
|
||||
(fn [event]
|
||||
(on-drag-enter-asset-group event dragging? prefix selected-components-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-callback
|
||||
(mf/deps dragging?)
|
||||
(fn [event]
|
||||
(on-drag-leave-asset event dragging?)))
|
||||
|
||||
on-drag-over (mf/use-callback #(dom/prevent-default %))
|
||||
|
||||
on-drop
|
||||
(mf/use-callback
|
||||
(mf/deps dragging? prefix selected-components-paths selected-components-full)
|
||||
(fn [event]
|
||||
(on-drop-asset-group event dragging? prefix selected-components-paths selected-components-full dwl/rename-component)))]
|
||||
|
||||
[:div {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
[:& asset-group-title {:file-id file-id
|
||||
:box :components
|
||||
:path prefix
|
||||
:group-open? group-open?
|
||||
:on-rename on-rename-group
|
||||
:on-ungroup on-ungroup}]
|
||||
|
||||
(when group-open?
|
||||
[:*
|
||||
(let [components (get groups "" [])]
|
||||
[:div {:class-name (dom/classnames
|
||||
:asset-grid @listing-thumbs?
|
||||
:big @listing-thumbs?
|
||||
:asset-enum (not @listing-thumbs?))}
|
||||
:asset-enum (not @listing-thumbs?)
|
||||
:drop-space (and
|
||||
(empty? components)
|
||||
(some? groups)
|
||||
(not @dragging?)))
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
(when @dragging?
|
||||
[:div.grid-placeholder "\u00A0"])
|
||||
(when (and
|
||||
(empty? components)
|
||||
(some? groups))
|
||||
[:div.drop-space])
|
||||
(for [component components]
|
||||
[:& components-item {:component component
|
||||
:renaming renaming
|
||||
|
@ -329,8 +514,11 @@
|
|||
:on-asset-click on-asset-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-drag-start
|
||||
:on-group on-group
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename}])])
|
||||
:cancel-rename cancel-rename
|
||||
:selected-components-full selected-components-full
|
||||
:selected-components-paths selected-components-paths}])])
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& components-group {:file-id file-id
|
||||
|
@ -346,7 +534,8 @@
|
|||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu}]))])]))
|
||||
:on-context-menu on-context-menu
|
||||
:selected-components-full selected-components-full}]))])]))
|
||||
|
||||
(mf/defc components-box
|
||||
[{:keys [file-id local? components listing-thumbs? open? reverse-sort? open-groups selected-assets
|
||||
|
@ -356,13 +545,14 @@
|
|||
|
||||
menu-state (mf/use-state auto-pos-menu-state)
|
||||
|
||||
selected-components (:components selected-assets)
|
||||
multi-components? (> (count selected-components) 1)
|
||||
multi-assets? (or (seq (:graphics selected-assets))
|
||||
(seq (:colors selected-assets))
|
||||
(seq (:typographies selected-assets)))
|
||||
selected-components (:components selected-assets)
|
||||
selected-components-full (filter #(contains? selected-components (:id %)) components)
|
||||
multi-components? (> (count selected-components) 1)
|
||||
multi-assets? (or (seq (:graphics selected-assets))
|
||||
(seq (:colors selected-assets))
|
||||
(seq (:typographies selected-assets)))
|
||||
|
||||
groups (group-assets components reverse-sort?)
|
||||
groups (group-assets components reverse-sort?)
|
||||
|
||||
on-duplicate
|
||||
(mf/use-callback
|
||||
|
@ -505,8 +695,10 @@
|
|||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-group on-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu}]
|
||||
:on-context-menu on-context-menu
|
||||
:selected-components-full selected-components-full}]
|
||||
(when local?
|
||||
[:& auto-pos-menu
|
||||
{:on-close on-close-menu
|
||||
|
@ -524,43 +716,113 @@
|
|||
|
||||
(mf/defc graphics-item
|
||||
[{:keys [object renaming listing-thumbs? selected-objects
|
||||
on-asset-click on-context-menu on-drag-start do-rename cancel-rename]}]
|
||||
[:div {:key (:id object)
|
||||
:class-name (dom/classnames
|
||||
:selected (contains? selected-objects (:id object))
|
||||
:grid-cell @listing-thumbs?
|
||||
:enum-item (not @listing-thumbs?))
|
||||
:draggable true
|
||||
:on-click #(on-asset-click % (:id object) nil)
|
||||
:on-context-menu (on-context-menu (:id object))
|
||||
:on-drag-start (partial on-drag-start object)}
|
||||
[:img {:src (cfg/resolve-file-media object true)
|
||||
:draggable false}] ;; Also need to add css pointer-events: none
|
||||
on-asset-click on-context-menu on-drag-start do-rename cancel-rename
|
||||
selected-graphics-full selected-graphics-paths]}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
|
||||
(let [renaming? (= renaming (:id object))]
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
:cell-name @listing-thumbs?
|
||||
:item-name (not @listing-thumbs?)
|
||||
:editing renaming?)
|
||||
:value (cph/merge-path-item (:path object) (:name object))
|
||||
:tooltip (cph/merge-path-item (:path object) (:name object))
|
||||
:display-value (if @listing-thumbs?
|
||||
(:name object)
|
||||
(cph/compact-name (:path object)
|
||||
(:name object)))
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
:on-cancel cancel-rename}])])
|
||||
dragging? (mf/use-state false)
|
||||
|
||||
on-drop
|
||||
(mf/use-callback
|
||||
(mf/deps object dragging? selected-objects selected-graphics-full selected-graphics-paths)
|
||||
(fn [event]
|
||||
(on-drop-asset event object dragging? selected-objects selected-graphics-full
|
||||
selected-graphics-paths dwl/rename-media)))
|
||||
|
||||
on-drag-over (mf/use-callback #(dom/prevent-default %))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-callback
|
||||
(mf/deps object dragging? selected-objects selected-graphics-paths)
|
||||
(fn [event]
|
||||
(on-drag-enter-asset event object dragging? selected-objects selected-graphics-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-callback
|
||||
(mf/deps dragging?)
|
||||
(fn [event]
|
||||
(on-drag-leave-asset event dragging?)))
|
||||
|
||||
on-grahic-drag-start
|
||||
(mf/use-callback
|
||||
(mf/deps object selected-objects item-ref on-drag-start)
|
||||
(fn [event]
|
||||
(on-asset-drag-start event object selected-objects item-ref :graphics on-drag-start)))]
|
||||
|
||||
[:div {:key (:id object)
|
||||
:ref item-ref
|
||||
:class-name (dom/classnames
|
||||
:selected (contains? selected-objects (:id object))
|
||||
:grid-cell @listing-thumbs?
|
||||
:enum-item (not @listing-thumbs?))
|
||||
:draggable true
|
||||
:on-click #(on-asset-click % (:id object) nil)
|
||||
:on-context-menu (on-context-menu (:id object))
|
||||
:on-drag-start on-grahic-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
[:img {:src (cfg/resolve-file-media object true)
|
||||
:draggable false}] ;; Also need to add css pointer-events: none
|
||||
|
||||
(let [renaming? (= renaming (:id object))]
|
||||
[:& editable-label
|
||||
{:class-name (dom/classnames
|
||||
:cell-name @listing-thumbs?
|
||||
:item-name (not @listing-thumbs?)
|
||||
:editing renaming?)
|
||||
:value (cph/merge-path-item (:path object) (:name object))
|
||||
:tooltip (cph/merge-path-item (:path object) (:name object))
|
||||
:display-value (if @listing-thumbs?
|
||||
(:name object)
|
||||
(cph/compact-name (:path object)
|
||||
(:name object)))
|
||||
:editing? renaming?
|
||||
:disable-dbl-click? true
|
||||
:on-change do-rename
|
||||
:on-cancel cancel-rename}]
|
||||
(when @dragging?
|
||||
[:div.dragging]))]))
|
||||
|
||||
(mf/defc graphics-group
|
||||
[{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected-objects on-asset-click
|
||||
on-drag-start do-rename cancel-rename on-rename-group on-ungroup
|
||||
on-context-menu]}]
|
||||
(let [group-open? (get open-groups prefix true)]
|
||||
on-context-menu selected-graphics-full]}]
|
||||
(let [group-open? (get open-groups prefix true)
|
||||
|
||||
[:*
|
||||
dragging? (mf/use-state false)
|
||||
|
||||
selected-graphics-paths (->> selected-graphics-full
|
||||
(map #(:path %))
|
||||
(map #(if (nil? %) "" %)))
|
||||
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-callback
|
||||
(mf/deps dragging? prefix selected-graphics-paths)
|
||||
(fn [event]
|
||||
(on-drag-enter-asset-group event dragging? prefix selected-graphics-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-callback
|
||||
(mf/deps dragging?)
|
||||
(fn [event]
|
||||
(on-drag-leave-asset event dragging?)))
|
||||
|
||||
on-drag-over (mf/use-callback #(dom/prevent-default %))
|
||||
|
||||
on-drop
|
||||
(mf/use-callback
|
||||
(mf/deps dragging? prefix selected-graphics-paths selected-graphics-full)
|
||||
(fn [event]
|
||||
(on-drop-asset-group event dragging? prefix selected-graphics-paths selected-graphics-full dwl/rename-media)))]
|
||||
|
||||
|
||||
[:div {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
[:& asset-group-title {:file-id file-id
|
||||
:box :graphics
|
||||
:path prefix
|
||||
|
@ -572,7 +834,21 @@
|
|||
(let [objects (get groups "" [])]
|
||||
[:div {:class-name (dom/classnames
|
||||
:asset-grid @listing-thumbs?
|
||||
:asset-enum (not @listing-thumbs?))}
|
||||
:asset-enum (not @listing-thumbs?)
|
||||
:drop-space (and
|
||||
(empty? objects)
|
||||
(some? groups)
|
||||
(not @dragging?)))
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
(when @dragging?
|
||||
[:div.grid-placeholder "\u00A0"])
|
||||
(when (and
|
||||
(empty? objects)
|
||||
(some? groups))
|
||||
[:div.drop-space])
|
||||
(for [object objects]
|
||||
[:& graphics-item {:object object
|
||||
:renaming renaming
|
||||
|
@ -582,7 +858,9 @@
|
|||
:on-context-menu on-context-menu
|
||||
:on-drag-start on-drag-start
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename}])])
|
||||
:cancel-rename cancel-rename
|
||||
:selected-graphics-full selected-graphics-full
|
||||
:selected-graphics-paths selected-graphics-paths}])])
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& graphics-group {:file-id file-id
|
||||
|
@ -598,7 +876,9 @@
|
|||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu}]))])]))
|
||||
:on-context-menu on-context-menu
|
||||
:selected-graphics-full selected-graphics-full
|
||||
:selected-graphics-paths selected-graphics-paths}]))])]))
|
||||
|
||||
(mf/defc graphics-box
|
||||
[{:keys [file-id local? objects listing-thumbs? open? open-groups selected-assets reverse-sort?
|
||||
|
@ -610,11 +890,14 @@
|
|||
menu-state (mf/use-state auto-pos-menu-state)
|
||||
|
||||
selected-objects (:graphics selected-assets)
|
||||
selected-graphics-full (filter #(contains? selected-objects (:id %)) objects)
|
||||
multi-objects? (> (count selected-objects) 1)
|
||||
multi-assets? (or (seq (:components selected-assets))
|
||||
(seq (:colors selected-assets))
|
||||
(seq (:typographies selected-assets)))
|
||||
|
||||
|
||||
|
||||
groups (group-assets objects reverse-sort?)
|
||||
|
||||
add-graphic
|
||||
|
@ -770,7 +1053,8 @@
|
|||
:cancel-rename cancel-rename
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu}]
|
||||
:on-context-menu on-context-menu
|
||||
:selected-graphics-full selected-graphics-full}]
|
||||
(when local?
|
||||
[:& auto-pos-menu
|
||||
{:on-close on-close-menu
|
||||
|
@ -786,8 +1070,11 @@
|
|||
|
||||
(mf/defc color-item
|
||||
[{:keys [color local? file-id selected-colors multi-colors? multi-assets?
|
||||
on-asset-click on-assets-delete on-clear-selection on-group] :as props}]
|
||||
(let [rename? (= (:color-for-rename @refs/workspace-local) (:id color))
|
||||
on-asset-click on-assets-delete on-clear-selection on-group
|
||||
selected-colors-full selected-colors-paths move-color] :as props}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
dragging? (mf/use-state false)
|
||||
rename? (= (:color-for-rename @refs/workspace-local) (:id color))
|
||||
input-ref (mf/use-ref)
|
||||
state (mf/use-state {:editing rename?})
|
||||
|
||||
|
@ -871,7 +1158,33 @@
|
|||
on-close-menu
|
||||
(mf/use-callback
|
||||
(fn []
|
||||
(swap! menu-state close-auto-pos-menu)))]
|
||||
(swap! menu-state close-auto-pos-menu)))
|
||||
on-drop
|
||||
(mf/use-callback
|
||||
(mf/deps color dragging? selected-colors selected-colors-full selected-colors-paths move-color)
|
||||
(fn [event]
|
||||
(on-drop-asset event color dragging? selected-colors selected-colors-full
|
||||
selected-colors-paths move-color)))
|
||||
|
||||
on-drag-over (mf/use-callback #(dom/prevent-default %))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-callback
|
||||
(mf/deps color dragging? selected-colors selected-colors-paths)
|
||||
(fn [event]
|
||||
(on-drag-enter-asset event color dragging? selected-colors selected-colors-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-callback
|
||||
(mf/deps dragging?)
|
||||
(fn [event]
|
||||
(on-drag-leave-asset event dragging?)))
|
||||
|
||||
on-color-drag-start
|
||||
(mf/use-callback
|
||||
(mf/deps color selected-colors item-ref)
|
||||
(fn [event]
|
||||
(on-asset-drag-start event color selected-colors item-ref :colors identity)))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps (:editing @state))
|
||||
|
@ -885,7 +1198,14 @@
|
|||
:on-context-menu on-context-menu
|
||||
:on-click (when-not (:editing @state)
|
||||
#(on-asset-click % (:id color)
|
||||
(partial apply-color (:id color))))}
|
||||
(partial apply-color (:id color))))
|
||||
:ref item-ref
|
||||
:draggable true
|
||||
:on-drag-start on-color-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
[:& bc/color-bullet {:color color}]
|
||||
|
||||
(if (:editing @state)
|
||||
|
@ -911,15 +1231,48 @@
|
|||
[(tr "workspace.assets.edit") edit-color-clicked])
|
||||
[(tr "workspace.assets.delete") delete-color]
|
||||
(when-not multi-assets?
|
||||
[(tr "workspace.assets.group") (on-group (:id color))])]}])]))
|
||||
[(tr "workspace.assets.group") (on-group (:id color))])]}])
|
||||
(when @dragging?
|
||||
[:div.dragging])]))
|
||||
|
||||
(mf/defc colors-group
|
||||
[{:keys [file-id prefix groups open-groups local? selected-colors
|
||||
multi-colors? multi-assets? on-asset-click on-assets-delete
|
||||
on-clear-selection on-group on-rename-group on-ungroup colors]}]
|
||||
(let [group-open? (get open-groups prefix true)]
|
||||
on-clear-selection on-group on-rename-group on-ungroup colors
|
||||
selected-colors-full]}]
|
||||
(let [group-open? (get open-groups prefix true)
|
||||
dragging? (mf/use-state false)
|
||||
|
||||
[:*
|
||||
selected-colors-paths (->> selected-colors-full
|
||||
(map #(:path %))
|
||||
(map #(if (nil? %) "" %)))
|
||||
|
||||
|
||||
move-color (partial dwl/rename-color file-id)
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-callback
|
||||
(mf/deps dragging? prefix selected-colors-paths)
|
||||
(fn [event]
|
||||
(on-drag-enter-asset-group event dragging? prefix selected-colors-paths)))
|
||||
|
||||
on-drag-leave (mf/use-callback
|
||||
(mf/deps dragging?)
|
||||
(fn [event]
|
||||
(on-drag-leave-asset event dragging?)))
|
||||
|
||||
on-drag-over (mf/use-callback #(dom/prevent-default %))
|
||||
|
||||
on-drop
|
||||
(mf/use-callback
|
||||
(mf/deps dragging? prefix selected-colors-paths selected-colors-full move-color)
|
||||
(fn [event]
|
||||
(on-drop-asset-group event dragging? prefix selected-colors-paths selected-colors-full move-color)))]
|
||||
|
||||
[:div {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
[:& asset-group-title {:file-id file-id
|
||||
:box :colors
|
||||
:path prefix
|
||||
|
@ -929,7 +1282,16 @@
|
|||
(when group-open?
|
||||
[:*
|
||||
(let [colors (get groups "" [])]
|
||||
[:div.asset-list
|
||||
[:div.asset-list {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
(when @dragging?
|
||||
[:div.grid-placeholder "\u00A0"])
|
||||
(when (and
|
||||
(empty? colors)
|
||||
(some? groups))
|
||||
[:div.drop-space])
|
||||
(for [color colors]
|
||||
(let [color (cond-> color
|
||||
(:value color) (assoc :color (:value color) :opacity 1)
|
||||
|
@ -946,7 +1308,10 @@
|
|||
:on-assets-delete on-assets-delete
|
||||
:on-clear-selection on-clear-selection
|
||||
:on-group on-group
|
||||
:colors colors}]))])
|
||||
:colors colors
|
||||
:selected-colors-full selected-colors-full
|
||||
:selected-colors-paths selected-colors-paths
|
||||
:move-color move-color}]))])
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
[:& colors-group {:file-id file-id
|
||||
|
@ -964,12 +1329,14 @@
|
|||
:on-group on-group
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:colors colors}]))])]))
|
||||
:colors colors
|
||||
:selected-colors-full selected-colors-full}]))])]))
|
||||
|
||||
(mf/defc colors-box
|
||||
[{:keys [file-id local? colors open? open-groups selected-assets reverse-sort?
|
||||
on-asset-click on-assets-delete on-clear-selection] :as props}]
|
||||
(let [selected-colors (:colors selected-assets)
|
||||
selected-colors-full (filter #(contains? selected-colors (:id %)) colors)
|
||||
multi-colors? (> (count selected-colors) 1)
|
||||
multi-assets? (or (seq (:components selected-assets))
|
||||
(seq (:graphics selected-assets))
|
||||
|
@ -1087,17 +1454,104 @@
|
|||
:on-group on-group
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:colors colors}]]]))
|
||||
:colors colors
|
||||
:selected-colors-full selected-colors-full}]]]))
|
||||
|
||||
;; ---- Typography box ----
|
||||
|
||||
(mf/defc typography-item
|
||||
[{:keys [typography file local? handle-change selected-typographies apply-typography
|
||||
editing-id local-data on-asset-click on-context-menu
|
||||
selected-typographies-full selected-typographies-paths move-typography] :as props}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
dragging? (mf/use-state false)
|
||||
on-drop
|
||||
(mf/use-callback
|
||||
(mf/deps typography dragging? selected-typographies selected-typographies-full selected-typographies-paths move-typography)
|
||||
(fn [event]
|
||||
(on-drop-asset event typography dragging? selected-typographies selected-typographies-full
|
||||
selected-typographies-paths move-typography)))
|
||||
|
||||
on-drag-over (mf/use-callback #(dom/prevent-default %))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-callback
|
||||
(mf/deps typography dragging? selected-typographies selected-typographies-paths)
|
||||
(fn [event]
|
||||
(on-drag-enter-asset event typography dragging? selected-typographies selected-typographies-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-callback
|
||||
(mf/deps dragging?)
|
||||
(fn [event]
|
||||
(on-drag-leave-asset event dragging?)))
|
||||
|
||||
on-typography-drag-start
|
||||
(mf/use-callback
|
||||
(mf/deps typography selected-typographies item-ref)
|
||||
(fn [event]
|
||||
(on-asset-drag-start event typography selected-typographies item-ref :typographies identity)))]
|
||||
|
||||
[:div.typography-container {:ref item-ref
|
||||
:draggable true
|
||||
:on-drag-start on-typography-drag-start
|
||||
:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
[:& typography-entry
|
||||
{:key (:id typography)
|
||||
:typography typography
|
||||
:file file
|
||||
:read-only? (not local?)
|
||||
:on-context-menu #(on-context-menu (:id typography) %)
|
||||
:on-change #(handle-change typography %)
|
||||
:selected? (contains? selected-typographies (:id typography))
|
||||
:on-click #(on-asset-click % (:id typography)
|
||||
(partial apply-typography typography))
|
||||
:editing? (= editing-id (:id typography))
|
||||
:focus-name? (= (:rename-typography local-data) (:id typography))}]
|
||||
(when @dragging?
|
||||
[:div.dragging])]))
|
||||
|
||||
(mf/defc typographies-group
|
||||
[{:keys [file-id prefix groups open-groups file local? selected-typographies local-data
|
||||
editing-id on-asset-click handle-change apply-typography
|
||||
on-rename-group on-ungroup on-context-menu]}]
|
||||
(let [group-open? (get open-groups prefix true)]
|
||||
on-rename-group on-ungroup on-context-menu selected-typographies-full]}]
|
||||
(let [group-open? (get open-groups prefix true)
|
||||
dragging? (mf/use-state false)
|
||||
|
||||
[:*
|
||||
selected-typographies-paths (->> selected-typographies-full
|
||||
(map #(:path %))
|
||||
(map #(if (nil? %) "" %)))
|
||||
|
||||
move-typography (partial dwl/rename-typography file-id)
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-callback
|
||||
(mf/deps dragging? prefix selected-typographies-paths)
|
||||
(fn [event]
|
||||
(on-drag-enter-asset-group event dragging? prefix selected-typographies-paths)))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-callback
|
||||
(mf/deps dragging?)
|
||||
(fn [event]
|
||||
(on-drag-leave-asset event dragging?)))
|
||||
|
||||
on-drag-over (mf/use-callback #(dom/prevent-default %))
|
||||
|
||||
on-drop
|
||||
(mf/use-callback
|
||||
(mf/deps dragging? prefix selected-typographies-paths selected-typographies-full move-typography)
|
||||
(fn [event]
|
||||
(on-drop-asset-group event dragging? prefix selected-typographies-paths selected-typographies-full move-typography)))]
|
||||
|
||||
|
||||
[:div {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
[:& asset-group-title {:file-id file-id
|
||||
:box :typographies
|
||||
:path prefix
|
||||
|
@ -1107,20 +1561,29 @@
|
|||
(when group-open?
|
||||
[:*
|
||||
(let [typographies (get groups "" [])]
|
||||
[:div.asset-list
|
||||
[:div.asset-list {:on-drag-enter on-drag-enter
|
||||
:on-drag-leave on-drag-leave
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
(when @dragging?
|
||||
[:div.grid-placeholder "\u00A0"])
|
||||
(when (and
|
||||
(empty? typographies)
|
||||
(some? groups))
|
||||
[:div.drop-space])
|
||||
(for [typography typographies]
|
||||
[:& typography-entry
|
||||
{:key (:id typography)
|
||||
:typography typography
|
||||
:file file
|
||||
:read-only? (not local?)
|
||||
:on-context-menu #(on-context-menu (:id typography) %)
|
||||
:on-change #(handle-change typography %)
|
||||
:selected? (contains? selected-typographies (:id typography))
|
||||
:on-click #(on-asset-click % (:id typography)
|
||||
(partial apply-typography typography))
|
||||
:editing? (= editing-id (:id typography))
|
||||
:focus-name? (= (:rename-typography local-data) (:id typography))}])])
|
||||
[:& typography-item {:typography typography
|
||||
:file file
|
||||
:local? local?
|
||||
:handle-change handle-change
|
||||
:selected-typographies selected-typographies
|
||||
:apply-typography apply-typography
|
||||
:editing-id editing-id
|
||||
:local-data local-data
|
||||
:on-asset-click on-asset-click
|
||||
:selected-typographies-full selected-typographies-full
|
||||
:selected-typographies-paths selected-typographies-paths
|
||||
:move-typography move-typography}])])
|
||||
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
|
@ -1138,7 +1601,8 @@
|
|||
:apply-typography apply-typography
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu}]))])]))
|
||||
:on-context-menu on-context-menu
|
||||
:selected-typographies-full selected-typographies-full}]))])]))
|
||||
|
||||
(mf/defc typographies-box
|
||||
[{:keys [file file-id local? typographies open? open-groups selected-assets reverse-sort?
|
||||
|
@ -1151,6 +1615,7 @@
|
|||
groups (group-assets typographies reverse-sort?)
|
||||
|
||||
selected-typographies (:typographies selected-assets)
|
||||
selected-typographies-full (filter #(contains? selected-typographies (:id %)) typographies)
|
||||
multi-typographies? (> (count selected-typographies) 1)
|
||||
multi-assets? (or (seq (:components selected-assets))
|
||||
(seq (:graphics selected-assets))
|
||||
|
@ -1317,7 +1782,8 @@
|
|||
:apply-typography apply-typography
|
||||
:on-rename-group on-rename-group
|
||||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu}]
|
||||
:on-context-menu on-context-menu
|
||||
:selected-typographies-full selected-typographies-full}]
|
||||
|
||||
(when local?
|
||||
[:& auto-pos-menu
|
||||
|
|
Loading…
Add table
Reference in a new issue