mirror of
https://github.com/penpot/penpot.git
synced 2025-03-16 01:31:22 -05:00
✨ Add context menu with right click in dashboard
This commit is contained in:
parent
70cba4bbdf
commit
e87dc6d34c
10 changed files with 235 additions and 117 deletions
|
@ -21,6 +21,10 @@
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.context-menu.fixed {
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
.context-menu-items {
|
.context-menu-items {
|
||||||
background: $color-white;
|
background: $color-white;
|
||||||
border-radius: $br-small;
|
border-radius: $br-small;
|
||||||
|
|
|
@ -162,7 +162,7 @@
|
||||||
overflow: unset;
|
overflow: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
& > li {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -27,8 +27,9 @@
|
||||||
options (gobj/get props "options")
|
options (gobj/get props "options")
|
||||||
is-selectable (gobj/get props "selectable")
|
is-selectable (gobj/get props "selectable")
|
||||||
selected (gobj/get props "selected")
|
selected (gobj/get props "selected")
|
||||||
top (gobj/get props "top")
|
top (gobj/get props "top" 0)
|
||||||
left (gobj/get props "left")
|
left (gobj/get props "left" 0)
|
||||||
|
fixed? (gobj/get props "fixed?" false)
|
||||||
|
|
||||||
offset (mf/use-state 0)
|
offset (mf/use-state 0)
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps top @offset)
|
(mf/deps top @offset)
|
||||||
(fn [node]
|
(fn [node]
|
||||||
(when node
|
(when (and node (not fixed?))
|
||||||
(let [{node-height :height} (dom/get-bounding-rect node)
|
(let [{node-height :height} (dom/get-bounding-rect node)
|
||||||
{window-height :height} (dom/get-window-size)
|
{window-height :height} (dom/get-window-size)
|
||||||
target-offset (if (> (+ top node-height) window-height)
|
target-offset (if (> (+ top node-height) window-height)
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
(when open?
|
(when open?
|
||||||
[:> dropdown' props
|
[:> dropdown' props
|
||||||
[:div.context-menu {:class (classnames :is-open open?
|
[:div.context-menu {:class (classnames :is-open open?
|
||||||
|
:fixed fixed?
|
||||||
:is-selectable is-selectable)
|
:is-selectable is-selectable)
|
||||||
:style {:top (+ top @offset)
|
:style {:top (+ top @offset)
|
||||||
:left left}}
|
:left left}}
|
||||||
|
|
96
frontend/src/app/main/ui/dashboard/file_menu.cljs
Normal file
96
frontend/src/app/main/ui/dashboard/file_menu.cljs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
;; defined by the Mozilla Public License, v. 2.0.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2021 UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.main.ui.dashboard.file-menu
|
||||||
|
(:require
|
||||||
|
[app.main.data.dashboard :as dd]
|
||||||
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.store :as st]
|
||||||
|
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||||
|
[app.util.dom :as dom]
|
||||||
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
|
(mf/defc file-menu
|
||||||
|
[{:keys [file show? on-edit on-menu-close top left] :as props}]
|
||||||
|
(assert (some? file) "missing `file` prop")
|
||||||
|
(assert (boolean? show?) "missing `show?` prop")
|
||||||
|
(assert (fn? on-edit) "missing `on-edit` prop")
|
||||||
|
(assert (fn? on-menu-close) "missing `on-menu-close` prop")
|
||||||
|
(let [top (or top 0)
|
||||||
|
left (or left 0)
|
||||||
|
|
||||||
|
delete-fn
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps file)
|
||||||
|
(st/emitf (dd/delete-file file)))
|
||||||
|
|
||||||
|
on-delete
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps file)
|
||||||
|
(fn [event]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(st/emit! (modal/show
|
||||||
|
{:type :confirm
|
||||||
|
:title (tr "modals.delete-file-confirm.title")
|
||||||
|
:message (tr "modals.delete-file-confirm.message")
|
||||||
|
:accept-label (tr "modals.delete-file-confirm.accept")
|
||||||
|
:on-accept delete-fn}))))
|
||||||
|
|
||||||
|
add-shared
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps file)
|
||||||
|
(st/emitf (dd/set-file-shared (assoc file :is-shared true))))
|
||||||
|
|
||||||
|
del-shared
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps file)
|
||||||
|
(st/emitf (dd/set-file-shared (assoc file :is-shared false))))
|
||||||
|
|
||||||
|
on-add-shared
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps file)
|
||||||
|
(fn [event]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(st/emit! (modal/show
|
||||||
|
{:type :confirm
|
||||||
|
:message ""
|
||||||
|
:title (tr "modals.add-shared-confirm.message" (:name file))
|
||||||
|
:hint (tr "modals.add-shared-confirm.hint")
|
||||||
|
:cancel-label :omit
|
||||||
|
:accept-label (tr "modals.add-shared-confirm.accept")
|
||||||
|
:accept-style :primary
|
||||||
|
:on-accept add-shared}))))
|
||||||
|
|
||||||
|
on-del-shared
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps file)
|
||||||
|
(fn [event]
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(st/emit! (modal/show
|
||||||
|
{:type :confirm
|
||||||
|
:message ""
|
||||||
|
:title (tr "modals.remove-shared-confirm.message" (:name file))
|
||||||
|
:hint (tr "modals.remove-shared-confirm.hint")
|
||||||
|
:cancel-label :omit
|
||||||
|
:accept-label (tr "modals.remove-shared-confirm.accept")
|
||||||
|
:on-accept del-shared}))))]
|
||||||
|
|
||||||
|
[:& context-menu {:on-close on-menu-close
|
||||||
|
:show show?
|
||||||
|
:fixed? (or (not= top 0) (not= left 0))
|
||||||
|
:top top
|
||||||
|
:left left
|
||||||
|
:options [[(tr "labels.rename") on-edit]
|
||||||
|
[(tr "labels.delete") on-delete]
|
||||||
|
(if (:is-shared file)
|
||||||
|
[(tr "dashboard.remove-shared") on-del-shared]
|
||||||
|
[(tr "dashboard.add-shared") on-add-shared])]}]))
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||||
[app.main.ui.dashboard.grid :refer [grid]]
|
[app.main.ui.dashboard.grid :refer [grid]]
|
||||||
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
||||||
|
[app.main.ui.dashboard.project-menu :refer [project-menu]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [t]]
|
[app.util.i18n :as i18n :refer [t]]
|
||||||
|
@ -45,23 +46,6 @@
|
||||||
(mf/deps project)
|
(mf/deps project)
|
||||||
(st/emitf (dd/toggle-project-pin project)))
|
(st/emitf (dd/toggle-project-pin project)))
|
||||||
|
|
||||||
delete-fn
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps project)
|
|
||||||
(fn [event]
|
|
||||||
(st/emit! (dd/delete-project project)
|
|
||||||
(rt/nav :dashboard-projects {:team-id (:id team)}))))
|
|
||||||
|
|
||||||
on-delete
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps project)
|
|
||||||
(st/emitf (modal/show
|
|
||||||
{:type :confirm
|
|
||||||
:title (t locale "modals.delete-project-confirm.title")
|
|
||||||
:message (t locale "modals.delete-project-confirm.message")
|
|
||||||
:accept-label (t locale "modals.delete-project-confirm.accept")
|
|
||||||
:on-accept delete-fn})))
|
|
||||||
|
|
||||||
on-create-clicked
|
on-create-clicked
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps project)
|
(mf/deps project)
|
||||||
|
@ -81,12 +65,14 @@
|
||||||
(st/emit! (dd/rename-project (assoc project :name name)))
|
(st/emit! (dd/rename-project (assoc project :name name)))
|
||||||
(swap! local assoc :edition false))}]
|
(swap! local assoc :edition false))}]
|
||||||
[:div.dashboard-title
|
[:div.dashboard-title
|
||||||
[:h1 (:name project)]
|
[:h1 {:on-double-click on-edit}
|
||||||
[:div.icon {:on-click on-menu-click} i/actions]
|
(:name project)]
|
||||||
[:& context-menu {:on-close on-menu-close
|
[:div.icon {:on-click on-menu-click}
|
||||||
:show (:menu-open @local)
|
i/actions]
|
||||||
:options [[(t locale "labels.rename") on-edit]
|
[:& project-menu {:project project
|
||||||
[(t locale "labels.delete") on-delete]]}]
|
:show? (:menu-open @local)
|
||||||
|
:on-edit on-edit
|
||||||
|
:on-menu-close on-menu-close}]
|
||||||
[:div.icon.pin-icon
|
[:div.icon.pin-icon
|
||||||
{:class (when (:is-pinned project) "active")
|
{:class (when (:is-pinned project) "active")
|
||||||
:on-click toggle-pin}
|
:on-click toggle-pin}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||||
|
[app.main.ui.dashboard.file-menu :refer [file-menu]]
|
||||||
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.worker :as wrk]
|
[app.main.worker :as wrk]
|
||||||
|
@ -61,84 +62,36 @@
|
||||||
(mf/defc grid-item
|
(mf/defc grid-item
|
||||||
{:wrap [mf/memo]}
|
{:wrap [mf/memo]}
|
||||||
[{:keys [id file] :as props}]
|
[{:keys [id file] :as props}]
|
||||||
(let [local (mf/use-state {:menu-open false :edition false})
|
(let [local (mf/use-state {:menu-open false
|
||||||
|
:menu-pos nil
|
||||||
|
:edition false})
|
||||||
locale (mf/deref i18n/locale)
|
locale (mf/deref i18n/locale)
|
||||||
on-close (mf/use-callback #(swap! local assoc :menu-open false))
|
menu-ref (mf/use-ref)
|
||||||
|
|
||||||
delete-fn
|
on-menu-close
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps file)
|
#(swap! local assoc :menu-open false))
|
||||||
(st/emitf (dd/delete-file file)))
|
|
||||||
|
|
||||||
on-delete
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps file)
|
|
||||||
(fn [event]
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(st/emit! (modal/show
|
|
||||||
{:type :confirm
|
|
||||||
:title (t locale "modals.delete-file-confirm.title")
|
|
||||||
:message (t locale "modals.delete-file-confirm.message")
|
|
||||||
:accept-label (t locale "modals.delete-file-confirm.accept")
|
|
||||||
:on-accept delete-fn}))))
|
|
||||||
|
|
||||||
on-navigate
|
on-navigate
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps id)
|
(mf/deps id)
|
||||||
(fn []
|
|
||||||
(let [pparams {:project-id (:project-id file)
|
|
||||||
:file-id (:id file)}
|
|
||||||
qparams {:page-id (first (get-in file [:data :pages]))}]
|
|
||||||
(st/emit! (rt/nav :workspace pparams qparams)))))
|
|
||||||
|
|
||||||
|
|
||||||
add-shared
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps file)
|
|
||||||
(st/emitf (dd/set-file-shared (assoc file :is-shared true))))
|
|
||||||
|
|
||||||
del-shared
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps file)
|
|
||||||
(st/emitf (dd/set-file-shared (assoc file :is-shared false))))
|
|
||||||
|
|
||||||
on-add-shared
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps file)
|
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(let [menu-icon (mf/ref-val menu-ref)
|
||||||
(st/emit! (modal/show
|
target (dom/get-target event)]
|
||||||
{:type :confirm
|
(when-not (dom/child? target menu-icon)
|
||||||
:message ""
|
(let [pparams {:project-id (:project-id file)
|
||||||
:title (t locale "modals.add-shared-confirm.message" (:name file))
|
:file-id (:id file)}
|
||||||
:hint (t locale "modals.add-shared-confirm.hint")
|
qparams {:page-id (first (get-in file [:data :pages]))}]
|
||||||
:cancel-label :omit
|
(st/emit! (rt/nav :workspace pparams qparams)))))))
|
||||||
:accept-label (t locale "modals.add-shared-confirm.accept")
|
|
||||||
:accept-style :primary
|
|
||||||
:on-accept add-shared}))))
|
|
||||||
|
|
||||||
on-del-shared
|
|
||||||
(mf/use-callback
|
|
||||||
(mf/deps file)
|
|
||||||
(fn [event]
|
|
||||||
(dom/prevent-default event)
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(st/emit! (modal/show
|
|
||||||
{:type :confirm
|
|
||||||
:message ""
|
|
||||||
:title (t locale "modals.remove-shared-confirm.message" (:name file))
|
|
||||||
:hint (t locale "modals.remove-shared-confirm.hint")
|
|
||||||
:cancel-label :omit
|
|
||||||
:accept-label (t locale "modals.remove-shared-confirm.accept")
|
|
||||||
:on-accept del-shared}))))
|
|
||||||
|
|
||||||
on-menu-click
|
on-menu-click
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps file)
|
(mf/deps file)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(let [position (dom/get-client-position event)]
|
||||||
(swap! local assoc :menu-open true)))
|
(swap! local assoc :menu-open true
|
||||||
|
:menu-pos position))))
|
||||||
|
|
||||||
edit
|
edit
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
@ -154,10 +107,10 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(swap! local assoc
|
(swap! local assoc
|
||||||
:edition true
|
:edition true
|
||||||
:menu-open false)))
|
:menu-open false)))]
|
||||||
|
|
||||||
]
|
[:div.grid-item.project-th {:on-click on-navigate
|
||||||
[:div.grid-item.project-th {:on-click on-navigate}
|
:on-context-menu on-menu-click}
|
||||||
[:div.overlay]
|
[:div.overlay]
|
||||||
[:& grid-item-thumbnail {:file file}]
|
[:& grid-item-thumbnail {:file file}]
|
||||||
(when (:is-shared file)
|
(when (:is-shared file)
|
||||||
|
@ -171,15 +124,15 @@
|
||||||
[:div.project-th-actions {:class (dom/classnames
|
[:div.project-th-actions {:class (dom/classnames
|
||||||
:force-display (:menu-open @local))}
|
:force-display (:menu-open @local))}
|
||||||
[:div.project-th-icon.menu
|
[:div.project-th-icon.menu
|
||||||
{:on-click on-menu-click}
|
{:ref menu-ref
|
||||||
i/actions]
|
:on-click on-menu-click}
|
||||||
[:& context-menu {:on-close on-close
|
i/actions]]
|
||||||
:show (:menu-open @local)
|
[:& file-menu {:file file
|
||||||
:options [[(t locale "labels.rename") on-edit]
|
:show? (:menu-open @local)
|
||||||
[(t locale "labels.delete") on-delete]
|
:left (:x (:menu-pos @local))
|
||||||
(if (:is-shared file)
|
:top (:y (:menu-pos @local))
|
||||||
[(t locale "dashboard.remove-shared") on-del-shared]
|
:on-edit on-edit
|
||||||
[(t locale "dashboard.add-shared") on-add-shared])]}]]]))
|
:on-menu-close on-menu-close}]]))
|
||||||
|
|
||||||
(mf/defc empty-placeholder
|
(mf/defc empty-placeholder
|
||||||
[]
|
[]
|
||||||
|
|
53
frontend/src/app/main/ui/dashboard/project_menu.cljs
Normal file
53
frontend/src/app/main/ui/dashboard/project_menu.cljs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
;; defined by the Mozilla Public License, v. 2.0.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2021 UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.main.ui.dashboard.project-menu
|
||||||
|
(:require
|
||||||
|
[app.main.data.dashboard :as dd]
|
||||||
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.store :as st]
|
||||||
|
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||||
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
[app.util.router :as rt]
|
||||||
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
|
(mf/defc project-menu
|
||||||
|
[{:keys [project show? on-edit on-menu-close top left] :as props}]
|
||||||
|
(assert (some? project) "missing `project` prop")
|
||||||
|
(assert (boolean? show?) "missing `show?` prop")
|
||||||
|
(assert (fn? on-edit) "missing `on-edit` prop")
|
||||||
|
(assert (fn? on-menu-close) "missing `on-menu-close` prop")
|
||||||
|
(let [top (or top 0)
|
||||||
|
left (or left 0)
|
||||||
|
|
||||||
|
delete-fn
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps project)
|
||||||
|
(fn [event]
|
||||||
|
(st/emit! (dd/delete-project project)
|
||||||
|
(rt/nav :dashboard-projects {:team-id (:team-id project)}))))
|
||||||
|
|
||||||
|
on-delete
|
||||||
|
(mf/use-callback
|
||||||
|
(mf/deps project)
|
||||||
|
(st/emitf (modal/show
|
||||||
|
{:type :confirm
|
||||||
|
:title (tr "modals.delete-project-confirm.title")
|
||||||
|
:message (tr "modals.delete-project-confirm.message")
|
||||||
|
:accept-label (tr "modals.delete-project-confirm.accept")
|
||||||
|
:on-accept delete-fn})))]
|
||||||
|
|
||||||
|
[:& context-menu {:on-close on-menu-close
|
||||||
|
:show show?
|
||||||
|
:fixed? (or (not= top 0) (not= left 0))
|
||||||
|
:top top
|
||||||
|
:left left
|
||||||
|
:options [[(tr "labels.rename") on-edit]
|
||||||
|
[(tr "labels.delete") on-delete]]}]))
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
(mf/deps project)
|
(mf/deps project)
|
||||||
(st/emitf (rt/nav :dashboard-files {:team-id (:team-id project)
|
(st/emitf (rt/nav :dashboard-files {:team-id (:team-id project)
|
||||||
:project-id (:id project)})))
|
:project-id (:id project)})))
|
||||||
|
|
||||||
toggle-pin
|
toggle-pin
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps project)
|
(mf/deps project)
|
||||||
|
@ -88,7 +89,6 @@
|
||||||
params {:project-id (:id project)}]
|
params {:project-id (:id project)}]
|
||||||
(st/emit! (dd/create-file (with-meta params mdata))))))]
|
(st/emit! (dd/create-file (with-meta params mdata))))))]
|
||||||
|
|
||||||
|
|
||||||
[:div.dashboard-project-row {:class (when first? "first")}
|
[:div.dashboard-project-row {:class (when first? "first")}
|
||||||
[:div.project
|
[:div.project
|
||||||
(when-not (:is-default project)
|
(when-not (:is-default project)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
[app.main.ui.components.forms :as fm]
|
[app.main.ui.components.forms :as fm]
|
||||||
[app.main.ui.dashboard.comments :refer [comments-section]]
|
[app.main.ui.dashboard.comments :refer [comments-section]]
|
||||||
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
||||||
|
[app.main.ui.dashboard.project-menu :refer [project-menu]]
|
||||||
[app.main.ui.dashboard.team-form]
|
[app.main.ui.dashboard.team-form]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.avatars :as avatars]
|
[app.util.avatars :as avatars]
|
||||||
|
@ -42,10 +43,12 @@
|
||||||
|
|
||||||
(mf/defc sidebar-project
|
(mf/defc sidebar-project
|
||||||
[{:keys [item selected?] :as props}]
|
[{:keys [item selected?] :as props}]
|
||||||
(let [dstate (mf/deref refs/dashboard-local)
|
(let [dstate (mf/deref refs/dashboard-local)
|
||||||
edit-id (:project-for-edit dstate)
|
edit-id (:project-for-edit dstate)
|
||||||
|
|
||||||
edition? (mf/use-state (= (:id item) edit-id))
|
local (mf/use-state {:menu-open false
|
||||||
|
:menu-pos nil
|
||||||
|
:edition? (= (:id item) edit-id)})
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
@ -54,23 +57,41 @@
|
||||||
(st/emit! (rt/nav :dashboard-files {:team-id (:team-id item)
|
(st/emit! (rt/nav :dashboard-files {:team-id (:team-id item)
|
||||||
:project-id (:id item)}))))
|
:project-id (:id item)}))))
|
||||||
|
|
||||||
on-dbl-click
|
on-menu-click
|
||||||
(mf/use-callback #(reset! edition? true))
|
(mf/use-callback (fn [event]
|
||||||
|
(let [position (dom/get-client-position event)]
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(swap! local assoc :menu-open true
|
||||||
|
:menu-pos position))))
|
||||||
|
|
||||||
|
on-menu-close
|
||||||
|
(mf/use-callback #(swap! local assoc :menu-open false))
|
||||||
|
|
||||||
|
on-edit-open
|
||||||
|
(mf/use-callback #(swap! local assoc :edition? true))
|
||||||
|
|
||||||
on-edit
|
on-edit
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps item)
|
(mf/deps item)
|
||||||
(fn [name]
|
(fn [name]
|
||||||
(st/emit! (dd/rename-project (assoc item :name name)))
|
(st/emit! (dd/rename-project (assoc item :name name)))
|
||||||
(reset! edition? false)))]
|
(swap! local assoc :edition? false)))]
|
||||||
|
|
||||||
[:li {:on-click on-click
|
[:*
|
||||||
:on-double-click on-dbl-click
|
[:li {:on-click on-click
|
||||||
:class (when selected? "current")}
|
:on-double-click on-edit-open
|
||||||
(if @edition?
|
:on-context-menu on-menu-click
|
||||||
[:& inline-edition {:content (:name item)
|
:class (when selected? "current")}
|
||||||
:on-end on-edit}]
|
(if (:edition? @local)
|
||||||
[:span.element-title (:name item)])]))
|
[:& inline-edition {:content (:name item)
|
||||||
|
:on-end on-edit}]
|
||||||
|
[:span.element-title (:name item)])]
|
||||||
|
[:& project-menu {:project item
|
||||||
|
:show? (:menu-open @local)
|
||||||
|
:left (:x (:menu-pos @local))
|
||||||
|
:top (:y (:menu-pos @local))
|
||||||
|
:on-edit on-edit-open
|
||||||
|
:on-menu-close on-menu-close}]]))
|
||||||
|
|
||||||
(mf/defc sidebar-search
|
(mf/defc sidebar-search
|
||||||
[{:keys [search-term team-id locale] :as props}]
|
[{:keys [search-term team-id locale] :as props}]
|
||||||
|
|
|
@ -249,6 +249,9 @@
|
||||||
(let [class-list (.-classList ^js node)]
|
(let [class-list (.-classList ^js node)]
|
||||||
(.contains ^js class-list class-name)))
|
(.contains ^js class-list class-name)))
|
||||||
|
|
||||||
|
(defn child? [node1 node2]
|
||||||
|
(.contains ^js node2 ^js node1))
|
||||||
|
|
||||||
(defn get-user-agent []
|
(defn get-user-agent []
|
||||||
(.-userAgent globals/navigator))
|
(.-userAgent globals/navigator))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue