diff --git a/backend/src/uxbox/services/mutations/pages.clj b/backend/src/uxbox/services/mutations/pages.clj index 5ea32c3f7..a1bca24e9 100644 --- a/backend/src/uxbox/services/mutations/pages.clj +++ b/backend/src/uxbox/services/mutations/pages.clj @@ -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) diff --git a/backend/src/uxbox/services/queries/files.clj b/backend/src/uxbox/services/queries/files.clj index b28b477f7..2baa0855c 100644 --- a/backend/src/uxbox/services/queries/files.clj +++ b/backend/src/uxbox/services/queries/files.clj @@ -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 diff --git a/backend/src/uxbox/services/queries/recent_files.clj b/backend/src/uxbox/services/queries/recent_files.clj index b99b83128..bf23a25b9 100644 --- a/backend/src/uxbox/services/queries/recent_files.clj +++ b/backend/src/uxbox/services/queries/recent_files.clj @@ -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 diff --git a/frontend/src/uxbox/main/data/workspace.cljs b/frontend/src/uxbox/main/data/workspace.cljs index 54bf6e439..19f1b4610 100644 --- a/frontend/src/uxbox/main/data/workspace.cljs +++ b/frontend/src/uxbox/main/data/workspace.cljs @@ -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 diff --git a/frontend/src/uxbox/main/ui/dashboard/grid.cljs b/frontend/src/uxbox/main/ui/dashboard/grid.cljs index 1fc12d738..17014d12b 100644 --- a/frontend/src/uxbox/main/ui/dashboard/grid.cljs +++ b/frontend/src/uxbox/main/ui/dashboard/grid.cljs @@ -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 diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs index 5ceb9ef33..6b433ffca 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs @@ -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) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap.cljs index 77e3822e8..2eedc6bd5 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/sitemap.cljs @@ -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