0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-25 07:58:49 -05:00

Implement recent files (back and front).

This commit is contained in:
Andrey Antukh 2019-12-11 12:15:06 +01:00
parent 4dad6bef40
commit 44e120d382
6 changed files with 72 additions and 42 deletions

View file

@ -7,9 +7,11 @@
(ns uxbox.services.queries.project-files (ns uxbox.services.queries.project-files
(:require (:require
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[cuerdas.core :as str]
[promesa.core :as p] [promesa.core :as p]
[uxbox.db :as db] [uxbox.db :as db]
[uxbox.services.queries :as sq] [uxbox.services.queries :as sq]
[uxbox.services.util :as su]
[uxbox.util.blob :as blob] [uxbox.util.blob :as blob]
[uxbox.util.spec :as us])) [uxbox.util.spec :as us]))
@ -22,7 +24,7 @@
(s/def ::project-id ::us/uuid) (s/def ::project-id ::us/uuid)
(s/def ::user ::us/uuid) (s/def ::user ::us/uuid)
(def ^:private sql:generic-project-files (su/defsql sql:generic-project-files
"select pf.*, "select pf.*,
array_agg(pp.id) as pages array_agg(pp.id) as pages
from project_files as pf from project_files as pf
@ -31,21 +33,42 @@
left join project_pages as pp on (pf.id = pp.file_id) left join project_pages as pp on (pf.id = pp.file_id)
where pu.user_id = $1 where pu.user_id = $1
and pu.can_edit = true and pu.can_edit = true
group by pf.id group by pf.id")
order by pf.created_at asc")
;; --- Query: Project Files ;; --- Query: Project Files
(def ^:private sql:project-files (declare retrieve-recent-files)
(str "with files as (" sql:generic-project-files ")" (declare retrieve-project-files)
" select * from files where project_id = $2"))
(s/def ::project-files (s/def ::project-files
(s/keys :req-un [::user ::project-id])) (s/keys :req-un [::user]
:opt-un [::project-id]))
(sq/defquery ::project-files (sq/defquery ::project-files
[{:keys [user project-id] :as params}] [{:keys [project-id] :as params}]
(-> (db/query db/pool [sql:project-files user project-id]) (if (nil? project-id)
(retrieve-recent-files db/pool params)
(retrieve-project-files db/pool params)))
(def ^:private sql:project-files
(str "with files as (" sql:generic-project-files ")"
" select * from files where project_id = $2"
" order by created_at asc"))
(defn retrieve-project-files
[conn {:keys [user project-id]}]
(-> (db/query conn [sql:project-files user project-id])
(p/then' (partial mapv decode-row))))
(su/defsql sql:recent-files
"with files as (~{sql:generic-project-files})
select * from files
order by modified_at desc
limit $2")
(defn retrieve-recent-files
[conn {:keys [user]}]
(-> (db/query conn [sql:recent-files user 20])
(p/then' (partial mapv decode-row)))) (p/then' (partial mapv decode-row))))
;; --- Query: Project File (By ID) ;; --- Query: Project File (By ID)

View file

@ -10,6 +10,7 @@
[promesa.core :as p] [promesa.core :as p]
[uxbox.db :as db] [uxbox.db :as db]
[uxbox.services.queries :as sq] [uxbox.services.queries :as sq]
[uxbox.services.util :as su]
[uxbox.util.blob :as blob] [uxbox.util.blob :as blob]
[uxbox.util.spec :as us])) [uxbox.util.spec :as us]))
@ -24,33 +25,20 @@
;; --- Query: Projects ;; --- Query: Projects
;; (def ^:private projects-sql (su/defsql sql:projects
;; "select distinct on (p.id, p.created_at)
;; p.*,
;; array_agg(pg.id) over (
;; partition by p.id
;; order by pg.created_at
;; range between unbounded preceding and unbounded following
;; ) as pages
;; from projects as p
;; left join pages as pg
;; on (pg.project_id = p.id)
;; where p.user_id = $1
;; order by p.created_at asc")
(def ^:private projects-sql
"select p.* "select p.*
from project_users as pu from project_users as pu
inner join projects as p on (p.id = pu.project_id) inner join projects as p on (p.id = pu.project_id)
where pu.can_edit = true where pu.can_edit = true
and pu.user_id = $1;") and pu.user_id = $1
order by p.created_at asc")
(s/def ::projects (s/def ::projects
(s/keys :req-un [::user])) (s/keys :req-un [::user]))
(sq/defquery ::projects (sq/defquery ::projects
[{:keys [user] :as params}] [{:keys [user] :as params}]
(-> (db/query db/pool [projects-sql user]) (-> (db/query db/pool [sql:projects user])
(p/then' (partial mapv decode-row)))) (p/then' (partial mapv decode-row))))
;; --- Helpers ;; --- Helpers

View file

@ -7,6 +7,7 @@
(ns uxbox.services.util (ns uxbox.services.util
(:require (:require
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[cuerdas.core :as str]
[vertx.core :as vc] [vertx.core :as vc]
[uxbox.core :refer [system]] [uxbox.core :refer [system]]
[uxbox.util.uuid :as uuid] [uxbox.util.uuid :as uuid]
@ -24,6 +25,10 @@
;; (log/info "service" type "processed in" elapsed) ;; (log/info "service" type "processed in" elapsed)
;; data))}) ;; data))})
(defmacro defsql
[sym str]
`(def ~sym (str/istr ~str)))
(defn raise-not-found-if-nil (defn raise-not-found-if-nil
[v] [v]
(if (nil? v) (if (nil? v)

View file

@ -36,7 +36,7 @@
(watch [this state s] (watch [this state s]
(swap! storage assoc :auth data) (swap! storage assoc :auth data)
(rx/of du/fetch-profile (rx/of du/fetch-profile
(rt/navigate :dashboard/projects))))) (rt/navigate :dashboard-projects)))))
(defn logged-in? (defn logged-in?
[v] [v]

View file

@ -122,8 +122,9 @@
(ptk/reify ::fetch-files (ptk/reify ::fetch-files
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(->> (rp/query :project-files {:project-id project-id}) (let [params (if (nil? project-id) {} {:project-id project-id})]
(rx/map files-fetched))))) (->> (rp/query :project-files params)
(rx/map files-fetched))))))
;; --- Fetch File (by ID) ;; --- Fetch File (by ID)
@ -247,3 +248,13 @@
(let [path-params {:file-id file-id} (let [path-params {:file-id file-id}
query-params {:page-id (first page-ids)}] query-params {:page-id (first page-ids)}]
(rx/of (rt/nav :workspace path-params query-params))))))) (rx/of (rt/nav :workspace path-params query-params)))))))
(defn go-to-project
[id]
(s/assert (s/nilable ::us/uuid) id)
(ptk/reify ::go-to-project
ptk/WatchEvent
(watch [_ state stream]
(if (nil? id)
(rx/of (rt/nav :dashboard-projects {} {}))
(rx/of (rt/nav :dashboard-projects {} {:project-id (str id)}))))))

View file

@ -30,6 +30,7 @@
(def +ordering-options+ (def +ordering-options+
{:name "ds.ordering.by-name" {:name "ds.ordering.by-name"
:modified "ds.ordering.by-last-update"
:created "ds.ordering.by-creation-date"}) :created "ds.ordering.by-creation-date"})
;; --- Refs ;; --- Refs
@ -49,6 +50,7 @@
(case ordering (case ordering
:name (cljs.core/sort-by :name files) :name (cljs.core/sort-by :name files)
:created (reverse (cljs.core/sort-by :created-at files)) :created (reverse (cljs.core/sort-by :created-at files))
:modified (reverse (cljs.core/sort-by :modified-at files))
files)) files))
(defn contains-term? (defn contains-term?
@ -65,8 +67,8 @@
;; --- Menu (Filter & Sort) ;; --- Menu (Filter & Sort)
(mf/defc menu (mf/defc menu
[{:keys [opts files] :as props}] [{:keys [id opts files] :as props}]
(let [ordering (:order opts :created) (let [ordering (:order opts :modified)
filtering (:filter opts "") filtering (:filter opts "")
on-term-change on-term-change
@ -94,12 +96,14 @@
[:div [:div
;; Sorting ;; Sorting
;; TODO: convert to separate component? ;; TODO: convert to separate component?
[:span (tr "ds.ordering")] (when id
[:select.input-select {:on-change on-order-change [:*
:value (pr-str ordering)} [:span (tr "ds.ordering")]
(for [[key value] (seq +ordering-options+)] [:select.input-select {:on-change on-order-change
(let [key (pr-str key)] :value (pr-str ordering)}
[:option {:key key :value key} (tr value)]))]] (for [[key value] (seq +ordering-options+)]
(let [key (pr-str key)]
[:option {:key key :value key} (tr value)]))]])]
;; Search ;; Search
;; TODO: convert to separate component? ;; TODO: convert to separate component?
@ -174,7 +178,7 @@
(mf/defc grid (mf/defc grid
[{:keys [opts files] :as props}] [{:keys [opts files] :as props}]
(let [order (:order opts :created) (let [order (:order opts :modified)
filter (:filter opts "") filter (:filter opts "")
files (->> files files (->> files
(filter-by filter) (filter-by filter)
@ -217,8 +221,7 @@
[{:keys [id name selected?] :as props}] [{:keys [id name selected?] :as props}]
(let [local (mf/use-state {}) (let [local (mf/use-state {})
editable? (not (nil? id)) editable? (not (nil? id))
on-click (fn [event] on-click #(st/emit! (udp/go-to-project id))]
(st/emit! (rt/nav :dashboard-projects {} {:project-id (str id)})))]
[:li {:on-click on-click [:li {:on-click on-click
;; :on-double-click on-double-click ;; :on-double-click on-double-click
:class-name (when selected? "current")} :class-name (when selected? "current")}
@ -248,7 +251,7 @@
"new project +"]] "new project +"]]
[:li {:style {:marginBottom "20px"} [:li {:style {:marginBottom "20px"}
:on-click #(st/emit! (rt/nav :dashboard/projects {} {})) :on-click #(st/emit! (udp/go-to-project nil))
:class-name (when (nil? id) "current")} :class-name (when (nil? id) "current")}
[:span.element-title "Recent"]] [:span.element-title "Recent"]]
@ -273,7 +276,7 @@
(let [opts (mf/deref opts-iref) (let [opts (mf/deref opts-iref)
files (mf/deref files-ref)] files (mf/deref files-ref)]
[:* [:*
[:& menu {:opts opts :files files}] [:& menu {:id id :opts opts :files files}]
[:section.dashboard-grid.library [:section.dashboard-grid.library
[:& grid {:id id :opts opts :files files}]]])) [:& grid {:id id :opts opts :files files}]]]))