0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

🎉 Add page ordering (with d&d).

This commit is contained in:
Andrey Antukh 2020-04-19 13:51:42 +02:00 committed by Alonso Torres
parent 11f54f51ea
commit 04d364225c
7 changed files with 91 additions and 51 deletions

View file

@ -11,6 +11,7 @@
(:require
[clojure.spec.alpha :as s]
[promesa.core :as p]
[uxbox.common.data :as d]
[uxbox.common.pages :as cp]
[uxbox.common.exceptions :as ex]
[uxbox.common.spec :as us]
@ -106,6 +107,33 @@
;; --- Mutation: Sort Pages
(s/def ::page-ids (s/every ::us/uuid :kind vector?))
(s/def ::reorder-pages
(s/keys :req-un [::profile-id ::file-id ::page-ids]))
(declare update-page-ordering)
(sm/defmutation ::reorder-pages
[{:keys [profile-id file-id page-ids]}]
(db/with-atomic [conn db/pool]
(p/run! #(update-page-ordering conn file-id %)
(d/enumerate page-ids))
nil))
(def ^:private sql:update-page-ordering
"update page
set ordering = $1
where id = $2 and file_id = $3")
(defn- update-page-ordering
[conn file-id [ordering page-id]]
(-> (db/query-one conn [sql:update-page-ordering ordering page-id file-id])
(p/then su/constantly-nil)))
;; --- Mutation: Generate Share Token
(declare assign-page-share-token)

View file

@ -93,7 +93,7 @@
and (fp_r.is_admin = true or
fp_r.is_owner = true or
fp_r.can_edit = true)
window pages_w as (partition by f.id order by pg.created_at
window pages_w as (partition by f.id order by pg.ordering
range between unbounded preceding
and unbounded following)
order by f.modified_at desc")
@ -182,7 +182,7 @@
where f.id = $1
and f.deleted_at is null
and pg.deleted_at is null
window pages_w as (partition by f.id order by pg.created_at
window pages_w as (partition by f.id order by pg.ordering
range between unbounded preceding
and unbounded following)")
@ -229,22 +229,6 @@
(check-edition-permissions! conn profile-id id)
(retrieve-file conn id)))
;; --- Query: Project Files
;; (declare retrieve-project-files)
;; (s/def ::project-files
;; (s/keys :req-un [::profile-id]
;; :opt-un [::project-id]))
;; (sq/defquery ::project-files
;; [{:keys [project-id] :as params}]
;; (retrieve-project-files db/pool params))
;; (defn retrieve-project-files
;; [conn {:keys [profile-id project-id]}]
;; (-> (db/query conn [sql:project-files profile-id project-id])
;; (p/then' (partial mapv decode-row))))
;; --- Helpers

View file

@ -32,7 +32,7 @@
and (fp_r.is_admin = true or
fp_r.is_owner = true or
fp_r.can_edit = true)
window pages_w as (partition by f.id order by pg.created_at
window pages_w as (partition by f.id order by pg.ordering
range between unbounded preceding
and unbounded following)
order by f.modified_at desc

View file

@ -1326,6 +1326,28 @@
[]
{:commit-local? true}))))))
;; --- Change Page Order (D&D Ordering)
(defn relocate-page
[id index]
(ptk/reify ::relocate-pages
ptk/UpdateEvent
(update [_ state]
(let [pages (get-in state [:workspace-file :pages])
[before after] (split-at index pages)
p? (partial = id)
pages' (d/concat []
(remove p? before)
[id]
(remove p? after))]
(assoc-in state [:workspace-file :pages] pages')))
ptk/WatchEvent
(watch [_ state stream]
(let [file (:workspace-file state)]
(->> (rp/mutation! :reorder-pages {:page-ids (:pages file)
:file-id (:id file)})
(rx/ignore))))))
;; --- Shape / Selection Alignment and Distribution

View file

@ -1,5 +1,4 @@
(ns uxbox.main.ui.dashboard.grid
(:refer-clojure :exclude [sort-by])
(:require
[cuerdas.core :as str]
[rumext.alpha :as mf]
@ -11,7 +10,6 @@
[uxbox.main.ui.keyboard :as kbd]
[uxbox.main.ui.confirm :refer [confirm-dialog]]
[uxbox.main.ui.components.context-menu :refer [context-menu]]
[uxbox.util.data :refer [classnames]]
[uxbox.util.dom :as dom]
[uxbox.util.i18n :as i18n :refer [t tr]]
[uxbox.util.router :as rt]
@ -75,7 +73,7 @@
:default-value (:name file)}]
[:h3 (:name file)])
[:& grid-item-metadata {:modified-at (:modified-at file)}]]
[:div.project-th-actions {:class (classnames
[:div.project-th-actions {:class (dom/classnames
:force-display (:menu-open @local))}
;; [:div.project-th-icon.pages
;; i/page

View file

@ -162,7 +162,6 @@
]
[:li {:on-context-menu on-context-menu
:ref dref
:data-index index
:class (dom/classnames
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot)

View file

@ -10,6 +10,7 @@
[cuerdas.core :as str]
[okulary.core :as l]
[rumext.alpha :as mf]
[uxbox.common.data :as d]
[uxbox.builtins.icons :as i]
[uxbox.main.data.workspace :as dw]
[uxbox.main.store :as st]
@ -17,7 +18,7 @@
[uxbox.main.ui.confirm :refer [confirm-dialog]]
[uxbox.main.ui.keyboard :as kbd]
[uxbox.main.ui.modal :as modal]
[uxbox.util.data :refer [classnames enumerate]]
[uxbox.main.ui.hooks :as hooks]
[uxbox.util.dom :as dom]
[uxbox.util.i18n :as i18n :refer [t]]
[uxbox.util.router :as rt]))
@ -27,6 +28,7 @@
(mf/defc page-item
[{:keys [page index deletable? selected?] :as props}]
(let [local (mf/use-state {})
on-double-click
(fn [event]
(dom/prevent-default event)
@ -54,22 +56,27 @@
(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}))
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 {:class (classnames :selected selected?)}
[:div.element-list-body {:class (classnames
:selected selected?
;; :dragging (:dragging? dprops)
)
on-drop
(fn [side {:keys [id name] :as data}]
(let [index (if (= :bot side) (inc index) index)]
(st/emit! (dw/relocate-page id index))))
[dprops dref] (hooks/use-sortable
:type "page"
:on-drop on-drop
:data {:id (:id page)
:index index
:name (:name page)})]
[:li {:class (dom/classnames
:selected selected?
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot))
:ref dref}
[:div.element-list-body {:class (dom/classnames
:selected selected?)
:on-click navigate-fn
:on-double-click on-double-click}
[:div.page-icon i/file-html]
@ -89,16 +96,17 @@
;; --- Page Item Wrapper
(defn- make-page-ref
(defn- make-page-iref
[id]
#(-> (l/in [:workspace-pages id])
(l/derived st/state)))
#(l/derived (fn [state]
(let [page (get-in state [:workspace-pages id])]
(select-keys page [:id :name :ordering])))
st/state =))
(mf/defc page-item-wrapper
[{:keys [page-id index deletable? selected?] :as props}]
(let [page-iref (mf/use-memo
(mf/deps page-id)
(make-page-ref page-id))
(let [page-iref (mf/use-memo (mf/deps page-id)
(make-page-iref page-id))
page (mf/deref page-iref)]
[:& page-item {:page page
:index index
@ -109,15 +117,16 @@
(mf/defc pages-list
[{:keys [file current-page] :as props}]
(let [pages (enumerate (:pages file))
(let [pages (d/enumerate (:pages file))
deletable? (> (count pages) 1)]
[:ul.element-list
(for [[index page-id] pages]
[:& page-item-wrapper {:page-id page-id
:index index
:deletable? deletable?
:selected? (= page-id (:id current-page))
:key page-id}])]))
[:& page-item-wrapper
{:page-id page-id
:index index
:deletable? deletable?
:selected? (= page-id (:id current-page))
:key page-id}])]))
;; --- Sitemap Toolbox