mirror of
https://github.com/penpot/penpot.git
synced 2025-03-26 14:41:36 -05:00
✨ In view mode allow comment/inspect to non-team users (by shared link permissions)
This commit is contained in:
parent
0f04398e61
commit
115314e97c
23 changed files with 254 additions and 132 deletions
CHANGES.md
backend
frontend/src/app/main
|
@ -6,6 +6,7 @@
|
|||
|
||||
- Allow for nested and rotated boards inside other boards and groups [Taiga #2874](https://tree.taiga.io/project/penpot/us/2874?milestone=319982)
|
||||
- View mode improvements to enable access and use in different conditions [Taiga #3023](https://tree.taiga.io/project/penpot/us/3023)
|
||||
- Improved share link options. Now you can allow non-team members to comment and/or inspect [Taiga #3056] (https://tree.taiga.io/project/penpot/us/3056)
|
||||
|
||||
### :bug: Bugs fixed
|
||||
### :arrow_up: Deps updates
|
||||
|
|
|
@ -228,13 +228,13 @@
|
|||
:fn (mg/resource "app/migrations/sql/0072-mod-file-object-thumbnail-table.sql")}
|
||||
|
||||
{:name "0073-mod-file-media-object-constraints"
|
||||
:fn (mg/resource "app/migrations/sql/0073-mod-file-media-object-constraints.sql")}
|
||||
|
||||
{:name "0073-mod-share-link-table"
|
||||
:fn (mg/resource "app/migrations/sql/0073-mod-share-link-table.sql")}
|
||||
:fn (mg/resource "app/migrations/sql/0073-mod-file-media-object-constraints.sql")}
|
||||
|
||||
{:name "0074-mod-file-library-rel-constraints"
|
||||
:fn (mg/resource "app/migrations/sql/0074-mod-file-library-rel-constraints.sql")}
|
||||
|
||||
{:name "0075-mod-share-link-table"
|
||||
:fn (mg/resource "app/migrations/sql/0075-mod-share-link-table.sql")}
|
||||
])
|
||||
|
||||
|
||||
|
|
|
@ -26,19 +26,21 @@
|
|||
|
||||
(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 ::create-comment-thread
|
||||
(s/keys :req-un [::profile-id ::file-id ::position ::content ::page-id]))
|
||||
(s/keys :req-un [::profile-id ::file-id ::position ::content ::page-id]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::create-comment-thread
|
||||
{::retry/max-retries 3
|
||||
::retry/matches retry/conflict-db-insert?}
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id] :as params}]
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id share-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(files/check-read-permissions! conn profile-id file-id)
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(create-comment-thread conn params)))
|
||||
|
||||
(defn- retrieve-next-seqn
|
||||
|
@ -92,18 +94,20 @@
|
|||
;; --- 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]))
|
||||
(s/keys :req-un [::profile-id ::id]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::update-comment-thread-status
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id] :as params}]
|
||||
[{: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-read-permissions! conn profile-id (:file-id cthr))
|
||||
(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
|
||||
|
@ -122,16 +126,17 @@
|
|||
|
||||
(s/def ::is-resolved ::us/boolean)
|
||||
(s/def ::update-comment-thread
|
||||
(s/keys :req-un [::profile-id ::id ::is-resolved]))
|
||||
(s/keys :req-un [::profile-id ::id ::is-resolved]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::update-comment-thread
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id is-resolved] :as params}]
|
||||
[{: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-read-permissions! conn profile-id (:file-id thread))
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
|
||||
(db/update! conn :comment-thread
|
||||
{:is-resolved is-resolved}
|
||||
|
@ -142,10 +147,11 @@
|
|||
;; --- Mutation: Add Comment
|
||||
|
||||
(s/def ::add-comment
|
||||
(s/keys :req-un [::profile-id ::thread-id ::content]))
|
||||
(s/keys :req-un [::profile-id ::thread-id ::content]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::add-comment
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id thread-id content] :as params}]
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id thread-id content share-id] :as params}]
|
||||
(db/with-atomic [conn pool]
|
||||
(let [thread (-> (db/get-by-id conn :comment-thread thread-id {:for-update true})
|
||||
(comments/decode-row))
|
||||
|
@ -155,7 +161,7 @@
|
|||
(when-not thread (ex/raise :type :not-found))
|
||||
|
||||
;; Permission Checks
|
||||
(files/check-read-permissions! conn profile-id (:file-id thread))
|
||||
(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))
|
||||
|
@ -199,10 +205,11 @@
|
|||
;; --- Mutation: Update Comment
|
||||
|
||||
(s/def ::update-comment
|
||||
(s/keys :req-un [::profile-id ::id ::content]))
|
||||
(s/keys :req-un [::profile-id ::id ::content]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::update-comment
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id content] :as params}]
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id id content share-id] :as 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))
|
||||
|
@ -210,7 +217,7 @@
|
|||
_ (when-not thread (ex/raise :type :not-found))
|
||||
pname (retrieve-page-name conn thread)]
|
||||
|
||||
(files/check-read-permissions! conn profile-id (:file-id 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)
|
||||
|
|
|
@ -53,6 +53,16 @@
|
|||
([perms] (:can-read perms))
|
||||
([conn & args] (check (apply qfn conn args)))))
|
||||
|
||||
(defn make-comment-predicate-fn
|
||||
"A simple factory for comment permission predicate functions."
|
||||
[qfn]
|
||||
(us/assert fn? qfn)
|
||||
(fn check
|
||||
([perms]
|
||||
(and (:is-logged perms) (= (:who-comment perms) "all")))
|
||||
([conn & args]
|
||||
(check (apply qfn conn args)))))
|
||||
|
||||
(defn make-check-fn
|
||||
"Helper that converts a predicate permission function to a check
|
||||
function (function that raises an exception)."
|
||||
|
|
|
@ -25,16 +25,16 @@
|
|||
|
||||
(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 ::team-id])
|
||||
:opt-un [::file-id ::share-id ::team-id])
|
||||
#(or (:file-id %) (:team-id %))))
|
||||
|
||||
(sv/defmethod ::comment-threads
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id] :as params}]
|
||||
[{:keys [pool] :as cfg} params]
|
||||
(with-open [conn (db/open pool)]
|
||||
(files/check-read-permissions! conn profile-id file-id)
|
||||
(retrieve-comment-threads conn params)))
|
||||
|
||||
(def sql:comment-threads
|
||||
|
@ -60,8 +60,8 @@
|
|||
window w as (partition by c.thread_id order by c.created_at asc)")
|
||||
|
||||
(defn- retrieve-comment-threads
|
||||
[conn {:keys [profile-id file-id]}]
|
||||
(files/check-read-permissions! conn profile-id file-id)
|
||||
[conn {:keys [profile-id file-id share-id]}]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(->> (db/exec! conn [sql:comment-threads profile-id file-id])
|
||||
(into [] (map decode-row))))
|
||||
|
||||
|
@ -116,13 +116,15 @@
|
|||
;; --- 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]))
|
||||
(s/keys :req-un [::profile-id ::file-id ::id]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::comment-thread
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id id] :as params}]
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id file-id id share-id] :as params}]
|
||||
(with-open [conn (db/open pool)]
|
||||
(files/check-read-permissions! conn profile-id file-id)
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(let [sql (str "with threads as (" sql:comment-threads ")"
|
||||
"select * from threads where id = ?")]
|
||||
(-> (db/exec-one! conn [sql profile-id file-id id])
|
||||
|
@ -133,15 +135,17 @@
|
|||
(declare retrieve-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]))
|
||||
(s/keys :req-un [::profile-id ::thread-id]
|
||||
:opt-un [::share-id]))
|
||||
|
||||
(sv/defmethod ::comments
|
||||
[{:keys [pool] :as cfg} {:keys [profile-id thread-id] :as params}]
|
||||
[{: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-read-permissions! conn profile-id (:file-id thread))
|
||||
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
|
||||
(retrieve-comments conn thread-id))))
|
||||
|
||||
(def sql:comments
|
||||
|
@ -153,3 +157,40 @@
|
|||
[conn thread-id]
|
||||
(->> (db/exec! conn [sql:comments thread-id])
|
||||
(into [] (map decode-row))))
|
||||
|
||||
;; file-comments-users
|
||||
|
||||
(declare retrieve-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]))
|
||||
|
||||
(sv/defmethod ::file-comments-users
|
||||
[{: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)))
|
||||
|
||||
(def sql:file-comment-users
|
||||
"select p.id,
|
||||
p.email,
|
||||
p.fullname as name,
|
||||
p.fullname as fullname,
|
||||
p.photo_id,
|
||||
p.is_active
|
||||
from profile p
|
||||
where p.id in
|
||||
(select owner_id from comment
|
||||
where thread_id in
|
||||
(select id from comment_thread
|
||||
where file_id=?))
|
||||
or p.id=?
|
||||
") ;; all the users that had comment the file, plus the current user
|
||||
|
||||
(defn retrieve-file-comments-users
|
||||
[conn file-id profile-id]
|
||||
(db/exec! conn [sql:file-comment-users file-id profile-id]))
|
||||
|
|
|
@ -98,7 +98,9 @@
|
|||
(some? perms) perms
|
||||
(some? ldata) {:type :share-link
|
||||
:can-read true
|
||||
:flags (:flags ldata)}))))
|
||||
:is-logged (some? profile-id)
|
||||
:who-comment (:who-comment ldata)
|
||||
:who-inspect (:who-inspect ldata)}))))
|
||||
|
||||
(def has-edit-permissions?
|
||||
(perms/make-edition-predicate-fn get-permissions))
|
||||
|
@ -106,12 +108,26 @@
|
|||
(def has-read-permissions?
|
||||
(perms/make-read-predicate-fn get-permissions))
|
||||
|
||||
(def has-comment-permissions?
|
||||
(perms/make-comment-predicate-fn get-permissions))
|
||||
|
||||
(def check-edition-permissions!
|
||||
(perms/make-check-fn has-edit-permissions?))
|
||||
|
||||
(def check-read-permissions!
|
||||
(perms/make-check-fn has-read-permissions?))
|
||||
|
||||
;; A user has comment permissions if she has read permissions, or comment permissions
|
||||
(defn check-comment-permissions!
|
||||
[conn profile-id file-id share-id]
|
||||
(let [can-read (has-read-permissions? conn profile-id file-id)
|
||||
can-comment (has-comment-permissions? conn profile-id file-id share-id)
|
||||
]
|
||||
(when-not (or can-read can-comment)
|
||||
(ex/raise :type :not-found
|
||||
:code :object-not-found
|
||||
:hint "not found"))))
|
||||
|
||||
;; --- Query: Files search
|
||||
|
||||
;; TODO: this query need to a good refactor
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
[app.common.exceptions :as ex]
|
||||
[app.common.spec :as us]
|
||||
[app.db :as db]
|
||||
[app.rpc.queries.comments :as comments]
|
||||
[app.rpc.queries.files :as files]
|
||||
[app.rpc.queries.share-link :as slnk]
|
||||
[app.rpc.queries.teams :as teams]
|
||||
[app.rpc.queries.share-link :as slnk]
|
||||
[app.util.services :as sv]
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]))
|
||||
|
@ -23,11 +23,11 @@
|
|||
(db/get-by-id pool :project id {:columns [:id :name :team-id]}))
|
||||
|
||||
(defn- retrieve-bundle
|
||||
[{:keys [pool] :as cfg} file-id]
|
||||
[{:keys [pool] :as cfg} file-id profile-id]
|
||||
(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 (teams/retrieve-users pool (:team-id project))
|
||||
users (comments/retrieve-file-comments-users pool file-id profile-id)
|
||||
|
||||
links (->> (db/query pool :share-link {:file-id file-id})
|
||||
(mapv slnk/decode-share-link-row))
|
||||
|
@ -54,7 +54,7 @@
|
|||
(p/let [slink (slnk/retrieve-share-link pool file-id share-id)
|
||||
perms (files/get-permissions pool profile-id file-id share-id)
|
||||
thumbs (files/retrieve-object-thumbnails cfg file-id)
|
||||
bundle (p/-> (retrieve-bundle cfg file-id)
|
||||
bundle (p/-> (retrieve-bundle cfg file-id profile-id)
|
||||
(assoc :permissions perms)
|
||||
(assoc-in [:file :thumbnails] thumbs))]
|
||||
|
||||
|
|
|
@ -49,7 +49,8 @@
|
|||
:profile-id (:id prof)
|
||||
:file-id (:id file)
|
||||
:pages #{(get-in file [:data :pages 0])}
|
||||
:flags #{}}
|
||||
:who-comment "team"
|
||||
:who-inspect "all"}
|
||||
out (th/mutation! data)]
|
||||
|
||||
;; (th/print-result! out)
|
||||
|
|
|
@ -75,20 +75,23 @@
|
|||
|
||||
(ptk/reify ::create-comment-thread
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/mutation :create-comment-thread params)
|
||||
(rx/mapcat #(rp/query :comment-thread {:file-id (:file-id %) :id (:id %)}))
|
||||
(rx/map #(partial created %))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)
|
||||
params (assoc params :share-id share-id)]
|
||||
(->> (rp/mutation :create-comment-thread params)
|
||||
(rx/mapcat #(rp/query :comment-thread {:file-id (:file-id %) :id (:id %) :share-id share-id}))
|
||||
(rx/map #(partial created %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
(defn update-comment-thread-status
|
||||
[{:keys [id] :as thread}]
|
||||
(us/assert ::comment-thread thread)
|
||||
(ptk/reify ::update-comment-thread-status
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [done #(d/update-in-when % [:comment-threads id] assoc :count-unread-comments 0)]
|
||||
(->> (rp/mutation :update-comment-thread-status {:id id})
|
||||
(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})
|
||||
(rx/map (constantly done))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
|
||||
|
@ -105,10 +108,11 @@
|
|||
(d/update-in-when state [:comment-threads id] assoc :is-resolved is-resolved))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/mutation :update-comment-thread {:id id :is-resolved is-resolved})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore)))))
|
||||
(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})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))))))
|
||||
|
||||
|
||||
(defn add-comment
|
||||
|
@ -119,12 +123,13 @@
|
|||
(update-in state [:comments (:id thread)] assoc (:id comment) comment))]
|
||||
(ptk/reify ::create-comment
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/concat
|
||||
(->> (rp/mutation :add-comment {:thread-id (:id thread) :content content})
|
||||
(rx/map #(partial created %))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))
|
||||
(rx/of (refresh-comment-thread thread)))))))
|
||||
(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})
|
||||
(rx/map #(partial created %))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))
|
||||
(rx/of (refresh-comment-thread thread))))))))
|
||||
|
||||
(defn update-comment
|
||||
[{:keys [id content thread-id] :as comment}]
|
||||
|
@ -135,10 +140,11 @@
|
|||
(d/update-in-when state [:comments thread-id id] assoc :content content))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/mutation :update-comment {:id id :content content})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore)))))
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/mutation :update-comment {:id id :content content :share-id share-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))))))
|
||||
|
||||
(defn delete-comment-thread
|
||||
[{:keys [id] :as thread}]
|
||||
|
@ -151,10 +157,11 @@
|
|||
(update :comment-threads dissoc id)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/mutation :delete-comment-thread {:id id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore)))))
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/mutation :delete-comment-thread {:id id :share-id share-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))))))
|
||||
|
||||
(defn delete-comment
|
||||
[{:keys [id thread-id] :as comment}]
|
||||
|
@ -165,10 +172,11 @@
|
|||
(d/update-in-when state [:comments thread-id] dissoc id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/mutation :delete-comment {:id id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore)))))
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/mutation :delete-comment {:id id :share-id share-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/ignore))))))
|
||||
|
||||
(defn refresh-comment-thread
|
||||
[{:keys [id file-id] :as thread}]
|
||||
|
@ -177,10 +185,11 @@
|
|||
(assoc-in state [:comment-threads id] thread))]
|
||||
(ptk/reify ::refresh-comment-thread
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :comment-thread {:file-id file-id :id id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/query :comment-thread {:file-id file-id :id id :share-id share-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
(defn retrieve-comment-threads
|
||||
[file-id]
|
||||
|
@ -189,10 +198,11 @@
|
|||
(assoc state :comment-threads (d/index-by :id data)))]
|
||||
(ptk/reify ::retrieve-comment-threads
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :comment-threads {:file-id file-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/query :comment-threads {:file-id file-id :share-id share-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
(defn retrieve-comments
|
||||
[thread-id]
|
||||
|
@ -201,10 +211,11 @@
|
|||
(update state :comments assoc thread-id (d/index-by :id comments)))]
|
||||
(ptk/reify ::retrieve-comments
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :comments {:thread-id thread-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error})))))))
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/query :comments {:thread-id thread-id :share-id share-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
(defn retrieve-unread-comment-threads
|
||||
"A event used mainly in dashboard for retrieve all unread threads of a team."
|
||||
|
|
|
@ -436,7 +436,6 @@
|
|||
(rx/map (constantly (fetch-profile)))
|
||||
(rx/catch on-error))))))
|
||||
|
||||
|
||||
(defn fetch-users
|
||||
[{:keys [team-id] :as params}]
|
||||
(us/assert ::us/uuid team-id)
|
||||
|
@ -450,6 +449,20 @@
|
|||
(->> (rp/query :team-users {:team-id team-id})
|
||||
(rx/map #(partial fetched %)))))))
|
||||
|
||||
(defn fetch-file-comments-users
|
||||
[{:keys [team-id] :as params}]
|
||||
(us/assert ::us/uuid team-id)
|
||||
(letfn [(fetched [users state]
|
||||
(->> users
|
||||
(d/index-by :id)
|
||||
(assoc state :file-comments-users)))]
|
||||
(ptk/reify ::fetch-team-users
|
||||
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})
|
||||
(rx/map #(partial fetched %))))))))
|
||||
|
||||
;; --- EVENT: request-account-deletion
|
||||
|
||||
(defn request-account-deletion
|
||||
|
|
|
@ -33,7 +33,9 @@
|
|||
:selected #{}
|
||||
:collapsed #{}
|
||||
:overlays []
|
||||
:hover nil})
|
||||
:hover nil
|
||||
:share-id ""
|
||||
:file-comments-users []})
|
||||
|
||||
(declare fetch-comment-threads)
|
||||
(declare fetch-bundle)
|
||||
|
@ -50,7 +52,7 @@
|
|||
:opt-un [::share-id ::page-id]))
|
||||
|
||||
(defn initialize
|
||||
[{:keys [file-id] :as params}]
|
||||
[{:keys [file-id share-id] :as params}]
|
||||
(us/assert ::initialize-params params)
|
||||
(ptk/reify ::initialize
|
||||
ptk/UpdateEvent
|
||||
|
@ -61,7 +63,8 @@
|
|||
(fn [lstate]
|
||||
(if (nil? lstate)
|
||||
default-local-state
|
||||
lstate)))))
|
||||
lstate)))
|
||||
(assoc-in [:viewer-local :share-id] share-id)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
|
@ -138,7 +141,7 @@
|
|||
(rx/of (go-to-frame-auto))))))))
|
||||
|
||||
(defn fetch-comment-threads
|
||||
[{:keys [file-id page-id] :as params}]
|
||||
[{:keys [file-id page-id share-id] :as params}]
|
||||
(letfn [(fetched [data state]
|
||||
(->> data
|
||||
(filter #(= page-id (:page-id %)))
|
||||
|
@ -153,7 +156,7 @@
|
|||
(ptk/reify ::fetch-comment-threads
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/query :comment-threads {:file-id file-id})
|
||||
(->> (rp/query :comment-threads {:file-id file-id :share-id share-id})
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch on-error))))))
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@
|
|||
(unchecked-set ug/global "name" name)))))
|
||||
|
||||
(defn- file-initialized
|
||||
[{:keys [file users project libraries] :as bundle}]
|
||||
[{:keys [file users project libraries file-comments-users] :as bundle}]
|
||||
(ptk/reify ::file-initialized
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
@ -156,7 +156,8 @@
|
|||
;; the version number
|
||||
#_(assoc :version 17)
|
||||
#_(app.common.pages.migrations/migrate-data 19))
|
||||
:workspace-libraries (d/index-by :id libraries)))
|
||||
:workspace-libraries (d/index-by :id libraries)
|
||||
:current-file-comments-users (d/index-by :id file-comments-users)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
|
|
|
@ -258,20 +258,23 @@
|
|||
[project-id file-id]
|
||||
(ptk/reify ::fetch-bundle
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (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}))
|
||||
(rx/take 1)
|
||||
(rx/map (fn [[file-raw users project libraries]]
|
||||
{:file-raw file-raw
|
||||
:users users
|
||||
:project project
|
||||
:libraries libraries}))
|
||||
(rx/mapcat (fn [{:keys [project] :as bundle}]
|
||||
(rx/of (ptk/data-event ::bundle-fetched bundle)
|
||||
(df/load-team-fonts (:team-id project)))))))))
|
||||
(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/take 1)
|
||||
(rx/map (fn [[file-raw users project libraries file-comments-users]]
|
||||
{:file-raw file-raw
|
||||
:users users
|
||||
:project project
|
||||
:libraries libraries
|
||||
: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))))))))))
|
||||
|
||||
|
||||
;; --- Helpers
|
||||
|
|
|
@ -387,6 +387,9 @@
|
|||
(def users
|
||||
(l/derived :users st/state))
|
||||
|
||||
(def current-file-comments-users
|
||||
(l/derived :current-file-comments-users st/state))
|
||||
|
||||
(def viewer-fullscreen?
|
||||
(l/derived (fn [state]
|
||||
(dm/get-in state [:viewer-local :fullscreen?]))
|
||||
|
|
|
@ -345,7 +345,6 @@
|
|||
(mf/defc comment-thread
|
||||
[{:keys [item users on-click] :as props}]
|
||||
(let [owner (get users (:owner-id item))
|
||||
|
||||
on-click*
|
||||
(mf/use-callback
|
||||
(mf/deps item)
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
show-dropdown (mf/use-fn #(reset! show-dropdown? true))
|
||||
hide-dropdown (mf/use-fn #(reset! show-dropdown? false))
|
||||
threads-map (mf/deref refs/comment-threads)
|
||||
users (mf/deref refs/users)
|
||||
users (mf/deref refs/current-file-comments-users)
|
||||
|
||||
tgroups (->> (vals threads-map)
|
||||
(sort-by :modified-at)
|
||||
|
|
|
@ -84,6 +84,5 @@
|
|||
[]
|
||||
(let [modal (mf/deref modal-ref)]
|
||||
(when modal
|
||||
(.log js/console "modal"(clj->js modal))
|
||||
[:& modal-wrapper {:data modal
|
||||
:key (:id modal)}])))
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
:who-comment who-comment
|
||||
:who-inspect who-inspect})
|
||||
|
||||
|
||||
|
||||
(mf/defc share-link-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :share-link}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.share-link]
|
||||
[app.main.ui.static :as static]
|
||||
[app.main.ui.viewer.comments :refer [comments-layer comments-sidebar]]
|
||||
[app.main.ui.viewer.comments :refer [comments-layer comments-sidebar]]
|
||||
[app.main.ui.viewer.handoff :as handoff]
|
||||
[app.main.ui.viewer.header :refer [header]]
|
||||
[app.main.ui.viewer.interactions :as interactions]
|
||||
|
@ -84,7 +84,7 @@
|
|||
|
||||
(when show-comments-list
|
||||
[:& comments-sidebar {:users users :frame frame :page page}])
|
||||
|
||||
|
||||
[:div.viewer-wrapper
|
||||
{:style {:width (:width wrapper-size)
|
||||
:height (:height wrapper-size)}}
|
||||
|
@ -140,7 +140,7 @@
|
|||
:on-click #(when (:close-click-outside overlay)
|
||||
(close-overlay (:frame overlay)))}])
|
||||
[:div.viewport-container.viewer-overlay
|
||||
|
||||
|
||||
{:id (str "overlay-" (-> overlay :frame :id))
|
||||
:style {:width (:width size-over)
|
||||
:height (:height size-over)
|
||||
|
@ -169,6 +169,17 @@
|
|||
(let [{:keys [page-id section index]} params
|
||||
{:keys [file users project permissions]} data
|
||||
|
||||
allowed (or
|
||||
(= section :interactions)
|
||||
(and (= section :comments)
|
||||
(or (:can-edit permissions)
|
||||
(and (true? (:is-logged permissions))
|
||||
(= (:who-comment permissions) "all"))))
|
||||
(and (= section :handoff)
|
||||
(or (:can-edit permissions)
|
||||
(and (true? (:is-logged permissions))
|
||||
(= (:who-inspect permissions) "all")))))
|
||||
|
||||
local (mf/deref refs/viewer-local)
|
||||
|
||||
nav-scroll (:nav-scroll local)
|
||||
|
@ -241,6 +252,9 @@
|
|||
(when (nil? page)
|
||||
(ex/raise :type :not-found))
|
||||
|
||||
(when (not allowed)
|
||||
(st/emit! (dv/go-to-section :interactions)))
|
||||
|
||||
;; Set the page title
|
||||
(mf/use-effect
|
||||
(mf/deps (:name file))
|
||||
|
@ -394,24 +408,23 @@
|
|||
:index index
|
||||
:viewer-pagination viewer-pagination}]
|
||||
|
||||
|
||||
[:& viewer-wrapper
|
||||
{:wrapper-size wrapper-size
|
||||
:scroll scroll
|
||||
:orig-frame orig-frame
|
||||
:orig-viewport-ref orig-viewport-ref
|
||||
:orig-size orig-size
|
||||
:page page
|
||||
:file file
|
||||
:users users
|
||||
:current-viewport-ref current-viewport-ref
|
||||
:size size
|
||||
:frame frame
|
||||
:interactions-mode interactions-mode
|
||||
:overlays overlays
|
||||
:zoom zoom
|
||||
:section section
|
||||
:index index}]))]]]))
|
||||
[:& viewer-wrapper
|
||||
{:wrapper-size wrapper-size
|
||||
:scroll scroll
|
||||
:orig-frame orig-frame
|
||||
:orig-viewport-ref orig-viewport-ref
|
||||
:orig-size orig-size
|
||||
:page page
|
||||
:file file
|
||||
:users users
|
||||
:current-viewport-ref current-viewport-ref
|
||||
:size size
|
||||
:frame frame
|
||||
:interactions-mode interactions-mode
|
||||
:overlays overlays
|
||||
:zoom zoom
|
||||
:section section
|
||||
:index index}]))]]]))
|
||||
|
||||
;; --- Component: Viewer Page
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@
|
|||
[:div.main-icon
|
||||
[:a {:on-click go-to-dashboard
|
||||
;; If the user doesn't have permission we disable the link
|
||||
:style {:pointer-events (when-not permissions "none")}} i/logo-icon]]
|
||||
:style {:pointer-events (when-not (:can-edit permissions) "none")}} i/logo-icon]]
|
||||
|
||||
[:& header-sitemap {:project project :file file :page page :frame frame :index index}]]
|
||||
|
||||
|
@ -199,7 +199,9 @@
|
|||
:alt (tr "viewer.header.interactions-section" (sc/get-tooltip :open-interactions))}
|
||||
i/play]
|
||||
|
||||
(when (:can-edit permissions)
|
||||
(when (or (:can-edit permissions)
|
||||
(and (true? (:is-logged permissions))
|
||||
(= (:who-comment permissions) "all")))
|
||||
[:button.mode-zone-button.tooltip.tooltip-bottom
|
||||
{:on-click #(navigate :comments)
|
||||
:class (dom/classnames :active (= section :comments))
|
||||
|
@ -208,7 +210,8 @@
|
|||
|
||||
(when (or (= (:type permissions) :membership)
|
||||
(and (= (:type permissions) :share-link)
|
||||
(contains? (:flags permissions) :section-handoff)))
|
||||
(true? (:is-logged permissions))
|
||||
(= (:who-inspect permissions) "all")))
|
||||
[:button.mode-zone-button.tooltip.tooltip-bottom
|
||||
{:on-click go-to-handoff
|
||||
:class (dom/classnames :active (= section :handoff))
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
[{:keys [users threads page-id]}]
|
||||
(let [threads-map (mf/deref refs/threads-ref)
|
||||
profile (mf/deref refs/profile)
|
||||
users-refs (mf/deref refs/users)
|
||||
users-refs (mf/deref refs/current-file-comments-users)
|
||||
users (or users users-refs)
|
||||
local (mf/deref refs/comments-local)
|
||||
options? (mf/use-state false)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
pos-y (* (- (:y vbox)) zoom)
|
||||
|
||||
profile (mf/deref refs/profile)
|
||||
users (mf/deref refs/users)
|
||||
users (mf/deref refs/current-file-comments-users)
|
||||
local (mf/deref refs/comments-local)
|
||||
threads-map (mf/deref refs/threads-ref)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue