mirror of
https://github.com/penpot/penpot.git
synced 2025-07-31 06:38:24 +02:00
🎉 Integrate storage/pointer-map file feature
This commit is contained in:
parent
a42d7164ad
commit
76333cec26
45 changed files with 2100 additions and 1408 deletions
|
@ -110,7 +110,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)]
|
||||
(->> (rp/query :team-members {:team-id team-id})
|
||||
(->> (rp/query! :team-members {:team-id team-id})
|
||||
(rx/map team-members-fetched))))))
|
||||
|
||||
;; --- EVENT: fetch-team-stats
|
||||
|
@ -128,7 +128,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)]
|
||||
(->> (rp/query :team-stats {:team-id team-id})
|
||||
(->> (rp/query! :team-stats {:team-id team-id})
|
||||
(rx/map team-stats-fetched))))))
|
||||
|
||||
;; --- EVENT: fetch-team-invitations
|
||||
|
@ -146,7 +146,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)]
|
||||
(->> (rp/query :team-invitations {:team-id team-id})
|
||||
(->> (rp/query! :team-invitations {:team-id team-id})
|
||||
(rx/map team-invitations-fetched))))))
|
||||
|
||||
;; --- EVENT: fetch-projects
|
||||
|
@ -165,7 +165,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)]
|
||||
(->> (rp/query :projects {:team-id team-id})
|
||||
(->> (rp/query! :projects {:team-id team-id})
|
||||
(rx/map projects-fetched))))))
|
||||
|
||||
;; --- EVENT: search
|
||||
|
@ -193,7 +193,7 @@
|
|||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)
|
||||
params (assoc params :team-id team-id)]
|
||||
(->> (rp/query :search-files params)
|
||||
(->> (rp/query! :search-files params)
|
||||
(rx/map search-result-fetched))))))
|
||||
|
||||
;; --- EVENT: files
|
||||
|
@ -222,7 +222,7 @@
|
|||
(ptk/reify ::fetch-files
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :project-files {:project-id project-id})
|
||||
(->> (rp/cmd! :get-project-files {:project-id project-id})
|
||||
(rx/map #(files-fetched project-id %))))))
|
||||
|
||||
;; --- EVENT: shared-files
|
||||
|
@ -243,7 +243,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)]
|
||||
(->> (rp/query :team-shared-files {:team-id team-id})
|
||||
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
||||
(rx/map shared-files-fetched))))))
|
||||
|
||||
;; --- EVENT: Get files that use this shared-file
|
||||
|
@ -269,7 +269,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rx/from files)
|
||||
(rx/mapcat (fn [file] (rp/query :library-using-files {:file-id (:id file)})))
|
||||
(rx/map :id)
|
||||
(rx/mapcat #(rp/cmd! :get-library-file-references {:file-id %}))
|
||||
(rx/reduce into [])
|
||||
(rx/map library-using-files-fetched)))))
|
||||
|
||||
|
@ -292,7 +293,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (or team-id (:current-team-id state))]
|
||||
(->> (rp/query :team-recent-files {:team-id team-id})
|
||||
(->> (rp/cmd! :get-team-recent-files {:team-id team-id})
|
||||
(rx/map recent-files-fetched)))))))
|
||||
|
||||
|
||||
|
@ -588,7 +589,7 @@
|
|||
|
||||
new-name (str name " " (tr "dashboard.copy-suffix"))]
|
||||
|
||||
(->> (rp/command! :duplicate-project {:project-id id :name new-name})
|
||||
(->> (rp/cmd! :duplicate-project {:project-id id :name new-name})
|
||||
(rx/tap on-success)
|
||||
(rx/map project-duplicated)
|
||||
(rx/catch on-error))))))
|
||||
|
@ -608,7 +609,7 @@
|
|||
:or {on-success identity
|
||||
on-error rx/throw}} (meta params)]
|
||||
|
||||
(->> (rp/command! :move-project {:project-id id :team-id team-id})
|
||||
(->> (rp/cmd! :move-project {:project-id id :team-id team-id})
|
||||
(rx/tap on-success)
|
||||
(rx/catch on-error))))))
|
||||
|
||||
|
@ -683,7 +684,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (uuid/uuid (get-in state [:route :path-params :team-id]))]
|
||||
(->> (rp/mutation :delete-file {:id id})
|
||||
(->> (rp/cmd! :delete-file {:id id})
|
||||
(rx/map #(file-deleted team-id project-id)))))))
|
||||
|
||||
;; --- Rename File
|
||||
|
@ -706,7 +707,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [params (select-keys params [:id :name])]
|
||||
(->> (rp/mutation :rename-file params)
|
||||
(->> (rp/cmd! :rename-file params)
|
||||
(rx/ignore))))))
|
||||
|
||||
;; --- Set File shared
|
||||
|
@ -731,7 +732,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [params {:id id :is-shared is-shared}]
|
||||
(->> (rp/mutation :set-file-shared params)
|
||||
(->> (rp/cmd! :set-file-shared params)
|
||||
(rx/ignore))))))
|
||||
|
||||
;; --- EVENT: create-file
|
||||
|
@ -774,7 +775,7 @@
|
|||
(assoc :name name)
|
||||
(assoc :features features))]
|
||||
|
||||
(->> (rp/mutation! :create-file params)
|
||||
(->> (rp/cmd! :create-file params)
|
||||
(rx/tap on-success)
|
||||
(rx/map #(with-meta (file-created %) (meta it)))
|
||||
(rx/catch on-error))))))
|
||||
|
@ -794,7 +795,7 @@
|
|||
|
||||
new-name (str name " " (tr "dashboard.copy-suffix"))]
|
||||
|
||||
(->> (rp/command! :duplicate-file {:file-id id :name new-name})
|
||||
(->> (rp/cmd! :duplicate-file {:file-id id :name new-name})
|
||||
(rx/tap on-success)
|
||||
(rx/map file-created)
|
||||
(rx/catch on-error))))))
|
||||
|
@ -816,7 +817,7 @@
|
|||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity
|
||||
on-error rx/throw}} (meta params)]
|
||||
(->> (rp/command! :move-files {:ids ids :project-id project-id})
|
||||
(->> (rp/cmd! :move-files {:ids ids :project-id project-id})
|
||||
(rx/tap on-success)
|
||||
(rx/catch on-error))))))
|
||||
|
||||
|
@ -836,8 +837,7 @@
|
|||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity
|
||||
on-error rx/throw}} (meta params)]
|
||||
|
||||
(->> (rp/command! :clone-template {:project-id project-id :template-id template-id})
|
||||
(->> (rp/cmd! :clone-template {:project-id project-id :template-id template-id})
|
||||
(rx/tap on-success)
|
||||
(rx/catch on-error))))))
|
||||
|
||||
|
|
|
@ -357,7 +357,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [params {:id id :name name}]
|
||||
(->> (rp/mutation :rename-file params)
|
||||
(->> (rp/cmd! :rename-file params)
|
||||
(rx/ignore))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.data.workspace.libraries
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.files.features :as ffeat]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.logging :as log]
|
||||
[app.common.pages :as cp]
|
||||
|
@ -19,7 +20,7 @@
|
|||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.file.media-object :as ctfm]
|
||||
[app.common.types.file.media-object :as ctfm]
|
||||
[app.common.types.pages-list :as ctpl]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.typography :as ctt]
|
||||
|
@ -359,7 +360,7 @@
|
|||
(pcb/with-library-data data)
|
||||
(pcb/update-component id update-fn))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(defn duplicate-component
|
||||
"Create a new component copied from the one with the given id."
|
||||
|
@ -428,7 +429,7 @@
|
|||
component (ctf/get-deleted-component file-data component-id)
|
||||
page (ctpl/get-page file-data (:main-instance-page component))
|
||||
|
||||
; Make a new main instance, with the same id of the original
|
||||
; Make a new main instance, with the same id of the original
|
||||
[_main-instance shapes]
|
||||
(ctn/make-component-instance page
|
||||
component
|
||||
|
@ -446,8 +447,8 @@
|
|||
changes
|
||||
shapes)
|
||||
|
||||
; restore-component change needs to be done after add main instance
|
||||
; because when undo changes, the orden is inverse
|
||||
; restore-component change needs to be done after add main instance
|
||||
; because when undo changes, the orden is inverse
|
||||
changes (pcb/restore-component changes component-id)]
|
||||
|
||||
(rx/of (dch/commit-changes (assoc changes :file-id library-id)))))))
|
||||
|
@ -508,12 +509,12 @@
|
|||
(cph/clean-loops objects))
|
||||
|
||||
changes (reduce
|
||||
(fn [changes id]
|
||||
(dwlh/generate-detach-instance changes container id))
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-container container)
|
||||
(pcb/with-objects objects))
|
||||
selected)]
|
||||
(fn [changes id]
|
||||
(dwlh/generate-detach-instance changes container id))
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-container container)
|
||||
(pcb/with-objects objects))
|
||||
selected)]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
|
@ -572,8 +573,8 @@
|
|||
|
||||
(log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
file))
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(defn update-component
|
||||
"Modify the component linked to the shape with the given id, in the
|
||||
|
@ -624,11 +625,11 @@
|
|||
|
||||
(log/debug :msg "UPDATE-COMPONENT finished"
|
||||
:js/local-changes (log-changes
|
||||
(:redo-changes local-changes)
|
||||
file)
|
||||
(:redo-changes local-changes)
|
||||
file)
|
||||
:js/nonlocal-changes (log-changes
|
||||
(:redo-changes nonlocal-changes)
|
||||
file))
|
||||
(:redo-changes nonlocal-changes)
|
||||
file))
|
||||
|
||||
(rx/of
|
||||
(when (seq (:redo-changes local-changes))
|
||||
|
@ -705,48 +706,48 @@
|
|||
sync-typographies? (or (nil? asset-type) (= asset-type :typographies))
|
||||
|
||||
library-changes (reduce
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(when sync-components?
|
||||
(dwlh/generate-sync-library it file-id :components asset-id library-id state))
|
||||
(when sync-colors?
|
||||
(dwlh/generate-sync-library it file-id :colors asset-id library-id state))
|
||||
(when sync-typographies?
|
||||
(dwlh/generate-sync-library it file-id :typographies asset-id library-id state))])
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(when sync-components?
|
||||
(dwlh/generate-sync-library it file-id :components asset-id library-id state))
|
||||
(when sync-colors?
|
||||
(dwlh/generate-sync-library it file-id :colors asset-id library-id state))
|
||||
(when sync-typographies?
|
||||
(dwlh/generate-sync-library it file-id :typographies asset-id library-id state))])
|
||||
file-changes (reduce
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(when sync-components?
|
||||
(dwlh/generate-sync-file it file-id :components asset-id library-id state))
|
||||
(when sync-colors?
|
||||
(dwlh/generate-sync-file it file-id :colors asset-id library-id state))
|
||||
(when sync-typographies?
|
||||
(dwlh/generate-sync-file it file-id :typographies asset-id library-id state))])
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(when sync-components?
|
||||
(dwlh/generate-sync-file it file-id :components asset-id library-id state))
|
||||
(when sync-colors?
|
||||
(dwlh/generate-sync-file it file-id :colors asset-id library-id state))
|
||||
(when sync-typographies?
|
||||
(dwlh/generate-sync-file it file-id :typographies asset-id library-id state))])
|
||||
|
||||
changes (pcb/concat-changes library-changes file-changes)]
|
||||
|
||||
(log/debug :msg "SYNC-FILE finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
(rx/concat
|
||||
(rx/of (dm/hide-tag :sync-dialog))
|
||||
(when (seq (:redo-changes changes))
|
||||
(rx/of (dch/commit-changes (assoc changes ;; TODO a ver qué pasa con esto
|
||||
:file-id file-id))))
|
||||
(when (not= file-id library-id)
|
||||
;; When we have just updated the library file, give some time for the
|
||||
;; update to finish, before marking this file as synced.
|
||||
;; TODO: look for a more precise way of syncing this.
|
||||
;; Maybe by using the stream (second argument passed to watch)
|
||||
;; to wait for the corresponding changes-committed and then proceed
|
||||
;; with the :update-sync mutation.
|
||||
(rx/concat (rx/timer 3000)
|
||||
(rp/mutation :update-sync
|
||||
{:file-id file-id
|
||||
:library-id library-id})))
|
||||
(when (and (seq (:redo-changes library-changes))
|
||||
sync-components?)
|
||||
(rx/of (sync-file-2nd-stage file-id library-id asset-id))))))))))
|
||||
(rx/of (dm/hide-tag :sync-dialog))
|
||||
(when (seq (:redo-changes changes))
|
||||
(rx/of (dch/commit-changes (assoc changes ;; TODO a ver qué pasa con esto
|
||||
:file-id file-id))))
|
||||
(when (not= file-id library-id)
|
||||
;; When we have just updated the library file, give some time for the
|
||||
;; update to finish, before marking this file as synced.
|
||||
;; TODO: look for a more precise way of syncing this.
|
||||
;; Maybe by using the stream (second argument passed to watch)
|
||||
;; to wait for the corresponding changes-committed and then proceed
|
||||
;; with the :update-file-library-sync-status mutation.
|
||||
(rx/concat (rx/timer 3000)
|
||||
(rp/cmd! :update-file-library-sync-status
|
||||
{:file-id file-id
|
||||
:library-id library-id})))
|
||||
(when (and (seq (:redo-changes library-changes))
|
||||
sync-components?)
|
||||
(rx/of (sync-file-2nd-stage file-id library-id asset-id))))))))))
|
||||
|
||||
(defn- sync-file-2nd-stage
|
||||
"If some components have been modified, we need to launch another synchronization
|
||||
|
@ -775,8 +776,8 @@
|
|||
(dwlh/generate-sync-library it file-id :components asset-id library-id state)])]
|
||||
|
||||
(log/debug :msg "SYNC-FILE (2nd stage) finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
(when (seq (:redo-changes changes))
|
||||
(rx/of (dch/commit-changes (assoc changes :file-id file-id))))))))
|
||||
|
||||
|
@ -788,9 +789,9 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(rp/mutation :ignore-sync
|
||||
{:file-id (get-in state [:workspace-file :id])
|
||||
:date (dt/now)}))))
|
||||
(rp/cmd! :ignore-file-library-sync-status
|
||||
{:file-id (get-in state [:workspace-file :id])
|
||||
:date (dt/now)}))))
|
||||
|
||||
(defn notify-sync-file
|
||||
[file-id]
|
||||
|
@ -852,8 +853,8 @@
|
|||
(log/info :msg "DETECTED COMPONENTS CHANGED"
|
||||
:ids (map str components-changed))
|
||||
(run! st/emit!
|
||||
(map #(update-component-sync % (:id data))
|
||||
components-changed)))))]
|
||||
(map #(update-component-sync % (:id data))
|
||||
components-changed)))))]
|
||||
|
||||
(when components-v2
|
||||
(->> change-s
|
||||
|
@ -880,7 +881,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [params {:id id :is-shared is-shared}]
|
||||
(->> (rp/mutation :set-file-shared params)
|
||||
(->> (rp/cmd! :set-file-shared params)
|
||||
(rx/ignore))))))
|
||||
|
||||
(defn- shared-files-fetched
|
||||
|
@ -898,7 +899,7 @@
|
|||
(ptk/reify ::fetch-shared-files
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :team-shared-files {:team-id team-id})
|
||||
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
||||
(rx/map shared-files-fetched)))))
|
||||
|
||||
;; --- Link and unlink Files
|
||||
|
@ -908,13 +909,16 @@
|
|||
(ptk/reify ::attach-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
fetched #(assoc-in %2 [:workspace-libraries (:id %1)] %1)
|
||||
params {:file-id file-id
|
||||
:library-id library-id}]
|
||||
(->> (rp/mutation :link-file-to-library params)
|
||||
(rx/mapcat #(rp/query :file {:id library-id :components-v2 components-v2}))
|
||||
(rx/map #(partial fetched %)))))))
|
||||
(let [features (cond-> ffeat/enabled
|
||||
(features/active-feature? state :components-v2)
|
||||
(conj "components/v2"))]
|
||||
(rx/concat
|
||||
(->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
|
||||
(rx/ignore))
|
||||
(->> (rp/cmd! :get-file {:id library-id :features features})
|
||||
(rx/map (fn [file]
|
||||
(fn [state]
|
||||
(assoc-in state [:workspace-libraries library-id] file))))))))))
|
||||
|
||||
(defn unlink-file-from-library
|
||||
[file-id library-id]
|
||||
|
@ -927,5 +931,5 @@
|
|||
(watch [_ _ _]
|
||||
(let [params {:file-id file-id
|
||||
:library-id library-id}]
|
||||
(->> (rp/mutation :unlink-file-from-library params)
|
||||
(->> (rp/cmd! :unlink-file-from-library params)
|
||||
(rx/ignore))))))
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.features :as ffeat]
|
||||
[app.common.logging :as log]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.changes-spec :as pcs]
|
||||
|
@ -18,7 +19,6 @@
|
|||
[app.config :as cf]
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.thumbnails :as dwt]
|
||||
|
@ -26,7 +26,6 @@
|
|||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.router :as rt]
|
||||
[app.util.time :as dt]
|
||||
[beicon.core :as rx]
|
||||
|
@ -138,7 +137,11 @@
|
|||
(ptk/reify ::persist-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [features (cond-> #{}
|
||||
(let [;; this features set does not includes the ffeat/enabled
|
||||
;; because they are already available on the backend and
|
||||
;; this request provides a set of features to enable in
|
||||
;; this request.
|
||||
features (cond-> #{}
|
||||
(features/active-feature? state :components-v2)
|
||||
(conj "components/v2"))
|
||||
sid (:session-id state)
|
||||
|
@ -150,7 +153,7 @@
|
|||
:features features}]
|
||||
|
||||
(when (= file-id (:id params))
|
||||
(->> (rp/mutation :update-file params)
|
||||
(->> (rp/cmd! :update-file params)
|
||||
(rx/mapcat (fn [lagged]
|
||||
(log/debug :hint "changes persisted" :lagged (count lagged))
|
||||
(let [lagged (cond->> lagged
|
||||
|
@ -285,14 +288,13 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)
|
||||
features (cond-> #{}
|
||||
features (cond-> ffeat/enabled
|
||||
(features/active-feature? state :components-v2)
|
||||
(conj "components/v2"))]
|
||||
|
||||
(->> (rx/zip (rp/query! :file-raw {:id file-id :features features})
|
||||
(->> (rx/zip (rp/cmd! :get-raw-file {:id file-id :features features})
|
||||
(rp/query! :team-users {:file-id file-id})
|
||||
(rp/query! :project {:id project-id})
|
||||
(rp/query! :file-libraries {:file-id file-id})
|
||||
(rp/cmd! :get-file-libraries {:file-id file-id})
|
||||
(rp/cmd! :get-profiles-for-file-comments {:file-id file-id :share-id share-id}))
|
||||
(rx/take 1)
|
||||
(rx/map (fn [[file-raw users project libraries file-comments-users]]
|
||||
|
@ -303,16 +305,7 @@
|
|||
:file-comments-users file-comments-users}))
|
||||
(rx/mapcat (fn [{:keys [project] :as bundle}]
|
||||
(rx/of (ptk/data-event ::bundle-fetched bundle)
|
||||
(df/load-team-fonts (:team-id project)))))
|
||||
(rx/catch (fn [err]
|
||||
(if (and (= (:type err) :restriction)
|
||||
(= (:code err) :feature-disabled))
|
||||
(let [team-id (:current-team-id state)]
|
||||
(rx/of (modal/show
|
||||
{:type :alert
|
||||
:message (tr "errors.components-v2")
|
||||
:on-accept #(st/emit! (rt/nav :dashboard-projects {:team-id team-id}))})))
|
||||
(rx/throw err)))))))))
|
||||
(df/load-team-fonts (:team-id project))))))))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
(rx/merge
|
||||
;; Update the local copy of the thumbnails so we don't need to request it again
|
||||
(rx/of #(assoc-in % [:workspace-file :thumbnails object-id] data))
|
||||
(->> (rp/mutation! :upsert-file-object-thumbnail params)
|
||||
(->> (rp/cmd! :upsert-file-object-thumbnail params)
|
||||
(rx/ignore))))
|
||||
|
||||
(rx/empty))))))))))
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.common.spec :as us]
|
||||
[app.config :as cf]
|
||||
[app.main.data.messages :as msg]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.users :as du]
|
||||
[app.main.store :as st]
|
||||
[app.util.globals :as glob]
|
||||
|
@ -167,6 +168,26 @@
|
|||
(ts/schedule
|
||||
#(st/emit! (rt/assign-exception error))))
|
||||
|
||||
(defmethod ptk/handle-error :restriction
|
||||
[{:keys [code] :as error}]
|
||||
(cond
|
||||
(= :feature-mismatch code)
|
||||
(let [message (tr "errors.feature-mismatch" (:feature error))]
|
||||
(st/emit! (modal/show
|
||||
{:type :alert
|
||||
:message message
|
||||
:on-accept #(prn "kaka")})))
|
||||
|
||||
(= :features-not-supported code)
|
||||
(let [message (tr "errors.feature-not-supported" (:feature error))]
|
||||
(st/emit! (modal/show
|
||||
{:type :alert
|
||||
:message message
|
||||
:on-accept #(prn "kaka")})))
|
||||
|
||||
:else
|
||||
(ptk/handle-error (assoc error :type :server-error))))
|
||||
|
||||
;; This happens when the backed server fails to process the
|
||||
;; request. This can be caused by an internal assertion or any other
|
||||
;; uncontrolled error.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
(log/set-level! :debug)
|
||||
|
||||
(def features-list #{:auto-layout :components-v2})
|
||||
(def available-features #{:auto-layout :components-v2})
|
||||
|
||||
(defn- toggle-feature
|
||||
[feature]
|
||||
|
@ -38,14 +38,14 @@
|
|||
|
||||
(defn toggle-feature!
|
||||
[feature]
|
||||
(assert (contains? features-list feature) "Not supported feature")
|
||||
(assert (contains? available-features feature) "Not supported feature")
|
||||
(st/emit! (toggle-feature feature)))
|
||||
|
||||
(defn active-feature?
|
||||
([feature]
|
||||
(active-feature? @st/state feature))
|
||||
([state feature]
|
||||
(assert (contains? features-list feature) "Not supported feature")
|
||||
(assert (contains? available-features feature) "Not supported feature")
|
||||
(contains? (get state :features) feature)))
|
||||
|
||||
(def features
|
||||
|
@ -57,7 +57,7 @@
|
|||
|
||||
(defn use-feature
|
||||
[feature]
|
||||
(assert (contains? features-list feature) "Not supported feature")
|
||||
(assert (contains? available-features feature) "Not supported feature")
|
||||
(let [active-feature-ref (mf/use-memo (mf/deps feature) #(active-feature feature))
|
||||
active-feature? (mf/deref active-feature-ref)]
|
||||
active-feature?))
|
||||
|
@ -69,6 +69,6 @@
|
|||
(when *assert*
|
||||
;; By default, all features disabled, except in development
|
||||
;; environment, that are enabled except components-v2
|
||||
(doseq [f features-list]
|
||||
(doseq [f available-features]
|
||||
(when (not= f :components-v2)
|
||||
(toggle-feature! f)))))
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
[app.util.http :as http]
|
||||
[beicon.core :as rx]))
|
||||
|
||||
(derive :get-file ::query)
|
||||
|
||||
(defn handle-response
|
||||
[{:keys [status body] :as response}]
|
||||
(cond
|
||||
|
@ -48,7 +50,6 @@
|
|||
query api."
|
||||
([id params]
|
||||
(send-query! id params nil))
|
||||
|
||||
([id params {:keys [raw-transit?]}]
|
||||
(let [decode-transit (if raw-transit?
|
||||
http/conditional-error-decode-transit
|
||||
|
@ -74,14 +75,24 @@
|
|||
(defn- send-command!
|
||||
"A simple helper for a common case of sending and receiving transit
|
||||
data to the penpot mutation api."
|
||||
[id params {:keys [response-type form-data?]}]
|
||||
(->> (http/send! {:method :post
|
||||
:uri (u/join @cf/public-uri "api/rpc/command/" (name id))
|
||||
:credentials "include"
|
||||
:body (if form-data? (http/form-data params) (http/transit-data params))
|
||||
:response-type (or response-type :text)})
|
||||
(rx/map http/conditional-decode-transit)
|
||||
(rx/mapcat handle-response)))
|
||||
[id params {:keys [response-type form-data? raw-transit?]}]
|
||||
(let [decode-fn (if raw-transit?
|
||||
http/conditional-error-decode-transit
|
||||
http/conditional-decode-transit)
|
||||
method (if (isa? id ::query) :get :post)]
|
||||
|
||||
(->> (http/send! {:method method
|
||||
:uri (u/join @cf/public-uri "api/rpc/command/" (name id))
|
||||
:credentials "include"
|
||||
:body (when (= method :post)
|
||||
(if form-data?
|
||||
(http/form-data params)
|
||||
(http/transit-data params)))
|
||||
:query (when (= method :get)
|
||||
params)
|
||||
:response-type (or response-type :text)})
|
||||
(rx/map decode-fn)
|
||||
(rx/mapcat handle-response))))
|
||||
|
||||
(defn- dispatch [& args] (first args))
|
||||
|
||||
|
@ -93,9 +104,9 @@
|
|||
[id params]
|
||||
(send-query! id params))
|
||||
|
||||
(defmethod query :file-raw
|
||||
(defmethod command :get-raw-file
|
||||
[_id params]
|
||||
(send-query! :file params {:raw-transit? true}))
|
||||
(send-command! :get-file params {:raw-transit? true}))
|
||||
|
||||
(defmethod mutation :default
|
||||
[id params]
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.dashboard.grid
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.features :as ffeat]
|
||||
[app.common.logging :as log]
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.messages :as msg]
|
||||
|
@ -34,18 +35,21 @@
|
|||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(log/set-level! :info)
|
||||
(log/set-level! :debug)
|
||||
|
||||
;; --- Grid Item Thumbnail
|
||||
|
||||
(defn ask-for-thumbnail
|
||||
"Creates some hooks to handle the files thumbnails cache"
|
||||
[file]
|
||||
(wrk/ask! {:cmd :thumbnails/generate
|
||||
:revn (:revn file)
|
||||
:file-id (:id file)
|
||||
:file-name (:name file)
|
||||
:components-v2 (features/active-feature? :components-v2)}))
|
||||
(let [features (cond-> ffeat/enabled
|
||||
(features/active-feature? :components-v2)
|
||||
(conj "components/v2"))]
|
||||
(wrk/ask! {:cmd :thumbnails/generate
|
||||
:revn (:revn file)
|
||||
:file-id (:id file)
|
||||
:file-name (:name file)
|
||||
:features features})))
|
||||
|
||||
(mf/defc grid-item-thumbnail
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
@ -61,10 +65,10 @@
|
|||
(rx/subscribe-on :af)
|
||||
(rx/subs (fn [{:keys [data fonts] :as params}]
|
||||
(run! fonts/ensure-loaded! fonts)
|
||||
(log/info :hint "loaded thumbnail"
|
||||
:file-id (dm/str (:id file))
|
||||
:file-name (:name file)
|
||||
:elapsed (str/ffmt "%ms" (tp)))
|
||||
(log/debug :hint "loaded thumbnail"
|
||||
:file-id (dm/str (:id file))
|
||||
:file-name (:name file)
|
||||
:elapsed (str/ffmt "%ms" (tp)))
|
||||
(when-let [node (mf/ref-val container)]
|
||||
(dom/set-html! node data))))))))
|
||||
|
||||
|
|
|
@ -98,22 +98,23 @@
|
|||
[{:keys [page-id file-id object-id render-embed?]}]
|
||||
(let [components-v2 (features/use-feature :components-v2)
|
||||
fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id object-id)
|
||||
(mf/deps file-id page-id object-id components-v2)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:object-id object-id
|
||||
:components-v2 components-v2}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second))
|
||||
(rx/map (fn [objects]
|
||||
(let [objects (render/adapt-objects-for-shape objects object-id)]
|
||||
{:objects objects
|
||||
:object (get objects object-id)}))))))
|
||||
(let [features (cond-> #{} components-v2 (conj "components/v2"))]
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/cmd! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:object-id object-id
|
||||
:features features}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second))
|
||||
(rx/map (fn [objects]
|
||||
(let [objects (render/adapt-objects-for-shape objects object-id)]
|
||||
{:objects objects
|
||||
:object (get objects object-id)})))))))
|
||||
|
||||
{:keys [objects object]} (use-resource fetch-state)]
|
||||
|
||||
|
@ -137,17 +138,18 @@
|
|||
[{:keys [page-id file-id object-ids render-embed?]}]
|
||||
(let [components-v2 (features/use-feature :components-v2)
|
||||
fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id)
|
||||
(mf/deps file-id page-id components-v2)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:components-v2 components-v2}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second)))))
|
||||
(let [features (cond-> #{} components-v2 (conj "components/v2"))]
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/cmd! :get-page {:file-id file-id
|
||||
:page-id page-id
|
||||
:features features}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second))))))
|
||||
|
||||
objects (use-resource fetch-state)]
|
||||
|
||||
|
@ -204,7 +206,7 @@
|
|||
[{:keys [file-id embed] :as props}]
|
||||
(let [fetch (mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn [] (repo/query! :file {:id file-id})))
|
||||
(fn [] (repo/cmd! :get-file {:id file-id})))
|
||||
|
||||
file (use-resource fetch)
|
||||
state (mf/use-state nil)]
|
||||
|
|
|
@ -139,6 +139,7 @@
|
|||
[{:keys [body headers] :as response}]
|
||||
(let [contenttype (get headers "content-type")]
|
||||
(if (and (str/starts-with? contenttype "application/transit+json")
|
||||
(string? body)
|
||||
(pos? (count body)))
|
||||
(assoc response :body (t/decode-str body))
|
||||
response)))
|
||||
|
|
|
@ -155,14 +155,15 @@
|
|||
(->> (r/render-components (:data file) :deleted-components)
|
||||
(rx/map #(vector (str (:id file) "/deleted-components.svg") %))))
|
||||
|
||||
(defn fetch-file-with-libraries [file-id components-v2]
|
||||
(->> (rx/zip (rp/query :file {:id file-id :components-v2 components-v2})
|
||||
(rp/query :file-libraries {:file-id file-id}))
|
||||
(rx/map
|
||||
(fn [[file file-libraries]]
|
||||
(let [libraries-ids (->> file-libraries (map :id) (filterv #(not= (:id file) %)))]
|
||||
(-> file
|
||||
(assoc :libraries libraries-ids)))))))
|
||||
(defn fetch-file-with-libraries
|
||||
[file-id components-v2]
|
||||
(let [features (cond-> #{} components-v2 (conj "components/v2"))]
|
||||
(->> (rx/zip (rp/cmd! :get-file {:id file-id :features features})
|
||||
(rp/cmd! :get-file-libraries {:file-id file-id}))
|
||||
(rx/map
|
||||
(fn [[file file-libraries]]
|
||||
(let [libraries-ids (->> file-libraries (map :id) (filterv #(not= (:id file) %)))]
|
||||
(assoc file :libraries libraries-ids)))))))
|
||||
|
||||
(defn get-component-ref-file
|
||||
[objects shape]
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns app.worker.impl
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.logging :as log]
|
||||
[app.common.pages.changes :as ch]
|
||||
[app.common.transit :as t]
|
||||
|
@ -36,18 +37,16 @@
|
|||
(let [data (-> (t/decode-str file-raw) :data)
|
||||
message (assoc message :data data)]
|
||||
(reset! state data)
|
||||
(handler (-> message
|
||||
(assoc :cmd :selection/initialize-index)))
|
||||
(handler (-> message
|
||||
(assoc :cmd :snaps/initialize-index)))))
|
||||
(handler (assoc message :cmd :selection/initialize-index))
|
||||
(handler (assoc message :cmd :snaps/initialize-index))))
|
||||
|
||||
(defmethod handler :update-page-indices
|
||||
[{:keys [page-id changes] :as message}]
|
||||
|
||||
(let [old-page (get-in @state [:pages-index page-id])]
|
||||
(let [old-page (dm/get-in @state [:pages-index page-id])]
|
||||
(swap! state ch/process-changes changes false)
|
||||
|
||||
(let [new-page (get-in @state [:pages-index page-id])
|
||||
(let [new-page (dm/get-in @state [:pages-index page-id])
|
||||
message (assoc message
|
||||
:old-page old-page
|
||||
:new-page new-page)]
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
[app.common.logging :as log]
|
||||
[app.common.media :as cm]
|
||||
[app.common.text :as ct]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.http :as http]
|
||||
|
@ -128,16 +127,15 @@
|
|||
(defn create-file
|
||||
"Create a new file on the back-end"
|
||||
[context components-v2]
|
||||
(let [resolve (:resolve context)
|
||||
file-id (resolve (:file-id context))]
|
||||
(rp/mutation :create-temp-file
|
||||
{:id file-id
|
||||
:name (:name context)
|
||||
:is-shared (:shared context)
|
||||
:project-id (:project-id context)
|
||||
:data (-> ctf/empty-file-data
|
||||
(assoc :id file-id)
|
||||
(assoc-in [:options :components-v2] components-v2))})))
|
||||
(let [resolve-fn (:resolve context)
|
||||
file-id (resolve-fn (:file-id context))
|
||||
features (cond-> #{} components-v2 (conj "components/v2"))]
|
||||
(rp/cmd! :create-temp-file
|
||||
{:id file-id
|
||||
:name (:name context)
|
||||
:is-shared (:shared context)
|
||||
:project-id (:project-id context)
|
||||
:features features})))
|
||||
|
||||
(defn link-file-libraries
|
||||
"Create a new file on the back-end"
|
||||
|
@ -147,7 +145,7 @@
|
|||
libraries (->> context :libraries (mapv resolve))]
|
||||
(->> (rx/from libraries)
|
||||
(rx/map #(hash-map :file-id file-id :library-id %))
|
||||
(rx/flat-map (partial rp/mutation :link-file-to-library)))))
|
||||
(rx/flat-map (partial rp/cmd! :link-file-to-library)))))
|
||||
|
||||
(defn send-changes
|
||||
"Creates batches of changes to be sent to the backend"
|
||||
|
@ -165,17 +163,17 @@
|
|||
(->> (rx/from (d/enumerate batches))
|
||||
(rx/merge-map
|
||||
(fn [[i change-batch]]
|
||||
(->> (rp/mutation :update-temp-file
|
||||
{:id file-id
|
||||
:session-id session-id
|
||||
:revn i
|
||||
:changes change-batch})
|
||||
(->> (rp/cmd! :update-temp-file
|
||||
{:id file-id
|
||||
:session-id session-id
|
||||
:revn i
|
||||
:changes change-batch})
|
||||
(rx/tap #(do (swap! processed inc)
|
||||
(progress! context :upload-data @processed total))))))
|
||||
(rx/map first)
|
||||
(rx/ignore))
|
||||
|
||||
(->> (rp/mutation :persist-temp-file {:id file-id})
|
||||
(->> (rp/cmd! :persist-temp-file {:id file-id})
|
||||
;; We use merge to keep some information not stored in back-end
|
||||
(rx/map #(merge file %))))))
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.worker.thumbnails
|
||||
(:require
|
||||
["react-dom/server" :as rds]
|
||||
[app.common.logging :as log]
|
||||
[app.common.uri :as u]
|
||||
[app.config :as cf]
|
||||
[app.main.fonts :as fonts]
|
||||
|
@ -17,6 +18,9 @@
|
|||
[debug :refer [debug?]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(log/set-level! :trace)
|
||||
|
||||
|
||||
(defn- handle-response
|
||||
[{:keys [body status] :as response}]
|
||||
(cond
|
||||
|
@ -48,30 +52,29 @@
|
|||
(= :request-body-too-large code)))
|
||||
|
||||
(defn- request-data-for-thumbnail
|
||||
[file-id revn components-v2]
|
||||
(let [path "api/rpc/query/file-data-for-thumbnail"
|
||||
params {:file-id file-id
|
||||
:revn revn
|
||||
:strip-frames-with-thumbnails true
|
||||
:components-v2 components-v2}
|
||||
request {:method :get
|
||||
:uri (u/join @cf/public-uri path)
|
||||
:credentials "include"
|
||||
:query params}]
|
||||
[file-id revn features]
|
||||
(let [path "api/rpc/command/get-file-data-for-thumbnail"
|
||||
params {:file-id file-id
|
||||
:revn revn
|
||||
:strip-frames-with-thumbnails true
|
||||
:features features}
|
||||
request {:method :get
|
||||
:uri (u/join @cf/public-uri path)
|
||||
:credentials "include"
|
||||
:query params}]
|
||||
(->> (http/send! request)
|
||||
(rx/map http/conditional-decode-transit)
|
||||
(rx/mapcat handle-response))))
|
||||
|
||||
(defn- request-thumbnail
|
||||
[file-id revn]
|
||||
(let [path "api/rpc/query/file-thumbnail"
|
||||
(let [path "api/rpc/command/get-file-thumbnail"
|
||||
params {:file-id file-id
|
||||
:revn revn}
|
||||
request {:method :get
|
||||
:uri (u/join @cf/public-uri path)
|
||||
:credentials "include"
|
||||
:query params}]
|
||||
|
||||
(->> (http/send! request)
|
||||
(rx/map http/conditional-decode-transit)
|
||||
(rx/mapcat handle-response))))
|
||||
|
@ -91,7 +94,7 @@
|
|||
|
||||
(defn- persist-thumbnail
|
||||
[{:keys [file-id data revn fonts]}]
|
||||
(let [path "api/rpc/mutation/upsert-file-thumbnail"
|
||||
(let [path "api/rpc/command/upsert-file-thumbnail"
|
||||
params {:file-id file-id
|
||||
:revn revn
|
||||
:props {:fonts fonts}
|
||||
|
@ -108,19 +111,22 @@
|
|||
(rx/map (constantly params)))))
|
||||
|
||||
(defmethod impl/handler :thumbnails/generate
|
||||
[{:keys [file-id revn components-v2] :as message}]
|
||||
[{:keys [file-id revn features] :as message}]
|
||||
(letfn [(on-result [{:keys [data props]}]
|
||||
{:data data
|
||||
:fonts (:fonts props)})
|
||||
|
||||
(on-cache-miss [_]
|
||||
(->> (request-data-for-thumbnail file-id revn components-v2)
|
||||
(log/debug :hint "request-thumbnail" :file-id file-id :revn revn :cache "miss")
|
||||
(->> (request-data-for-thumbnail file-id revn features)
|
||||
(rx/map render-thumbnail)
|
||||
(rx/mapcat persist-thumbnail)))]
|
||||
|
||||
(if (debug? :disable-thumbnail-cache)
|
||||
(->> (request-data-for-thumbnail file-id revn components-v2)
|
||||
(->> (request-data-for-thumbnail file-id revn features)
|
||||
(rx/map render-thumbnail))
|
||||
(->> (request-thumbnail file-id revn)
|
||||
(rx/tap (fn [_]
|
||||
(log/debug :hint "request-thumbnail" :file-id file-id :revn revn :cache "hit")))
|
||||
(rx/catch not-found? on-cache-miss)
|
||||
(rx/map on-result)))))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue