mirror of
https://github.com/penpot/penpot.git
synced 2025-06-02 01:51:37 +02:00
♻️ Refactor dashboard state management.
Mainly for performance, also affects backend endpoints.
This commit is contained in:
parent
e7b3f12b71
commit
c70bc5baff
23 changed files with 1110 additions and 1007 deletions
|
@ -12,6 +12,7 @@
|
|||
[app.db :as db]
|
||||
[app.rpc.permissions :as perms]
|
||||
[app.rpc.queries.projects :as projects]
|
||||
[app.rpc.queries.teams :as teams]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.services :as sv]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
@ -97,7 +98,13 @@
|
|||
ppr.is_owner = true or
|
||||
ppr.can_edit = true)
|
||||
)
|
||||
select distinct f.*
|
||||
select distinct
|
||||
f.id,
|
||||
f.project_id,
|
||||
f.created_at,
|
||||
f.modified_at,
|
||||
f.name,
|
||||
f.is_shared
|
||||
from file as f
|
||||
inner join projects as pr on (f.project_id = pr.id)
|
||||
where f.name ilike ('%' || ? || '%')
|
||||
|
@ -109,14 +116,14 @@
|
|||
|
||||
(sv/defmethod ::search-files
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id team-id search-term] :as params}]
|
||||
(let [rows (db/exec! pool [sql:search-files
|
||||
profile-id team-id
|
||||
profile-id team-id
|
||||
search-term])]
|
||||
(into [] decode-row-xf rows)))
|
||||
(db/exec! pool [sql:search-files
|
||||
profile-id team-id
|
||||
profile-id team-id
|
||||
search-term]))
|
||||
|
||||
;; --- Query: Files
|
||||
|
||||
;; --- Query: Project Files
|
||||
;; DEPRECATED: should be removed probably on 1.6.x
|
||||
|
||||
(def ^:private sql:files
|
||||
"select f.*
|
||||
|
@ -136,6 +143,29 @@
|
|||
(into [] decode-row-xf (db/exec! conn [sql:files project-id]))))
|
||||
|
||||
|
||||
;; --- Query: Project Files
|
||||
|
||||
(def ^:private sql:project-files
|
||||
"select f.id,
|
||||
f.project_id,
|
||||
f.created_at,
|
||||
f.modified_at,
|
||||
f.name,
|
||||
f.is_shared
|
||||
from file as f
|
||||
where f.project_id = ?
|
||||
and f.deleted_at is null
|
||||
order by f.modified_at desc")
|
||||
|
||||
(s/def ::project-files
|
||||
(s/keys :req-un [::profile-id ::project-id]))
|
||||
|
||||
(sv/defmethod ::project-files
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id project-id] :as params}]
|
||||
(with-open [conn (db/open pool)]
|
||||
(projects/check-read-permissions! conn profile-id project-id)
|
||||
(db/exec! conn [sql:project-files project-id])))
|
||||
|
||||
;; --- Query: File (By ID)
|
||||
|
||||
(defn retrieve-file
|
||||
|
@ -154,17 +184,20 @@
|
|||
(retrieve-file conn id)))
|
||||
|
||||
(s/def ::page
|
||||
(s/keys :req-un [::profile-id ::id ::file-id]))
|
||||
(s/keys :req-un [::profile-id ::file-id]))
|
||||
|
||||
(sv/defmethod ::page
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id id]}]
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id]}]
|
||||
(db/with-atomic [conn pool]
|
||||
(check-edition-permissions! conn profile-id file-id)
|
||||
(let [file (retrieve-file conn file-id)]
|
||||
(get-in file [:data :pages-index id]))))
|
||||
(let [file (retrieve-file conn file-id)
|
||||
page-id (get-in file [:data :pages 0])]
|
||||
(get-in file [:data :pages-index page-id]))))
|
||||
|
||||
;; --- Query: Shared Library Files
|
||||
|
||||
;; DEPRECATED: and will be removed on 1.6.x
|
||||
|
||||
(def ^:private sql:shared-files
|
||||
"select f.*
|
||||
from file as f
|
||||
|
@ -183,11 +216,35 @@
|
|||
(into [] decode-row-xf (db/exec! pool [sql:shared-files team-id])))
|
||||
|
||||
|
||||
;; --- Query: Shared Library Files
|
||||
|
||||
(def ^:private sql:team-shared-files
|
||||
"select f.id,
|
||||
f.project_id,
|
||||
f.created_at,
|
||||
f.modified_at,
|
||||
f.name,
|
||||
f.is_shared
|
||||
from file as f
|
||||
inner join project as p on (p.id = f.project_id)
|
||||
where f.is_shared = true
|
||||
and f.deleted_at is null
|
||||
and p.deleted_at is null
|
||||
and p.team_id = ?
|
||||
order by f.modified_at desc")
|
||||
|
||||
(s/def ::team-shared-files
|
||||
(s/keys :req-un [::profile-id ::team-id]))
|
||||
|
||||
(sv/defmethod ::team-shared-files
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id team-id] :as params}]
|
||||
(db/exec! pool [sql:team-shared-files team-id]))
|
||||
|
||||
|
||||
;; --- Query: File Libraries used by a File
|
||||
|
||||
(def ^:private sql:file-libraries
|
||||
"select fl.*,
|
||||
? as is_indirect,
|
||||
flr.synced_at as synced_at
|
||||
from file as fl
|
||||
inner join file_library_rel as flr on (flr.library_file_id = fl.id)
|
||||
|
@ -196,22 +253,12 @@
|
|||
|
||||
(defn retrieve-file-libraries
|
||||
[conn is-indirect file-id]
|
||||
(let [direct-libraries
|
||||
(into [] decode-row-xf (db/exec! conn [sql:file-libraries is-indirect file-id]))
|
||||
|
||||
select-distinct
|
||||
(fn [used-libraries new-libraries]
|
||||
(remove (fn [new-library]
|
||||
(some #(= (:id %) (:id new-library)) used-libraries))
|
||||
new-libraries))]
|
||||
|
||||
(reduce (fn [used-libraries library]
|
||||
(concat used-libraries
|
||||
(select-distinct
|
||||
used-libraries
|
||||
(retrieve-file-libraries conn true (:id library)))))
|
||||
direct-libraries
|
||||
direct-libraries)))
|
||||
(let [libraries (->> (db/exec! conn [sql:file-libraries file-id])
|
||||
(map #(assoc :is-indirect is-indirect))
|
||||
(into #{} decode-row-xf))]
|
||||
(reduce #(into %1 (retrieve-file-libraries conn true %2))
|
||||
libraries
|
||||
(map :id libraries))))
|
||||
|
||||
(s/def ::file-libraries
|
||||
(s/keys :req-un [::profile-id ::file-id]))
|
||||
|
@ -222,31 +269,35 @@
|
|||
(check-edition-permissions! conn profile-id file-id)
|
||||
(retrieve-file-libraries conn false file-id)))
|
||||
|
||||
;; --- QUERY: team-recent-files
|
||||
|
||||
;; --- Query: Single File Library
|
||||
(def sql:team-recent-files
|
||||
"with recent_files as (
|
||||
select f.id,
|
||||
f.project_id,
|
||||
f.created_at,
|
||||
f.modified_at,
|
||||
f.name,
|
||||
f.is_shared,
|
||||
row_number() over w as row_num
|
||||
from file as f
|
||||
join project as p on (p.id = f.project_id)
|
||||
where p.team_id = ?
|
||||
and p.deleted_at is null
|
||||
and f.deleted_at is null
|
||||
window w as (partition by f.project_id order by f.modified_at desc)
|
||||
order by f.modified_at desc
|
||||
)
|
||||
select * from recent_files where row_num <= 10;")
|
||||
|
||||
;; TODO: this looks like is duplicate of `::file`
|
||||
(s/def ::team-recent-files
|
||||
(s/keys :req-un [::profile-id ::team-id]))
|
||||
|
||||
(def ^:private sql:file-library
|
||||
"select fl.*
|
||||
from file as fl
|
||||
where fl.id = ?")
|
||||
|
||||
(defn retrieve-file-library
|
||||
[conn file-id]
|
||||
(let [rows (db/exec! conn [sql:file-library file-id])]
|
||||
(when-not (seq rows)
|
||||
(ex/raise :type :not-found))
|
||||
(first (sequence decode-row-xf rows))))
|
||||
|
||||
(s/def ::file-library
|
||||
(s/keys :req-un [::profile-id ::file-id]))
|
||||
|
||||
(sv/defmethod ::file-library
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(check-edition-permissions! conn profile-id file-id) ;; TODO: this should check read permissions
|
||||
(retrieve-file-library conn file-id)))
|
||||
(sv/defmethod ::team-recent-files
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id team-id]}]
|
||||
(with-open [conn (db/open pool)]
|
||||
(teams/check-read-permissions! conn profile-id team-id)
|
||||
(db/exec! conn [sql:team-recent-files team-id])))
|
||||
|
||||
|
||||
;; --- Helpers
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
[app.util.services :as sv]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; DEPRECATED: should be removed on 1.6.x
|
||||
|
||||
(def sql:recent-files
|
||||
"with recent_files as (
|
||||
select f.*, row_number() over w as row_num
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
(t/is (= (:id data) (:id result)))
|
||||
(t/is (= (:name data) (:name result))))))
|
||||
|
||||
(t/testing "query files"
|
||||
(t/testing "query files (deprecated)"
|
||||
(let [data {::th/type :files
|
||||
:project-id proj-id
|
||||
:profile-id (:id prof)}
|
||||
|
@ -67,6 +67,20 @@
|
|||
(t/is (= "new name" (get-in result [0 :name])))
|
||||
(t/is (= 1 (count (get-in result [0 :data :pages])))))))
|
||||
|
||||
(t/testing "query files"
|
||||
(let [data {::th/type :project-files
|
||||
:project-id proj-id
|
||||
:profile-id (:id prof)}
|
||||
out (th/query! data)]
|
||||
|
||||
;; (th/print-result! out)
|
||||
(t/is (nil? (:error out)))
|
||||
|
||||
(let [result (:result out)]
|
||||
(t/is (= 1 (count result)))
|
||||
(t/is (= file-id (get-in result [0 :id])))
|
||||
(t/is (= "new name" (get-in result [0 :name]))))))
|
||||
|
||||
(t/testing "query single file without users"
|
||||
(let [data {::th/type :file
|
||||
:profile-id (:id prof)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue