From 582a20d369f951b9f0f2d82c3a28235e78966edd Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 10 Oct 2022 15:55:14 +0200 Subject: [PATCH] :sparkles: Improve consistency on event handling on dashboard --- frontend/src/app/main/ui/dashboard/files.cljs | 123 +++++++++--------- frontend/src/app/main/ui/dashboard/grid.cljs | 22 ++-- .../app/main/ui/dashboard/placeholder.cljs | 36 ++--- .../src/app/main/ui/dashboard/projects.cljs | 112 +++++++++------- 4 files changed, 162 insertions(+), 131 deletions(-) diff --git a/frontend/src/app/main/ui/dashboard/files.cljs b/frontend/src/app/main/ui/dashboard/files.cljs index d298e2fb11..747192a7ca 100644 --- a/frontend/src/app/main/ui/dashboard/files.cljs +++ b/frontend/src/app/main/ui/dashboard/files.cljs @@ -23,29 +23,38 @@ [rumext.v2 :as mf])) (mf/defc header - [{:keys [project on-create-clicked] :as props}] - (let [local (mf/use-state {:menu-open false - :edition false}) + [{:keys [project create-fn] :as props}] + (let [local (mf/use-state + {:menu-open false + :edition false}) + + on-create-click + (mf/use-fn + (mf/deps create-fn) + (fn [event] + (dom/prevent-default event) + (create-fn "dashboard:header"))) + on-menu-click - (mf/use-callback + (mf/use-fn (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)) + (mf/use-fn #(swap! local assoc :menu-open false)) on-edit - (mf/use-callback #(swap! local assoc :edition true :menu-open false)) + (mf/use-fn #(swap! local assoc :edition true :menu-open false)) toggle-pin - (mf/use-callback + (mf/use-fn (mf/deps project) #(st/emit! (dd/toggle-project-pin project))) on-import - (mf/use-callback + (mf/use-fn (mf/deps (:id project)) (fn [] (st/emit! (dd/fetch-files {:project-id (:id project)}) @@ -78,7 +87,7 @@ :on-import on-import}] [:div.dashboard-header-actions - [:a.btn-secondary.btn-small {:on-click (partial on-create-clicked project "dashboard:header") :data-test "new-file"} + [:a.btn-secondary.btn-small {:on-click on-create-click :data-test "new-file"} (tr "dashboard.new-file")] (when-not (:is-default project) @@ -95,69 +104,65 @@ (mf/defc files-section [{:keys [project team] :as props}] - (let [files-map (mf/deref refs/dashboard-files) - width (mf/use-state nil) - rowref (mf/use-ref) - itemsize (if (>= @width 1030) - 280 - 230) + (let [files-map (mf/deref refs/dashboard-files) + project-id (:id project) + width (mf/use-state nil) + rowref (mf/use-ref) + itemsize (if (>= @width 1030) + 280 + 230) - ratio (if (some? @width) (/ @width itemsize) 0) - nitems (mth/floor ratio) - limit (min 10 nitems) - limit (max 1 limit) + ratio (if (some? @width) (/ @width itemsize) 0) + nitems (mth/floor ratio) + limit (min 10 nitems) + limit (max 1 limit) - files (->> (vals files-map) - (filter #(= (:id project) (:project-id %))) - (sort-by :modified-at) - (reverse)) + files (mf/with-memo [project-id files-map] + (->> (vals files-map) + (filter #(= project-id (:project-id %))) + (sort-by :modified-at) + (reverse))) - on-create-clicked - (mf/use-callback - (fn [project origin event] - (dom/prevent-default event) + create-file + (mf/use-fn + (fn [origin] (st/emit! (with-meta (dd/create-file {:project-id (:id project)}) {::ev/origin origin}))))] - (mf/use-effect - (fn [] - (let [node (mf/ref-val rowref) - mnt? (volatile! true) - sub (->> (wapi/observe-resize node) - (rx/observe-on :af) - (rx/subs (fn [entries] - (let [row (first entries) - row-rect (.-contentRect ^js row) - row-width (.-width ^js row-rect)] - (when @mnt? - (reset! width row-width))))))] - (fn [] - (vreset! mnt? false) - (rx/dispose! sub))))) + (mf/with-effect [] + (let [node (mf/ref-val rowref) + mnt? (volatile! true) + sub (->> (wapi/observe-resize node) + (rx/observe-on :af) + (rx/subs (fn [entries] + (let [row (first entries) + row-rect (.-contentRect ^js row) + row-width (.-width ^js row-rect)] + (when @mnt? + (reset! width row-width))))))] + (fn [] + (vreset! mnt? false) + (rx/dispose! sub)))) + (mf/with-effect [project] + (when project + (let [pname (if (:is-default project) + (tr "labels.drafts") + (:name project))] + (dom/set-html-title (tr "title.dashboard.files" pname))))) - (mf/use-effect - (mf/deps project) - (fn [] - (when project - (let [pname (if (:is-default project) - (tr "labels.drafts") - (:name project))] - (dom/set-html-title (tr "title.dashboard.files" pname)))))) - - (mf/use-effect - (mf/deps project) - (fn [] - (st/emit! (dd/fetch-files {:project-id (:id project)}) - (dd/clear-selected-files)))) + (mf/with-effect [project-id] + (st/emit! (dd/fetch-files {:project-id project-id}) + (dd/clear-selected-files))) [:* - [:& header {:team team :project project - :on-create-clicked on-create-clicked}] + [:& header {:team team + :project project + :create-fn create-file}] [:section.dashboard-container.no-bg {:ref rowref} [:& grid {:project project :files files - :on-create-clicked on-create-clicked :origin :files + :create-fn create-file :limit limit}]]])) diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 3621380be1..83df572260 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -177,8 +177,8 @@ [{:keys [file navigate? origin library-view?] :as props}] (let [file-id (:id file) local (mf/use-state {:menu-open false - :menu-pos nil - :edition false}) + :menu-pos nil + :edition false}) selected-files (mf/deref refs/dashboard-selected-files) dashboard-local (mf/deref refs/dashboard-local) node-ref (mf/use-ref) @@ -313,7 +313,7 @@ (mf/defc grid - [{:keys [files project on-create-clicked origin limit library-view?] :as props}] + [{:keys [files project origin limit library-view? create-fn] :as props}] (let [dragging? (mf/use-state false) project-id (:id project) node-ref (mf/use-var nil) @@ -384,10 +384,8 @@ :else [:& empty-placeholder - {:default? (:is-default project) - :on-create-clicked on-create-clicked - :project project - :limit limit + {:limit limit + :create-fn create-fn :origin origin}])])) (mf/defc line-grid-row @@ -407,7 +405,7 @@ :navigate? false}])])) (mf/defc line-grid - [{:keys [project team files limit on-create-clicked] :as props}] + [{:keys [project team files limit create-fn] :as props}] (let [dragging? (mf/use-state false) project-id (:id project) team-id (:id team) @@ -494,8 +492,8 @@ :limit limit}] :else - [:& empty-placeholder {:dragging? @dragging? - :default? (:is-default project) - :on-create-clicked on-create-clicked - :limit limit}])])) + [:& empty-placeholder + {:dragging? @dragging? + :limit limit + :create-fn create-fn}])])) diff --git a/frontend/src/app/main/ui/dashboard/placeholder.cljs b/frontend/src/app/main/ui/dashboard/placeholder.cljs index bc85b64ff4..6ea8f2a096 100644 --- a/frontend/src/app/main/ui/dashboard/placeholder.cljs +++ b/frontend/src/app/main/ui/dashboard/placeholder.cljs @@ -11,21 +11,27 @@ [rumext.v2 :as mf])) (mf/defc empty-placeholder - [{:keys [dragging? on-create-clicked project limit origin] :as props}] - (cond - (true? dragging?) - [:div.grid-row.no-wrap - {:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}} - [:div.grid-item]] - (= :libraries origin) - [:div.grid-empty-placeholder.libs {:data-test "empty-placeholder"} - [:div.text - [:& i18n/tr-html {:label "dashboard.empty-placeholder-drafts"}]]] - :else - [:div.grid-empty-placeholder - {:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}} - [:button.create-new {:on-click (partial on-create-clicked project "dashboard:empty-folder-placeholder")} - (tr "dashboard.new-file")]])) + [{:keys [dragging? limit origin create-fn] :as props}] + (let [on-click + (mf/use-fn + (mf/deps create-fn) + (fn [_] + (create-fn "dashboard:empty-folder-placeholder")))] + (cond + (true? dragging?) + [:div.grid-row.no-wrap + {:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}} + [:div.grid-item]] + + (= :libraries origin) + [:div.grid-empty-placeholder.libs {:data-test "empty-placeholder"} + [:div.text + [:& i18n/tr-html {:label "dashboard.empty-placeholder-drafts"}]]] + + :else + [:div.grid-empty-placeholder + {:style {:grid-template-columns (str "repeat(" limit ", 1fr)")}} + [:button.create-new {:on-click on-click} (tr "dashboard.new-file")]]))) (mf/defc loading-placeholder [] diff --git a/frontend/src/app/main/ui/dashboard/projects.cljs b/frontend/src/app/main/ui/dashboard/projects.cljs index 08b507302e..d04a27e9eb 100644 --- a/frontend/src/app/main/ui/dashboard/projects.cljs +++ b/frontend/src/app/main/ui/dashboard/projects.cljs @@ -33,37 +33,47 @@ (mf/defc header {::mf/wrap [mf/memo]} [] - (let [create #(st/emit! (dd/create-project))] + (let [on-click (mf/use-fn #(st/emit! (dd/create-project)))] [:header.dashboard-header [:div.dashboard-title [:h1 (tr "dashboard.projects-title")]] - - [:a.btn-secondary.btn-small {:on-click create :data-test "new-project-button"} + [:a.btn-secondary.btn-small + {:on-click on-click + :data-test "new-project-button"} (tr "dashboard.new-project")]])) (mf/defc team-hero {::mf/wrap [mf/memo]} - [{:keys [team close-banner] :as props}] - (let [go-members (mf/use-fn #(st/emit! (dd/go-to-team-members))) + [{:keys [team close-fn] :as props}] + (let [on-nav-members-click (mf/use-fn #(st/emit! (dd/go-to-team-members))) - invite-member + on-invite-click (mf/use-fn (mf/deps team) (fn [] (st/emit! (modal/show {:type :invite-members :team team - :origin :hero}))))] + :origin :hero})))) + on-close-click + (mf/use-fn + (mf/deps close-fn) + (fn [event] + (dom/prevent-default event) + (close-fn)))] + [:div.team-hero [:img {:src "images/deco-team-banner.png" :border "0"}] [:div.text [:div.title (tr "dasboard.team-hero.title")] [:div.info [:span (tr "dasboard.team-hero.text")] - [:a {:on-click go-members} (tr "dasboard.team-hero.management")]]] + [:a {:on-click on-nav-members-click} (tr "dasboard.team-hero.management")]]] [:button.btn-primary.invite - {:on-click invite-member} + {:on-click on-invite-click} (tr "onboarding.choice.team-up.invite-members")] - [:button.close {:on-click close-banner} + [:button.close + {:on-click on-close-click + :aria-label (tr "labels.close")} [:span i/close]]])) (def builtin-templates @@ -140,6 +150,7 @@ (let [locale (mf/deref i18n/locale) file-count (or (:count project) 0) project-id (:id project) + team-id (:id team) dstate (mf/deref refs/dashboard-local) edit-id (:project-for-edit dstate) @@ -161,30 +172,33 @@ on-nav (mf/use-fn - (mf/deps project) + (mf/deps project-id team-id) (fn [] - (st/emit! (rt/nav :dashboard-files {:team-id (:team-id project) - :project-id project-id})))) + (st/emit! (rt/nav :dashboard-files + {:team-id team-id + :project-id project-id})))) toggle-pin - (mf/use-callback + (mf/use-fn (mf/deps project) #(st/emit! (dd/toggle-project-pin project))) on-menu-click - (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)))) + (mf/use-fn + (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)) + (mf/use-fn #(swap! local assoc :menu-open false)) on-edit-open - (mf/use-callback #(swap! local assoc :edition? true)) + (mf/use-fn #(swap! local assoc :edition? true)) on-edit - (mf/use-callback + (mf/use-fn (mf/deps project) (fn [name] (let [name (str/trim name)] @@ -194,29 +208,33 @@ (swap! local assoc :edition? false)))) on-file-created - (mf/use-callback - (mf/deps project) + (mf/use-fn (fn [data] (let [pparams {:project-id (:project-id data) :file-id (:id data)} qparams {:page-id (get-in data [:data :pages 0])}] (st/emit! (rt/nav :workspace pparams qparams))))) - create-file - (mf/use-callback - (mf/deps project) + (mf/use-fn + (mf/deps project-id on-file-created) (fn [origin] (let [mdata {:on-success on-file-created} - params {:project-id (:id project)}] - (st/emit! (with-meta (dd/create-file (with-meta params mdata)) - {::ev/origin origin}))))) + params {:project-id project-id}] + (st/emit! (-> (dd/create-file (with-meta params mdata)) + (with-meta {::ev/origin origin})))))) + + on-create-click + (mf/use-fn + (mf/deps create-file) + (fn [_] + (create-file "dashboard:grid-header-plus-button"))) on-import - (mf/use-callback - (mf/deps (:id project) (:id team)) + (mf/use-fn + (mf/deps project-id (:id team)) (fn [] - (st/emit! (dd/fetch-files {:project-id (:id project)}) + (st/emit! (dd/fetch-files {:project-id project-id}) (dd/fetch-recent-files (:id team)) (dd/clear-selected-files))))] @@ -235,7 +253,6 @@ (vreset! mnt? false) (rx/dispose! sub)))) - [:div.dashboard-project-row {:class (when first? "first")} [:div.project {:ref rowref} @@ -249,13 +266,14 @@ (tr "labels.drafts") (:name project))]) - [:& project-menu {:project project - :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 - :on-import on-import}] + [:& project-menu + {:project project + :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 + :on-import on-import}] [:span.info (str (tr "labels.num-of-files" (i18n/c file-count)))] (when (> file-count 0) @@ -272,11 +290,15 @@ i/pin)]) [:a.btn-secondary.btn-small.tooltip.tooltip-bottom - {:on-click create-file :alt (tr "dashboard.new-file") :data-test "project-new-file"} + {:on-click on-create-click + :alt (tr "dashboard.new-file") + :data-test "project-new-file"} i/close] [:a.btn-secondary.btn-small.tooltip.tooltip-bottom - {:on-click on-menu-click :alt (tr "dashboard.options") :data-test "project-options"} + {:on-click on-menu-click + :alt (tr "dashboard.options") + :data-test "project-options"} i/actions]]] (when (and (> limit 0) @@ -290,7 +312,7 @@ {:project project :team team :files files - :on-create-clicked (partial create-file "dashboard:empty-folder-placeholder") + :create-fn create-file :limit limit}]])) @@ -349,7 +371,7 @@ [:& header] (when team-hero? - [:& team-hero {:team team :close-banner close-banner}]) + [:& team-hero {:team team :close-fn close-banner}]) (when (or (not tutorial-viewed?) (not walkthrough-viewed?)) [:div.hero-projects