mirror of
https://github.com/penpot/penpot.git
synced 2025-02-10 00:58:26 -05:00
Merge pull request #2147 from penpot/niwinz-enhancements-20220808
Enhancements & Fixes
This commit is contained in:
commit
37f5b41486
12 changed files with 466 additions and 364 deletions
|
@ -301,11 +301,17 @@
|
|||
"SELECT * FROM file_media_object WHERE id = ANY(?)")
|
||||
|
||||
(defn- retrieve-file-media
|
||||
[pool {:keys [data] :as file}]
|
||||
[pool {:keys [data id] :as file}]
|
||||
(with-open [^AutoCloseable conn (db/open pool)]
|
||||
(let [ids (app.tasks.file-gc/collect-used-media data)
|
||||
ids (db/create-array conn "uuid" ids)]
|
||||
(db/exec! conn [sql:file-media-objects ids]))))
|
||||
|
||||
;; We assoc the file-id again to the file-media-object row
|
||||
;; because there are cases that used objects refer to other
|
||||
;; files and we need to ensure in the exportation process that
|
||||
;; all ids matches
|
||||
(->> (db/exec! conn [sql:file-media-objects ids])
|
||||
(mapv #(assoc % :file-id id))))))
|
||||
|
||||
(def ^:private storage-object-id-xf
|
||||
(comp
|
||||
|
@ -539,16 +545,13 @@
|
|||
(us/assert! ::read-import-options options)
|
||||
|
||||
(letfn [(lookup-index [id]
|
||||
(if ignore-index-errors?
|
||||
(or (get @*index* id) id)
|
||||
(let [val (get @*index* id)]
|
||||
(l/trace :fn "lookup-index" :id id :val val ::l/async false)
|
||||
(when-not val
|
||||
(ex/raise :type :validation
|
||||
:code :incomplete-index
|
||||
:hint "looks like index has missing data"))
|
||||
val)))
|
||||
|
||||
(let [val (get @*index* id)]
|
||||
(l/trace :fn "lookup-index" :id id :val val ::l/async false)
|
||||
(when (and (not ignore-index-errors?) (not val))
|
||||
(ex/raise :type :validation
|
||||
:code :incomplete-index
|
||||
:hint "looks like index has missing data"))
|
||||
(or val id)))
|
||||
(update-index [index coll]
|
||||
(loop [items (seq coll)
|
||||
index index]
|
||||
|
@ -701,7 +704,6 @@
|
|||
(let [storage (media/configure-assets-storage storage)
|
||||
ids (read-obj! input)]
|
||||
|
||||
;; Step 1: process all storage objects
|
||||
(doseq [expected-storage-id ids]
|
||||
(let [id (read-uuid! input)
|
||||
mdata (read-obj! input)]
|
||||
|
@ -723,18 +725,28 @@
|
|||
(assoc ::sto/touched-at (dt/now)))
|
||||
sobject @(sto/put-object! storage params)]
|
||||
(l/trace :hint "persisted storage object" :id id :new-id (:id sobject) ::l/async false)
|
||||
(vswap! *index* assoc id (:id sobject)))))
|
||||
(vswap! *index* assoc id (:id sobject)))))))
|
||||
|
||||
;; Step 2: insert all file-media-object rows with correct
|
||||
;; storage-id reference.
|
||||
(doseq [item @*media*]
|
||||
(l/trace :hint "inserting file media objects" :id (:id item) ::l/async false)
|
||||
(db/insert! *conn* :file-media-object
|
||||
(-> item
|
||||
(update :file-id lookup-index)
|
||||
(d/update-when :media-id lookup-index)
|
||||
(d/update-when :thumbnail-id lookup-index))
|
||||
{:on-conflict-do-nothing overwrite?}))))]
|
||||
(persist-file-media-objects! []
|
||||
(l/debug :hint "processing file media objects" :section :v1/sobjects ::l/async false)
|
||||
|
||||
;; Step 2: insert all file-media-object rows with correct
|
||||
;; storage-id reference.
|
||||
(doseq [item @*media*]
|
||||
(l/trace :hint "inserting file media object"
|
||||
:id (:id item)
|
||||
:file-id (:file-id item)
|
||||
::l/async false)
|
||||
|
||||
(let [file-id (lookup-index (:file-id item))]
|
||||
(if (= file-id (:file-id item))
|
||||
(l/warn :hint "ignoring file media object" :file-id (:file-id item) ::l/async false)
|
||||
(db/insert! *conn* :file-media-object
|
||||
(-> item
|
||||
(assoc :file-id file-id)
|
||||
(d/update-when :media-id lookup-index)
|
||||
(d/update-when :thumbnail-id lookup-index))
|
||||
{:on-conflict-do-nothing overwrite?})))))]
|
||||
|
||||
(with-open [input (bs/zstd-input-stream input)]
|
||||
(with-open [input (bs/data-input-stream input)]
|
||||
|
@ -750,9 +762,11 @@
|
|||
|
||||
(doseq [section sections]
|
||||
(case section
|
||||
:v1/rels (read-rels-section! input)
|
||||
:v1/files (read-files-section! input files)
|
||||
:v1/sobjects (read-sobjects-section! input))))))))))
|
||||
:v1/rels (read-rels-section! input)
|
||||
:v1/files (read-files-section! input files)
|
||||
:v1/sobjects (do
|
||||
(read-sobjects-section! input)
|
||||
(persist-file-media-objects!)))))))))))
|
||||
|
||||
(defn export!
|
||||
[cfg]
|
||||
|
|
|
@ -6,14 +6,23 @@
|
|||
|
||||
(ns app.rpc.commands.comments
|
||||
(:require
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.spec :as us]
|
||||
[app.db :as db]
|
||||
[app.rpc.doc :as-alias doc]
|
||||
[app.rpc.queries.files :as files]
|
||||
[app.rpc.queries.teams :as teams]
|
||||
[app.rpc.retry :as retry]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; QUERY COMMANDS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [participants position] :as row}]
|
||||
(cond-> row
|
||||
|
@ -130,9 +139,16 @@
|
|||
(-> (db/exec-one! conn [sql profile-id file-id id])
|
||||
(decode-row)))))
|
||||
|
||||
;; --- COMMAND: Comments
|
||||
(defn get-comment-thread
|
||||
[conn {:keys [profile-id file-id id] :as params}]
|
||||
(let [sql (str "with threads as (" sql:comment-threads ")"
|
||||
"select * from threads where id = ?")]
|
||||
(-> (db/exec-one! conn [sql profile-id file-id id])
|
||||
(decode-row))))
|
||||
|
||||
(declare retrieve-comments)
|
||||
;; --- COMMAND: Retrieve Comments
|
||||
|
||||
(declare get-comments)
|
||||
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
|
@ -145,22 +161,24 @@
|
|||
[{:keys [pool] :as cfg} {:keys [profile-id thread-id share-id] :as params}]
|
||||
(with-open [conn (db/open pool)]
|
||||
(let [thread (db/get-by-id conn :comment-thread thread-id)]
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
(retrieve-comments conn thread-id))))
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id))
|
||||
(get-comments conn thread-id)))
|
||||
|
||||
(def sql:comments
|
||||
"select c.* from comment as c
|
||||
where c.thread_id = ?
|
||||
order by c.created_at asc")
|
||||
|
||||
(defn retrieve-comments
|
||||
(defn get-comments
|
||||
[conn thread-id]
|
||||
(->> (db/exec! conn [sql:comments thread-id])
|
||||
(->> (db/query conn :comment
|
||||
{:thread-id thread-id}
|
||||
{:order-by [[:created-at :asc]]})
|
||||
(into [] (map decode-row))))
|
||||
|
||||
;; --- COMMAND: Get file comments users
|
||||
|
||||
(declare retrieve-file-comments-users)
|
||||
(declare get-file-comments-users)
|
||||
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
|
@ -177,7 +195,7 @@
|
|||
[{:keys [pool] :as cfg} {:keys [profile-id file-id share-id]}]
|
||||
(with-open [conn (db/open pool)]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(retrieve-file-comments-users conn file-id profile-id)))
|
||||
(get-file-comments-users conn file-id profile-id)))
|
||||
|
||||
;; All the profiles that had comment the file, plus the current
|
||||
;; profile.
|
||||
|
@ -197,6 +215,320 @@
|
|||
FROM profile AS p
|
||||
WHERE p.id IN (SELECT id FROM available_profiles) OR p.id=?")
|
||||
|
||||
(defn retrieve-file-comments-users
|
||||
(defn get-file-comments-users
|
||||
[conn file-id profile-id]
|
||||
(db/exec! conn [sql:file-comment-users file-id profile-id]))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; MUTATION COMMANDS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; --- COMMAND: Create Comment Thread
|
||||
|
||||
(declare upsert-comment-thread-status!)
|
||||
(declare create-comment-thread)
|
||||
(declare retrieve-page-name)
|
||||
|
||||
(s/def ::page-id ::us/uuid)
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
(s/def ::profile-id ::us/uuid)
|
||||
(s/def ::position ::gpt/point)
|
||||
(s/def ::content ::us/string)
|
||||
(s/def ::frame-id ::us/uuid)
|
||||
|
||||
(s/def ::create-comment-thread
|
||||
(s/keys :req-un [::profile-id ::file-id ::position ::content ::page-id ::frame-id]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::create-comment-thread
|
||||
{::retry/max-retries 3
|
||||
::retry/matches retry/conflict-db-insert?
|
||||
::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id share-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(create-comment-thread conn params)))
|
||||
|
||||
(defn- retrieve-next-seqn
|
||||
[conn file-id]
|
||||
(let [sql "select (f.comment_thread_seqn + 1) as next_seqn from file as f where f.id = ?"
|
||||
res (db/exec-one! conn [sql file-id])]
|
||||
(:next-seqn res)))
|
||||
|
||||
(defn create-comment-thread
|
||||
[conn {:keys [profile-id file-id page-id position content frame-id] :as params}]
|
||||
(let [seqn (retrieve-next-seqn conn file-id)
|
||||
now (dt/now)
|
||||
pname (retrieve-page-name conn params)
|
||||
thread (db/insert! conn :comment-thread
|
||||
{:file-id file-id
|
||||
:owner-id profile-id
|
||||
:participants (db/tjson #{profile-id})
|
||||
:page-name pname
|
||||
:page-id page-id
|
||||
:created-at now
|
||||
:modified-at now
|
||||
:seqn seqn
|
||||
:position (db/pgpoint position)
|
||||
:frame-id frame-id})]
|
||||
|
||||
|
||||
;; Create a comment entry
|
||||
(db/insert! conn :comment
|
||||
{:thread-id (:id thread)
|
||||
:owner-id profile-id
|
||||
:created-at now
|
||||
:modified-at now
|
||||
:content content})
|
||||
|
||||
;; Make the current thread as read.
|
||||
(upsert-comment-thread-status! conn profile-id (:id thread))
|
||||
|
||||
;; Optimistic update of current seq number on file.
|
||||
(db/update! conn :file
|
||||
{:comment-thread-seqn seqn}
|
||||
{:id file-id})
|
||||
|
||||
(select-keys thread [:id :file-id :page-id])))
|
||||
|
||||
(defn- retrieve-page-name
|
||||
[conn {:keys [file-id page-id]}]
|
||||
(let [{:keys [data]} (db/get-by-id conn :file file-id)
|
||||
data (blob/decode data)]
|
||||
(get-in data [:pages-index page-id :name])))
|
||||
|
||||
|
||||
;; --- COMMAND: Update Comment Thread Status
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
|
||||
(s/def ::update-comment-thread-status
|
||||
(s/keys :req-un [::profile-id ::id]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::update-comment-thread-status
|
||||
{::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id share-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [cthr (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not cthr
|
||||
(ex/raise :type :not-found))
|
||||
|
||||
(files/check-comment-permissions! conn profile-id (:file-id cthr) share-id)
|
||||
(upsert-comment-thread-status! conn profile-id (:id cthr)))))
|
||||
|
||||
(def sql:upsert-comment-thread-status
|
||||
"insert into comment_thread_status (thread_id, profile_id)
|
||||
values (?, ?)
|
||||
on conflict (thread_id, profile_id)
|
||||
do update set modified_at = clock_timestamp()
|
||||
returning modified_at;")
|
||||
|
||||
(defn upsert-comment-thread-status!
|
||||
[conn profile-id thread-id]
|
||||
(db/exec-one! conn [sql:upsert-comment-thread-status thread-id profile-id]))
|
||||
|
||||
|
||||
;; --- COMMAND: Update Comment Thread
|
||||
|
||||
(s/def ::is-resolved ::us/boolean)
|
||||
(s/def ::update-comment-thread
|
||||
(s/keys :req-un [::profile-id ::id ::is-resolved]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::update-comment-thread
|
||||
{::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id is-resolved share-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not thread
|
||||
(ex/raise :type :not-found))
|
||||
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
|
||||
(db/update! conn :comment-thread
|
||||
{:is-resolved is-resolved}
|
||||
{:id id})
|
||||
nil)))
|
||||
|
||||
|
||||
;; --- COMMAND: Add Comment
|
||||
|
||||
(declare create-comment)
|
||||
|
||||
(s/def ::create-comment
|
||||
(s/keys :req-un [::profile-id ::thread-id ::content]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::create-comment
|
||||
{::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} params]
|
||||
(db/with-atomic [conn pool]
|
||||
(create-comment conn params)))
|
||||
|
||||
(defn create-comment
|
||||
[conn {:keys [profile-id thread-id content share-id] :as params}]
|
||||
(let [thread (-> (db/get-by-id conn :comment-thread thread-id {:for-update true})
|
||||
(decode-row))
|
||||
pname (retrieve-page-name conn thread)]
|
||||
|
||||
;; Standard Checks
|
||||
(when-not thread (ex/raise :type :not-found))
|
||||
|
||||
;; Permission Checks
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
|
||||
;; Update the page-name cachedattribute on comment thread table.
|
||||
(when (not= pname (:page-name thread))
|
||||
(db/update! conn :comment-thread
|
||||
{:page-name pname}
|
||||
{:id thread-id}))
|
||||
|
||||
;; NOTE: is important that all timestamptz related fields are
|
||||
;; created or updated on the database level for avoid clock
|
||||
;; inconsistencies (some user sees something read that is not
|
||||
;; read, etc...)
|
||||
(let [ppants (:participants thread #{})
|
||||
comment (db/insert! conn :comment
|
||||
{:thread-id thread-id
|
||||
:owner-id profile-id
|
||||
:content content})]
|
||||
|
||||
;; NOTE: this is done in SQL instead of using db/update!
|
||||
;; helper because currently the helper does not allow pass raw
|
||||
;; function call parameters to the underlying prepared
|
||||
;; statement; in a future when we fix/improve it, this can be
|
||||
;; changed to use the helper.
|
||||
|
||||
;; Update thread modified-at attribute and assoc the current
|
||||
;; profile to the participant set.
|
||||
(let [ppants (conj ppants profile-id)
|
||||
sql "update comment_thread
|
||||
set modified_at = clock_timestamp(),
|
||||
participants = ?
|
||||
where id = ?"]
|
||||
(db/exec-one! conn [sql (db/tjson ppants) thread-id]))
|
||||
|
||||
;; Update the current profile status in relation to the
|
||||
;; current thread.
|
||||
(upsert-comment-thread-status! conn profile-id thread-id)
|
||||
|
||||
;; Return the created comment object.
|
||||
comment)))
|
||||
|
||||
;; --- COMMAND: Update Comment
|
||||
|
||||
(declare update-comment)
|
||||
|
||||
(s/def ::update-comment
|
||||
(s/keys :req-un [::profile-id ::id ::content]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::update-comment
|
||||
{::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} params]
|
||||
(db/with-atomic [conn pool]
|
||||
(update-comment conn params)))
|
||||
|
||||
(defn update-comment
|
||||
[conn {:keys [profile-id id content share-id] :as params}]
|
||||
(let [comment (db/get-by-id conn :comment id {:for-update true})
|
||||
_ (when-not comment (ex/raise :type :not-found))
|
||||
thread (db/get-by-id conn :comment-thread (:thread-id comment) {:for-update true})
|
||||
_ (when-not thread (ex/raise :type :not-found))
|
||||
pname (retrieve-page-name conn thread)]
|
||||
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
|
||||
;; Don't allow edit comments to not owners
|
||||
(when-not (= (:owner-id thread) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
|
||||
(db/update! conn :comment
|
||||
{:content content
|
||||
:modified-at (dt/now)}
|
||||
{:id (:id comment)})
|
||||
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at (dt/now)
|
||||
:page-name pname}
|
||||
{:id (:id thread)})
|
||||
nil))
|
||||
|
||||
|
||||
;; --- COMMAND: Delete Comment Thread
|
||||
|
||||
(s/def ::delete-comment-thread
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sv/defmethod ::delete-comment-thread
|
||||
{::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not (= (:owner-id thread) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
(db/delete! conn :comment-thread {:id id})
|
||||
nil)))
|
||||
|
||||
|
||||
;; --- COMMAND: Delete comment
|
||||
|
||||
(s/def ::delete-comment
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sv/defmethod ::delete-comment
|
||||
{::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [comment (db/get-by-id conn :comment id {:for-update true})]
|
||||
(when-not (= (:owner-id comment) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
|
||||
(db/delete! conn :comment {:id id}))))
|
||||
|
||||
;; --- COMMAND: Update comment thread position
|
||||
|
||||
(s/def ::update-comment-thread-position
|
||||
(s/keys :req-un [::profile-id ::id ::position ::frame-id]))
|
||||
|
||||
(sv/defmethod ::update-comment-thread-position
|
||||
{::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id position frame-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not (= (:owner-id thread) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at (dt/now)
|
||||
:position (db/pgpoint position)
|
||||
:frame-id frame-id}
|
||||
{:id (:id thread)})
|
||||
nil)))
|
||||
|
||||
;; --- COMMAND: Update comment frame
|
||||
|
||||
(s/def ::update-comment-thread-frame
|
||||
(s/keys :req-un [::profile-id ::id ::frame-id]))
|
||||
|
||||
(sv/defmethod ::update-comment-thread-frame
|
||||
{::doc/added "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id frame-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not (= (:owner-id thread) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at (dt/now)
|
||||
:frame-id frame-id}
|
||||
{:id (:id thread)})
|
||||
nil)))
|
||||
|
||||
|
|
|
@ -7,35 +7,18 @@
|
|||
(ns app.rpc.mutations.comments
|
||||
(:require
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.spec :as us]
|
||||
[app.db :as db]
|
||||
[app.rpc.commands.comments :as cmd.comments]
|
||||
[app.rpc.doc :as-alias doc]
|
||||
[app.rpc.queries.comments :as comments]
|
||||
[app.rpc.queries.files :as files]
|
||||
[app.rpc.retry :as retry]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; --- Mutation: Create Comment Thread
|
||||
|
||||
(declare upsert-comment-thread-status!)
|
||||
(declare create-comment-thread)
|
||||
(declare retrieve-page-name)
|
||||
|
||||
(s/def ::page-id ::us/uuid)
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
(s/def ::profile-id ::us/uuid)
|
||||
(s/def ::position ::gpt/point)
|
||||
(s/def ::content ::us/string)
|
||||
(s/def ::frame-id ::us/uuid)
|
||||
|
||||
(s/def ::create-comment-thread
|
||||
(s/keys :req-un [::profile-id ::file-id ::position ::content ::page-id ::frame-id]
|
||||
:opt-un [::share-id]))
|
||||
(s/def ::create-comment-thread ::cmd.comments/create-comment-thread)
|
||||
|
||||
(sv/defmethod ::create-comment-thread
|
||||
{::retry/max-retries 3
|
||||
|
@ -45,65 +28,14 @@
|
|||
[{:keys [pool] :as cfg} {:keys [profile-id file-id share-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(create-comment-thread conn params)))
|
||||
|
||||
(defn- retrieve-next-seqn
|
||||
[conn file-id]
|
||||
(let [sql "select (f.comment_thread_seqn + 1) as next_seqn from file as f where f.id = ?"
|
||||
res (db/exec-one! conn [sql file-id])]
|
||||
(:next-seqn res)))
|
||||
|
||||
(defn- create-comment-thread
|
||||
[conn {:keys [profile-id file-id page-id position content frame-id] :as params}]
|
||||
(let [seqn (retrieve-next-seqn conn file-id)
|
||||
now (dt/now)
|
||||
pname (retrieve-page-name conn params)
|
||||
thread (db/insert! conn :comment-thread
|
||||
{:file-id file-id
|
||||
:owner-id profile-id
|
||||
:participants (db/tjson #{profile-id})
|
||||
:page-name pname
|
||||
:page-id page-id
|
||||
:created-at now
|
||||
:modified-at now
|
||||
:seqn seqn
|
||||
:position (db/pgpoint position)
|
||||
:frame-id frame-id})]
|
||||
|
||||
|
||||
;; Create a comment entry
|
||||
(db/insert! conn :comment
|
||||
{:thread-id (:id thread)
|
||||
:owner-id profile-id
|
||||
:created-at now
|
||||
:modified-at now
|
||||
:content content})
|
||||
|
||||
;; Make the current thread as read.
|
||||
(upsert-comment-thread-status! conn profile-id (:id thread))
|
||||
|
||||
;; Optimistic update of current seq number on file.
|
||||
(db/update! conn :file
|
||||
{:comment-thread-seqn seqn}
|
||||
{:id file-id})
|
||||
|
||||
(select-keys thread [:id :file-id :page-id])))
|
||||
|
||||
(defn- retrieve-page-name
|
||||
[conn {:keys [file-id page-id]}]
|
||||
(let [{:keys [data]} (db/get-by-id conn :file file-id)
|
||||
data (blob/decode data)]
|
||||
(get-in data [:pages-index page-id :name])))
|
||||
|
||||
(cmd.comments/create-comment-thread conn params)))
|
||||
|
||||
;; --- Mutation: Update Comment Thread Status
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
|
||||
(s/def ::update-comment-thread-status
|
||||
(s/keys :req-un [::profile-id ::id]
|
||||
:opt-un [::share-id]))
|
||||
(s/def ::update-comment-thread-status ::cmd.comments/update-comment-thread-status)
|
||||
|
||||
(sv/defmethod ::update-comment-thread-status
|
||||
{::doc/added "1.0"
|
||||
|
@ -111,30 +43,14 @@
|
|||
[{:keys [pool] :as cfg} {:keys [profile-id id share-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [cthr (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not cthr
|
||||
(ex/raise :type :not-found))
|
||||
|
||||
(when-not cthr (ex/raise :type :not-found))
|
||||
(files/check-comment-permissions! conn profile-id (:file-id cthr) share-id)
|
||||
(upsert-comment-thread-status! conn profile-id (:id cthr)))))
|
||||
|
||||
(def sql:upsert-comment-thread-status
|
||||
"insert into comment_thread_status (thread_id, profile_id)
|
||||
values (?, ?)
|
||||
on conflict (thread_id, profile_id)
|
||||
do update set modified_at = clock_timestamp()
|
||||
returning modified_at;")
|
||||
|
||||
(defn- upsert-comment-thread-status!
|
||||
[conn profile-id thread-id]
|
||||
(db/exec-one! conn [sql:upsert-comment-thread-status thread-id profile-id]))
|
||||
(cmd.comments/upsert-comment-thread-status! conn profile-id (:id cthr)))))
|
||||
|
||||
|
||||
;; --- Mutation: Update Comment Thread
|
||||
|
||||
(s/def ::is-resolved ::us/boolean)
|
||||
(s/def ::update-comment-thread
|
||||
(s/keys :req-un [::profile-id ::id ::is-resolved]
|
||||
:opt-un [::share-id]))
|
||||
(s/def ::update-comment-thread ::cmd.comments/update-comment-thread)
|
||||
|
||||
(sv/defmethod ::update-comment-thread
|
||||
{::doc/added "1.0"
|
||||
|
@ -146,7 +62,6 @@
|
|||
(ex/raise :type :not-found))
|
||||
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
|
||||
(db/update! conn :comment-thread
|
||||
{:is-resolved is-resolved}
|
||||
{:id id})
|
||||
|
@ -155,104 +70,31 @@
|
|||
|
||||
;; --- Mutation: Add Comment
|
||||
|
||||
(s/def ::add-comment
|
||||
(s/keys :req-un [::profile-id ::thread-id ::content]
|
||||
:opt-un [::share-id]))
|
||||
(s/def ::add-comment ::cmd.comments/create-comment)
|
||||
|
||||
(sv/defmethod ::add-comment
|
||||
{::doc/added "1.0"
|
||||
::doc/deprecated "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id thread-id content share-id] :as params}]
|
||||
[{:keys [pool] :as cfg} params]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [thread (-> (db/get-by-id conn :comment-thread thread-id {:for-update true})
|
||||
(comments/decode-row))
|
||||
pname (retrieve-page-name conn thread)]
|
||||
|
||||
;; Standard Checks
|
||||
(when-not thread (ex/raise :type :not-found))
|
||||
|
||||
;; Permission Checks
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
|
||||
;; Update the page-name cachedattribute on comment thread table.
|
||||
(when (not= pname (:page-name thread))
|
||||
(db/update! conn :comment-thread
|
||||
{:page-name pname}
|
||||
{:id thread-id}))
|
||||
|
||||
;; NOTE: is important that all timestamptz related fields are
|
||||
;; created or updated on the database level for avoid clock
|
||||
;; inconsistencies (some user sees something read that is not
|
||||
;; read, etc...)
|
||||
(let [ppants (:participants thread #{})
|
||||
comment (db/insert! conn :comment
|
||||
{:thread-id thread-id
|
||||
:owner-id profile-id
|
||||
:content content})]
|
||||
|
||||
;; NOTE: this is done in SQL instead of using db/update!
|
||||
;; helper because currently the helper does not allow pass raw
|
||||
;; function call parameters to the underlying prepared
|
||||
;; statement; in a future when we fix/improve it, this can be
|
||||
;; changed to use the helper.
|
||||
|
||||
;; Update thread modified-at attribute and assoc the current
|
||||
;; profile to the participant set.
|
||||
(let [ppants (conj ppants profile-id)
|
||||
sql "update comment_thread
|
||||
set modified_at = clock_timestamp(),
|
||||
participants = ?
|
||||
where id = ?"]
|
||||
(db/exec-one! conn [sql (db/tjson ppants) thread-id]))
|
||||
|
||||
;; Update the current profile status in relation to the
|
||||
;; current thread.
|
||||
(upsert-comment-thread-status! conn profile-id thread-id)
|
||||
|
||||
;; Return the created comment object.
|
||||
comment))))
|
||||
(cmd.comments/create-comment conn params)))
|
||||
|
||||
|
||||
;; --- Mutation: Update Comment
|
||||
|
||||
(s/def ::update-comment
|
||||
(s/keys :req-un [::profile-id ::id ::content]
|
||||
:opt-un [::share-id]))
|
||||
(s/def ::update-comment ::cmd.comments/update-comment)
|
||||
|
||||
(sv/defmethod ::update-comment
|
||||
{::doc/added "1.0"
|
||||
::doc/deprecated "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id content share-id] :as params}]
|
||||
[{:keys [pool] :as cfg} params]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [comment (db/get-by-id conn :comment id {:for-update true})
|
||||
_ (when-not comment (ex/raise :type :not-found))
|
||||
thread (db/get-by-id conn :comment-thread (:thread-id comment) {:for-update true})
|
||||
_ (when-not thread (ex/raise :type :not-found))
|
||||
pname (retrieve-page-name conn thread)]
|
||||
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
|
||||
;; Don't allow edit comments to not owners
|
||||
(when-not (= (:owner-id thread) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
|
||||
(db/update! conn :comment
|
||||
{:content content
|
||||
:modified-at (dt/now)}
|
||||
{:id (:id comment)})
|
||||
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at (dt/now)
|
||||
:page-name pname}
|
||||
{:id (:id thread)})
|
||||
nil)))
|
||||
(cmd.comments/update-comment conn params)))
|
||||
|
||||
|
||||
;; --- Mutation: Delete Comment Thread
|
||||
|
||||
(s/def ::delete-comment-thread
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
(s/def ::delete-comment-thread ::cmd.comments/delete-comment-thread)
|
||||
|
||||
(sv/defmethod ::delete-comment-thread
|
||||
{::doc/added "1.0"
|
||||
|
@ -261,16 +103,14 @@
|
|||
(db/with-atomic [conn pool]
|
||||
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not (= (:owner-id thread) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
(ex/raise :type :validation :code :not-allowed))
|
||||
(db/delete! conn :comment-thread {:id id})
|
||||
nil)))
|
||||
|
||||
|
||||
;; --- Mutation: Delete comment
|
||||
|
||||
(s/def ::delete-comment
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
(s/def ::delete-comment ::cmd.comments/delete-comment)
|
||||
|
||||
(sv/defmethod ::delete-comment
|
||||
{::doc/added "1.0"
|
||||
|
@ -279,44 +119,5 @@
|
|||
(db/with-atomic [conn pool]
|
||||
(let [comment (db/get-by-id conn :comment id {:for-update true})]
|
||||
(when-not (= (:owner-id comment) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
|
||||
(ex/raise :type :validation :code :not-allowed))
|
||||
(db/delete! conn :comment {:id id}))))
|
||||
|
||||
;; --- Mutation: Update comment thread position
|
||||
|
||||
(s/def ::update-comment-thread-position
|
||||
(s/keys :req-un [::profile-id ::id ::position ::frame-id]))
|
||||
|
||||
(sv/defmethod ::update-comment-thread-position
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id position frame-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not (= (:owner-id thread) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at (dt/now)
|
||||
:position (db/pgpoint position)
|
||||
:frame-id frame-id}
|
||||
{:id (:id thread)})
|
||||
nil)))
|
||||
|
||||
;; --- Mutation: Update comment frame
|
||||
|
||||
(s/def ::update-comment-thread-frame
|
||||
(s/keys :req-un [::profile-id ::id ::frame-id]))
|
||||
|
||||
(sv/defmethod ::update-comment-thread-frame
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id frame-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||
(when-not (= (:owner-id thread) profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at (dt/now)
|
||||
:frame-id frame-id}
|
||||
{:id (:id thread)})
|
||||
nil)))
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
(ns app.rpc.queries.comments
|
||||
(:require
|
||||
[app.common.spec :as us]
|
||||
[app.db :as db]
|
||||
[app.rpc.commands.comments :as cmd.comments]
|
||||
[app.rpc.doc :as-alias doc]
|
||||
|
@ -23,27 +22,18 @@
|
|||
|
||||
;; --- QUERY: Comment Threads
|
||||
|
||||
(s/def ::team-id ::us/uuid)
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
|
||||
(s/def ::comment-threads
|
||||
(s/and (s/keys :req-un [::profile-id]
|
||||
:opt-un [::file-id ::share-id ::team-id])
|
||||
#(or (:file-id %) (:team-id %))))
|
||||
(s/def ::comment-threads ::cmd.comments/get-comment-threads)
|
||||
|
||||
(sv/defmethod ::comment-threads
|
||||
{::doc/deprecated "1.15"}
|
||||
{::doc/added "1.0"
|
||||
::doc/deprecated "1.15"}
|
||||
[{:keys [pool] :as cfg} params]
|
||||
(with-open [conn (db/open pool)]
|
||||
(cmd.comments/retrieve-comment-threads conn params)))
|
||||
|
||||
|
||||
;; --- QUERY: Unread Comment Threads
|
||||
|
||||
(s/def ::team-id ::us/uuid)
|
||||
(s/def ::unread-comment-threads
|
||||
(s/keys :req-un [::profile-id ::team-id]))
|
||||
(s/def ::unread-comment-threads ::cmd.comments/get-unread-comment-threads)
|
||||
|
||||
(sv/defmethod ::unread-comment-threads
|
||||
{::doc/added "1.0"
|
||||
|
@ -55,31 +45,19 @@
|
|||
|
||||
;; --- QUERY: Single Comment Thread
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
(s/def ::comment-thread
|
||||
(s/keys :req-un [::profile-id ::file-id ::id]
|
||||
:opt-un [::share-id]))
|
||||
(s/def ::comment-thread ::cmd.comments/get-comment-thread)
|
||||
|
||||
(sv/defmethod ::comment-thread
|
||||
{::doc/added "1.0"
|
||||
::doc/deprecated "1.15"}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id id share-id] :as params}]
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id share-id] :as params}]
|
||||
(with-open [conn (db/open pool)]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(let [sql (str "with threads as (" cmd.comments/sql:comment-threads ")"
|
||||
"select * from threads where id = ?")]
|
||||
(-> (db/exec-one! conn [sql profile-id file-id id])
|
||||
(decode-row)))))
|
||||
(cmd.comments/get-comment-thread conn params)))
|
||||
|
||||
;; --- QUERY: Comments
|
||||
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
(s/def ::thread-id ::us/uuid)
|
||||
(s/def ::comments
|
||||
(s/keys :req-un [::profile-id ::thread-id]
|
||||
:opt-un [::share-id]))
|
||||
(s/def ::comments ::cmd.comments/get-comments)
|
||||
|
||||
(sv/defmethod ::comments
|
||||
{::doc/added "1.0"
|
||||
|
@ -87,17 +65,13 @@
|
|||
[{:keys [pool] :as cfg} {:keys [profile-id thread-id share-id] :as params}]
|
||||
(with-open [conn (db/open pool)]
|
||||
(let [thread (db/get-by-id conn :comment-thread thread-id)]
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
(cmd.comments/retrieve-comments conn thread-id))))
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id))
|
||||
(cmd.comments/get-comments conn thread-id)))
|
||||
|
||||
|
||||
;; --- QUERY: Get file comments users
|
||||
|
||||
(s/def ::file-id ::us/uuid)
|
||||
(s/def ::share-id (s/nilable ::us/uuid))
|
||||
|
||||
(s/def ::file-comments-users
|
||||
(s/keys :req-un [::profile-id ::file-id]
|
||||
:opt-un [::share-id]))
|
||||
(s/def ::file-comments-users ::cmd.comments/get-profiles-for-file-comments)
|
||||
|
||||
(sv/defmethod ::file-comments-users
|
||||
{::doc/deprecated "1.15"
|
||||
|
@ -105,4 +79,4 @@
|
|||
[{:keys [pool] :as cfg} {:keys [profile-id file-id share-id]}]
|
||||
(with-open [conn (db/open pool)]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(cmd.comments/retrieve-file-comments-users conn file-id profile-id)))
|
||||
(cmd.comments/get-file-comments-users conn file-id profile-id)))
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
(p/let [file (files/retrieve-file cfg file-id)
|
||||
project (retrieve-project pool (:project-id file))
|
||||
libs (files/retrieve-file-libraries cfg false file-id)
|
||||
users (comments/retrieve-file-comments-users pool file-id profile-id)
|
||||
users (comments/get-file-comments-users pool file-id profile-id)
|
||||
|
||||
links (->> (db/query pool :share-link {:file-id file-id})
|
||||
(mapv slnk/decode-share-link-row))
|
||||
|
|
|
@ -93,8 +93,8 @@
|
|||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (cph/frame-id-by-position objects (:position params))
|
||||
params (assoc params :frame-id frame-id)]
|
||||
(->> (rp/mutation :create-comment-thread params)
|
||||
(rx/mapcat #(rp/query :comment-thread {:file-id (:file-id %) :id (:id %)}))
|
||||
(->> (rp/cmd! :create-comment-thread params)
|
||||
(rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %)}))
|
||||
(rx/map created-thread-on-workspace)
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
|
||||
|
@ -122,8 +122,8 @@
|
|||
(let [share-id (-> state :viewer-local :share-id)
|
||||
frame-id (:frame-id params)
|
||||
params (assoc params :share-id share-id :frame-id frame-id)]
|
||||
(->> (rp/mutation :create-comment-thread params)
|
||||
(rx/mapcat #(rp/query :comment-thread {:file-id (:file-id %) :id (:id %) :share-id share-id}))
|
||||
(->> (rp/cmd! :create-comment-thread params)
|
||||
(rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %) :share-id share-id}))
|
||||
(rx/map created-thread-on-viewer)
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
|
||||
|
@ -135,7 +135,7 @@
|
|||
(watch [_ state _]
|
||||
(let [done #(d/update-in-when % [:comment-threads id] assoc :count-unread-comments 0)
|
||||
share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/mutation :update-comment-thread-status {:id id :share-id share-id})
|
||||
(->> (rp/cmd! :update-comment-thread-status {:id id :share-id share-id})
|
||||
(rx/map (constantly done))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
|
||||
|
@ -153,7 +153,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/mutation :update-comment-thread {:id id :is-resolved is-resolved :share-id share-id})
|
||||
(->> (rp/cmd! :update-comment-thread {:id id :is-resolved is-resolved :share-id share-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))))))
|
||||
|
||||
|
@ -168,7 +168,7 @@
|
|||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(rx/concat
|
||||
(->> (rp/mutation :add-comment {:thread-id (:id thread) :content content :share-id share-id})
|
||||
(->> (rp/cmd! :create-comment {:thread-id (:id thread) :content content :share-id share-id})
|
||||
(rx/map #(partial created %))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))
|
||||
(rx/of (refresh-comment-thread thread))))))))
|
||||
|
@ -184,7 +184,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/mutation :update-comment {:id id :content content :share-id share-id})
|
||||
(->> (rp/cmd! :update-comment {:id id :content content :share-id share-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))))))
|
||||
|
||||
|
@ -202,7 +202,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/mutation :delete-comment-thread {:id id})
|
||||
(->> (rp/cmd! :delete-comment-thread {:id id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore)))))
|
||||
|
||||
|
@ -221,7 +221,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/mutation :delete-comment-thread {:id id :share-id share-id})
|
||||
(->> (rp/cmd! :delete-comment-thread {:id id :share-id share-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))))))
|
||||
|
||||
|
@ -236,7 +236,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/mutation :delete-comment {:id id :share-id share-id})
|
||||
(->> (rp/cmd! :delete-comment {:id id :share-id share-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))))))
|
||||
|
||||
|
@ -249,7 +249,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/query :comment-thread {:file-id file-id :id id :share-id share-id})
|
||||
(->> (rp/cmd! :get-comment-thread {:file-id file-id :id id :share-id share-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
|
@ -272,7 +272,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/query :comment-threads {:file-id file-id :share-id share-id})
|
||||
(->> (rp/cmd! :get-comment-threads {:file-id file-id :share-id share-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
|
@ -285,7 +285,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/query :comments {:thread-id thread-id :share-id share-id})
|
||||
(->> (rp/cmd! :get-comments {:thread-id thread-id :share-id share-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
|
@ -297,7 +297,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [fetched #(assoc %2 :comment-threads (d/index-by :id %1))]
|
||||
(->> (rp/query :unread-comment-threads {:team-id team-id})
|
||||
(->> (rp/cmd! :get-unread-comment-threads {:team-id team-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
|
||||
|
@ -426,7 +426,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [thread-id (:id thread)]
|
||||
(->> (rp/mutation :update-comment-thread-frame {:id thread-id :frame-id frame-id})
|
||||
(->> (rp/cmd! :update-comment-thread-frame {:id thread-id :frame-id frame-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error :code :update-comment-thread-frame}))
|
||||
(rx/ignore)))))))
|
||||
|
||||
|
|
|
@ -445,7 +445,7 @@
|
|||
(ptk/reify ::fetch-team-users
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :team-users {:team-id team-id})
|
||||
(->> (rp/query! :team-users {:team-id team-id})
|
||||
(rx/map #(partial fetched %)))))))
|
||||
|
||||
(defn fetch-file-comments-users
|
||||
|
@ -459,7 +459,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/query :file-comments-users {:team-id team-id :share-id share-id})
|
||||
(->> (rp/command! :get-profiles-for-file-comments {:team-id team-id :share-id share-id})
|
||||
(rx/map #(partial fetched %))))))))
|
||||
|
||||
;; --- EVENT: request-account-deletion
|
||||
|
|
|
@ -102,7 +102,7 @@
|
|||
(watch [_ _ _]
|
||||
(let [params' (cond-> {:file-id file-id}
|
||||
(uuid? share-id) (assoc :share-id share-id))]
|
||||
(->> (rp/query :view-only-bundle params')
|
||||
(->> (rp/query! :view-only-bundle params')
|
||||
(rx/mapcat
|
||||
(fn [{:keys [fonts] :as bundle}]
|
||||
(rx/of (df/fonts-fetched fonts)
|
||||
|
@ -156,7 +156,7 @@
|
|||
(ptk/reify ::fetch-comment-threads
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :comment-threads {:file-id file-id :share-id share-id})
|
||||
(->> (rp/cmd! :get-comment-threads {:file-id file-id :share-id share-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch on-error))))))
|
||||
|
||||
|
@ -167,7 +167,7 @@
|
|||
(ptk/reify ::refresh-comment-thread
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :comment-thread {:file-id file-id :id id})
|
||||
(->> (rp/cmd! :get-comment-thread {:file-id file-id :id id})
|
||||
(rx/map #(partial fetched %)))))))
|
||||
|
||||
(defn fetch-comments
|
||||
|
@ -178,7 +178,7 @@
|
|||
(ptk/reify ::retrieve-comments
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :comments {:thread-id thread-id})
|
||||
(->> (rp/cmd! :get-comments {:thread-id thread-id})
|
||||
(rx/map #(partial fetched %)))))))
|
||||
|
||||
;; --- Zoom Management
|
||||
|
|
|
@ -136,7 +136,7 @@
|
|||
|
||||
(rx/merge
|
||||
(rx/of (dwc/commit-changes changes))
|
||||
(->> (rp/mutation :update-comment-thread-position thread)
|
||||
(->> (rp/cmd! :update-comment-thread-position thread)
|
||||
(rx/catch #(rx/throw {:type :update-comment-thread-position}))
|
||||
(rx/ignore))))))))
|
||||
|
||||
|
|
|
@ -262,11 +262,11 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rx/zip (rp/query :file-raw {:id file-id})
|
||||
(rp/query :team-users {:file-id file-id})
|
||||
(rp/query :project {:id project-id})
|
||||
(rp/query :file-libraries {:file-id file-id})
|
||||
(rp/query :file-comments-users {:file-id file-id :share-id share-id}))
|
||||
(->> (rx/zip (rp/query! :file-raw {:id file-id})
|
||||
(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-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]]
|
||||
{:file-raw file-raw
|
||||
|
|
|
@ -178,56 +178,33 @@
|
|||
(let [objects (wsh/lookup-page-objects state)]
|
||||
(rx/of (dwc/expand-all-parents ids objects))))))
|
||||
|
||||
|
||||
|
||||
(defn- select-siblings
|
||||
[state parent]
|
||||
(let [children (wsh/lookup-shapes state (:shapes parent))
|
||||
selected (into (d/ordered-set)
|
||||
(comp (remove :blocked) (map :id))
|
||||
children)]
|
||||
(rx/of (select-shapes selected))))
|
||||
|
||||
(defn- select-all-frame
|
||||
[state]
|
||||
(let [focus (:workspace-focus-selected state)
|
||||
objects (-> (wsh/lookup-page-objects state)
|
||||
(cp/focus-objects focus))
|
||||
|
||||
selected (let [frame-ids (into #{} (comp
|
||||
(map (d/getf objects))
|
||||
(map :frame-id))
|
||||
(wsh/lookup-selected state))
|
||||
frame-id (if (= 1 (count frame-ids))
|
||||
(first frame-ids)
|
||||
uuid/zero)]
|
||||
(cph/get-immediate-children objects frame-id))
|
||||
|
||||
selected (into (d/ordered-set)
|
||||
(comp (remove :blocked) (map :id))
|
||||
selected)]
|
||||
|
||||
(rx/of (select-shapes selected))))
|
||||
|
||||
|
||||
(defn select-all
|
||||
[]
|
||||
(ptk/reify ::select-all
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [current-selection-parents (->> (wsh/lookup-selected state)
|
||||
(wsh/lookup-shapes state)
|
||||
(into #{} (map :parent-id)))
|
||||
num-parents (count current-selection-parents)
|
||||
parent (when (= num-parents 1)
|
||||
(wsh/lookup-shape state (first current-selection-parents)))]
|
||||
(let [;; Make the select-all aware of the focus mode; in this
|
||||
;; case delimit the objects to the focused shapes if focus
|
||||
;; mode is active
|
||||
focus (:workspace-focus-selected state)
|
||||
objects (-> (wsh/lookup-page-objects state)
|
||||
(cp/focus-objects focus))
|
||||
|
||||
(case num-parents
|
||||
0 (select-all-frame state)
|
||||
1 (if (cph/frame-shape? parent)
|
||||
(select-all-frame state)
|
||||
(select-siblings state parent))
|
||||
nil)))))
|
||||
lookup (d/getf objects)
|
||||
parents (->> (wsh/lookup-selected state)
|
||||
(into #{} (comp (keep lookup) (map :parent-id))))
|
||||
|
||||
;; If we have a only unique parent, then use it as main
|
||||
;; anchor for the selection; if not, use the root frame as
|
||||
;; parent
|
||||
parent (if (= 1 (count parents))
|
||||
(-> parents first lookup)
|
||||
(lookup uuid/zero))
|
||||
|
||||
toselect (->> (cph/get-immediate-children objects (:id parent))
|
||||
(into (d/ordered-set) (comp (remove :blocked) (map :id))))]
|
||||
|
||||
(rx/of (select-shapes toselect))))))
|
||||
|
||||
(defn deselect-all
|
||||
"Clear all possible state of drawing, edition
|
||||
|
|
|
@ -127,6 +127,10 @@
|
|||
([id] (command id {}))
|
||||
([id params] (command id params)))
|
||||
|
||||
(defn cmd!
|
||||
([id] (command id {}))
|
||||
([id params] (command id params)))
|
||||
|
||||
(defmethod command :login-with-oidc
|
||||
[_ {:keys [provider] :as params}]
|
||||
(let [uri (u/join base-uri "api/auth/oauth/" (d/name provider))
|
||||
|
|
Loading…
Add table
Reference in a new issue