diff --git a/CHANGES.md b/CHANGES.md index be607ef8a..0bfdb3e46 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj index b8657d010..9b55fb4ca 100644 --- a/backend/src/app/migrations.clj +++ b/backend/src/app/migrations.clj @@ -228,10 +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")} + :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")} ]) diff --git a/backend/src/app/migrations/sql/0075-mod-share-link-table.sql b/backend/src/app/migrations/sql/0075-mod-share-link-table.sql new file mode 100644 index 000000000..326091cda --- /dev/null +++ b/backend/src/app/migrations/sql/0075-mod-share-link-table.sql @@ -0,0 +1,4 @@ +ALTER TABLE share_link + ADD COLUMN who_comment text NOT NULL DEFAULT('team'), + ADD COLUMN who_inspect text NOT NULL DEFAULT('team'), + DROP COLUMN flags; diff --git a/backend/src/app/rpc/mutations/comments.clj b/backend/src/app/rpc/mutations/comments.clj index 438cfdebd..45e75a626 100644 --- a/backend/src/app/rpc/mutations/comments.clj +++ b/backend/src/app/rpc/mutations/comments.clj @@ -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) diff --git a/backend/src/app/rpc/mutations/share_link.clj b/backend/src/app/rpc/mutations/share_link.clj index 6079ecf7d..e9d9efc6c 100644 --- a/backend/src/app/rpc/mutations/share_link.clj +++ b/backend/src/app/rpc/mutations/share_link.clj @@ -19,7 +19,8 @@ (s/def ::id ::us/uuid) (s/def ::profile-id ::us/uuid) (s/def ::file-id ::us/uuid) -(s/def ::flags (s/every ::us/string :kind set?)) +(s/def ::who-comment ::us/string) +(s/def ::who-inspect ::us/string) (s/def ::pages (s/every ::us/uuid :kind set?)) ;; --- Mutation: Create Share Link @@ -27,14 +28,13 @@ (declare create-share-link) (s/def ::create-share-link - (s/keys :req-un [::profile-id ::file-id ::flags] - :opt-un [::pages])) + (s/keys :req-un [::profile-id ::file-id ::who-comment ::who-inspect ::pages])) (sv/defmethod ::create-share-link "Creates a share-link object. - Share links are resources that allows external users access to - specific files with specific permissions (flags)." + Share links are resources that allows external users access to specific + pages of a file with specific permissions (who-comment and who-inspect)." [{:keys [pool] :as cfg} {:keys [profile-id file-id] :as params}] (db/with-atomic [conn pool] @@ -42,19 +42,17 @@ (create-share-link conn params))) (defn create-share-link - [conn {:keys [profile-id file-id pages flags]}] + [conn {:keys [profile-id file-id pages who-comment who-inspect]}] (let [pages (db/create-array conn "uuid" pages) - flags (->> (map name flags) - (db/create-array conn "text")) slink (db/insert! conn :share-link {:id (uuid/next) :file-id file-id - :flags flags + :who-comment who-comment + :who-inspect who-inspect :pages pages :owner-id profile-id})] (-> slink - (update :pages db/decode-pgarray #{}) - (update :flags db/decode-pgarray #{})))) + (update :pages db/decode-pgarray #{})))) ;; --- Mutation: Delete Share Link diff --git a/backend/src/app/rpc/permissions.clj b/backend/src/app/rpc/permissions.clj index 363f967e6..773038253 100644 --- a/backend/src/app/rpc/permissions.clj +++ b/backend/src/app/rpc/permissions.clj @@ -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)." diff --git a/backend/src/app/rpc/queries/comments.clj b/backend/src/app/rpc/queries/comments.clj index 1894022f9..3815ef31c 100644 --- a/backend/src/app/rpc/queries/comments.clj +++ b/backend/src/app/rpc/queries/comments.clj @@ -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])) diff --git a/backend/src/app/rpc/queries/files.clj b/backend/src/app/rpc/queries/files.clj index 946a7902f..9460be08f 100644 --- a/backend/src/app/rpc/queries/files.clj +++ b/backend/src/app/rpc/queries/files.clj @@ -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 diff --git a/backend/src/app/rpc/queries/share_link.clj b/backend/src/app/rpc/queries/share_link.clj index 0bc567364..96ec658c8 100644 --- a/backend/src/app/rpc/queries/share_link.clj +++ b/backend/src/app/rpc/queries/share_link.clj @@ -11,7 +11,6 @@ (defn decode-share-link-row [row] (-> row - (update :flags db/decode-pgarray #{}) (update :pages db/decode-pgarray #{}))) (defn retrieve-share-link diff --git a/backend/src/app/rpc/queries/viewer.clj b/backend/src/app/rpc/queries/viewer.clj index b98de0a38..a82e08e65 100644 --- a/backend/src/app/rpc/queries/viewer.clj +++ b/backend/src/app/rpc/queries/viewer.clj @@ -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))] diff --git a/backend/test/app/services_viewer_test.clj b/backend/test/app/services_viewer_test.clj index 1b9d7c013..e8a01c255 100644 --- a/backend/test/app/services_viewer_test.clj +++ b/backend/test/app/services_viewer_test.clj @@ -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) diff --git a/frontend/resources/styles/main/partials/share-link.scss b/frontend/resources/styles/main/partials/share-link.scss index 1dd9a5415..0a9f4c5bd 100644 --- a/frontend/resources/styles/main/partials/share-link.scss +++ b/frontend/resources/styles/main/partials/share-link.scss @@ -1,139 +1,240 @@ -.share-link-dialog { - width: 475px; - background-color: $color-white; +.share-modal { + display: block; + top: 50px; + left: calc(100vw - 500px); - .modal-footer { - display: flex; - align-items: center; - justify-content: flex-end; - height: unset; - padding: 16px 26px; + .share-link-dialog { + width: 480px; + background-color: $color-white; - .btn-primary, - .btn-secondary, - .btn-warning { - width: 126px; - margin-bottom: 0px; - - &:not(:last-child) { - margin-right: 10px; - } - } - - .confirm-dialog { - display: flex; - flex-direction: column; - background-color: unset; - - .description { - font-size: $fs14; - - margin-bottom: 16px; - } - .actions { + .modal-content { + padding: 16px 32px; + &:first-child { + border-top: 0px; + padding: 0; + height: 50px; display: flex; - justify-content: flex-end; + justify-content: center; } - } - } - - .modal-content { - padding: 26px; - - &:first-child { - border-top: 0px; - } - - .title { - display: flex; - justify-content: space-between; - - h2 { - font-size: $fs18; - color: $color-black; - } - - .modal-close-button { - margin-right: 0px; - } - } - - .share-link-section { - margin-top: 12px; - label { - font-size: $fs12; - color: $color-black; - } - - .hint { - padding-top: 10px; - font-size: $fs14; - color: $color-gray-40; - } - - .help-icon { - cursor: pointer; - } - } - - .view-mode, - .access-mode { - display: flex; - flex-direction: column; .title { - color: $color-black; - font-weight: 400; + display: flex; + justify-content: space-between; + align-items: center; + height: 100%; + margin-left: 32px; + h2 { + font-size: $fs18; + color: $color-black; + } + + .modal-close-button { + margin-right: 16px; + } } - .items { - padding-left: 20px; - display: flex; - - > .input-checkbox, - > .input-radio { + .share-link-section { + .custom-input { display: flex; - user-select: none; - - /* input { */ - /* appearance: checkbox; */ - /* } */ - - label { + flex-direction: row; + margin-bottom: 15px; + border: 1px solid $color-gray-20; + input { + padding: 0 0 0 15px; + border: none; + } + } + .hint-wrapper { + display: flex; + justify-content: space-between; + align-items: center; + .hint { + font-size: $fs12; + color: $color-gray-40; + } + .confirm-dialog { display: flex; - align-items: center; - color: $color-black; + flex-direction: column; + background-color: unset; + .actions { + display: flex; + justify-content: flex-end; + gap: 16px; + } + .description { + font-size: $fs12; + margin-bottom: 16px; + color: $color-black; + } + .btn-primary, + .btn-secondary, + .btn-warning { + width: 126px; + margin-bottom: 0px; - .hint { - margin-left: 5px; + &:not(:last-child) { + margin-right: 10px; + } + } + } + } + + label { + font-size: $fs12; + color: $color-black; + } + + .help-icon { + height: 40px; + width: 40px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + position: relative; + right: 0; + top: 0; + background-color: $color-gray-10; + border-left: 1px solid $color-gray-20; + svg { + fill: $color-gray-30; + } + &:hover { + background-color: $color-primary; + svg { + fill: $color-gray-60; + } + } + } + input { + margin: 0; + } + } + + &.ops-section { + .manage-permissions { + display: flex; + color: $color-primary-dark; + font-size: $fs12; + cursor: pointer; + .icon { + svg { + height: 16px; + width: 16px; + fill: $color-primary-dark; + } + } + .title { + margin-left: 8px; + } + } + .view-mode { + min-height: 34px; + .subtitle { + height: 32px; + } + .row { + display: flex; + justify-content: space-between; + align-items: center; + .count-pages { + font-size: $fs12; color: $color-gray-30; } } - - &.disabled { - label { - color: $color-gray-30; + .current-tag { + font-size: $fs12; + color: $color-gray-30; + } + label { + color: $color-black; + } + } + .access-mode, + .inspect-mode { + display: grid; + grid-template-columns: auto 1fr; + .items { + display: flex; + justify-content: flex-end; + align-items: center; + } + } + .view-mode, + .access-mode, + .inspect-mode { + margin: 8px 0; + .subtitle { + display: flex; + justify-content: flex-start; + align-items: center; + color: $color-black; + font-size: $fs16; + .icon { + display: flex; + justify-content: center; + align-items: center; + margin-right: 10px; + svg { + height: 16px; + width: 16px; + } } } + .items { + .input-select { + background-image: url("/images/icons/arrow-down.svg"); + margin: 0; + padding-right: 28px; + border: 1px solid $color-gray-10; + max-width: 227px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + > .input-radio { + display: flex; + user-select: none; + margin-top: 0; + margin-bottom: 0; + label { + display: flex; + align-items: center; + color: $color-black; + max-width: 115px; + + &::before { + height: 16px; + width: 16px; + } + .hint { + margin-left: 5px; + color: $color-gray-30; + } + } + + &.disabled { + label { + color: $color-gray-30; + } + } + } + } + } + + .pages-selection { + border-top: 1px solid $color-gray-10; + border-bottom: 1px solid $color-gray-10; + padding-left: 20px; + max-height: 200px; + overflow-y: scroll; + user-select: none; + + label { + color: $color-black; + } } } } - - .pages-selection { - padding-left: 20px; - max-height: 200px; - overflow-y: scroll; - user-select: none; - - label { - color: $color-black; - } - } - - .custom-input { - input { - padding: 0 40px 0 15px; - } - } } } diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs index 3dd8741c0..8d749e5f3 100644 --- a/frontend/src/app/main/data/comments.cljs +++ b/frontend/src/app/main/data/comments.cljs @@ -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." diff --git a/frontend/src/app/main/data/users.cljs b/frontend/src/app/main/data/users.cljs index 275c4b194..7ea945437 100644 --- a/frontend/src/app/main/data/users.cljs +++ b/frontend/src/app/main/data/users.cljs @@ -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 diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index 98f576c94..54c042222 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -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)))))) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 7885fbc92..d146c13e7 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -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 [_ _ _] diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index d01df8f38..7b81dc8cd 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -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 diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index 3e709aea1..81d51b461 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -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?])) diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index a7019d362..5aa993a27 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -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) diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs index 582ea47ac..11d3ef701 100644 --- a/frontend/src/app/main/ui/dashboard/comments.cljs +++ b/frontend/src/app/main/ui/dashboard/comments.cljs @@ -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) diff --git a/frontend/src/app/main/ui/share_link.cljs b/frontend/src/app/main/ui/share_link.cljs index 52438b3de..490cb2f96 100644 --- a/frontend/src/app/main/ui/share_link.cljs +++ b/frontend/src/app/main/ui/share_link.cljs @@ -24,53 +24,66 @@ (log/set-level! :warn) (defn prepare-params - [{:keys [sections pages pages-mode]}] - {:pages pages - :flags (-> #{} - (into (map #(str "section-" %)) sections) - (into (map #(str "pages-" %)) [pages-mode]))}) + [{:keys [pages who-comment who-inspect]}] + + {:pages pages + :who-comment who-comment + :who-inspect who-inspect}) (mf/defc share-link-dialog {::mf/register modal/components ::mf/register-as :share-link} [{:keys [file page]}] - (let [slinks (mf/deref refs/share-links) - router (mf/deref refs/router) - route (mf/deref refs/route) + (let [current-page page + slinks (mf/deref refs/share-links) + router (mf/deref refs/router) + route (mf/deref refs/route) - link (mf/use-state nil) - confirm (mf/use-state false) + link (mf/use-state nil) + confirm (mf/use-state false) + open-ops (mf/use-state false) + + opts (mf/use-state + {:pages-mode "current" + :all-pages false + :pages #{(:id page)} + :who-comment "team" + :who-inspect "team"}) - opts (mf/use-state - {:sections #{"viewer"} - :pages-mode "current" - :pages #{(:id page)}}) close (fn [event] (dom/prevent-default event) - (st/emit! (modal/hide))) + (st/emit! (modal/hide)) + (modal/disallow-click-outside!)) - select-pages-mode - (fn [mode] + toggle-all + (fn [] (reset! confirm false) (swap! opts (fn [state] - (-> state - (assoc :pages-mode mode) - (cond-> (= mode "current") (assoc :pages #{(:id page)})) - (cond-> (= mode "all") (assoc :pages (into #{} (get-in file [:data :pages])))))))) + (if (= true (:all-pages state)) + (-> state + (assoc :all-pages false) + (assoc :pages #{(:id page)})) + (-> state + (assoc :all-pages true) + (assoc :pages (into #{} (get-in file [:data :pages])))))))) mark-checked-page (fn [event id] (let [target (dom/get-target event) - checked? (.-checked ^js target)] - (reset! confirm false) - (swap! opts update :pages - (fn [pages] - (if checked? - (conj pages id) - (disj pages id)))))) + checked? (.-checked ^js target) + dif-pages? (not= id (first (:pages @opts))) + no-one-page (< 1 (count (:pages @opts))) + should-change (or no-one-page dif-pages?)] + (when should-change + (reset! confirm false) + (swap! opts update :pages + (fn [pages] + (if checked? + (conj pages id) + (disj pages id))))))) create-link (fn [_] @@ -83,7 +96,7 @@ (wapi/write-to-clipboard @link) (st/emit! (dm/show {:type :info :content (tr "common.share-link.link-copied-success") - :timeout 3000}))) + :timeout 1000}))) try-delete-link (fn [_] @@ -94,17 +107,27 @@ (let [params (prepare-params @opts) slink (d/seek #(= (:flags %) (:flags params)) slinks)] (reset! confirm false) - (st/emit! (dc/delete-share-link slink) - (dm/show {:type :info - :content (tr "common.share-link.link-deleted-success") - :timeout 3000})))) - ] + (st/emit! (dc/delete-share-link slink)))) + + manage-open-ops + (fn [_] + (swap! open-ops not)) + + on-who-change + (fn [type event] + (let [target (dom/get-target event) + value (dom/get-value target) + value (keyword value)] + (reset! confirm false) + (if (= type :comment) + (swap! opts assoc :who-comment (d/name value)) + (swap! opts assoc :who-inspect (d/name value)))))] (mf/use-effect (mf/deps file slinks @opts) (fn [] - (let [{:keys [flags pages] :as params} (prepare-params @opts) - slink (d/seek #(and (= (:flags %) flags) (= (:pages %) pages)) slinks) + (let [{:keys [pages who-comment who-inspect] :as params} (prepare-params @opts) + slink (d/seek #(and (= (:who-inspect %) who-inspect) (= (:who-comment %) who-comment) (= (:pages %) pages)) slinks) href (when slink (let [pparams (:path-params route) qparams (-> (:query-params route) @@ -114,123 +137,123 @@ (assoc cf/public-uri :fragment href)))] (reset! link (some-> href str))))) - [:div.modal-overlay + [:div.modal-overlay.share-modal [:div.modal-container.share-link-dialog - [:div.modal-content + [:div.modal-content.initial [:div.title [:h2 (tr "common.share-link.title")] [:div.modal-close-button {:on-click close :title (tr "labels.close")} - i/close]] - - [:div.share-link-section - [:label (tr "labels.link")] - [:div.custom-input.with-icon - [:input {:type "text" - :value (or @link "") - :placeholder (tr "common.share-link.placeholder") - :read-only true}] - (when (some? @link) - [:div.help-icon {:title (tr "labels.copy") - :on-click copy-link} - i/copy])] - - [:div.hint (tr "common.share-link.permissions-hint")]]] - + i/close]]] [:div.modal-content - (let [sections (:sections @opts)] - [:div.access-mode - [:div.title (tr "common.share-link.permissions-can-access")] - [:div.items - [:div.input-checkbox.check-primary.disabled - [:input.check-primary.input-checkbox {:type "checkbox" :disabled true}] - [:label (tr "labels.workspace")]] + [:div.share-link-section + (when (and (not @confirm) (some? @link)) + [:div.custom-input.with-icon + [:input {:type "text" + :value (or @link "") + :placeholder (tr "common.share-link.placeholder") + :read-only true}] + [:div.help-icon {:title (tr "viewer.header.share.copy-link") + :on-click copy-link} + i/copy]]) + [:div.hint-wrapper + (when (not @confirm) [:div.hint (tr "common.share-link.permissions-hint")]) + (cond + (true? @confirm) + [:div.confirm-dialog + [:div.description (tr "common.share-link.confirm-deletion-link-description")] + [:div.actions + [:input.btn-secondary + {:type "button" + :on-click #(reset! confirm false) + :value (tr "labels.cancel")}] + [:input.btn-warning + {:type "button" + :on-click delete-link + :value (tr "common.share-link.destroy-link")}]]] - [:div.input-checkbox.check-primary - [:input {:type "checkbox" - :default-checked (contains? sections "viewer")}] - [:label (tr "labels.viewer") - [:span.hint "(" (tr "labels.default") ")"]]] - - ;; [:div.input-checkbox.check-primary - ;; [:input.check-primary.input-checkbox {:type "checkbox"}] - ;; [:label "Handoff" ]] - ]]) - - (let [mode (:pages-mode @opts)] - [:* - [:div.view-mode - [:div.title (tr "common.share-link.permissions-can-view")] - [:div.items - [:div.input-radio.radio-primary - [:input {:type "radio" - :id "view-all" - :checked (= "all" mode) - :name "pages-mode" - :on-change #(select-pages-mode "all")}] - [:label {:for "view-all"} (tr "common.share-link.view-all-pages")]] - - [:div.input-radio.radio-primary - [:input {:type "radio" - :id "view-current" - :name "pages-mode" - :checked (= "current" mode) - :on-change #(select-pages-mode "current")}] - [:label {:for "view-current"} (tr "common.share-link.view-current-page")]] - - [:div.input-radio.radio-primary - [:input {:type "radio" - :id "view-selected" - :name "pages-mode" - :checked (= "selected" mode) - :on-change #(select-pages-mode "selected")}] - [:label {:for "view-selected"} (tr "common.share-link.view-selected-pages")]]]] - - (when (= "selected" mode) - (let [pages (->> (get-in file [:data :pages]) - (map #(get-in file [:data :pages-index %]))) - selected (:pages @opts)] - [:ul.pages-selection - (for [page pages] - [:li.input-checkbox.check-primary {:key (str (:id page))} - [:input {:type "checkbox" - :id (str "page-" (:id page)) - :on-change #(mark-checked-page % (:id page)) - :checked (contains? selected (:id page))}] - [:label {:for (str "page-" (:id page))} (:name page)]])]))])] - - [:div.modal-footer - (cond - (true? @confirm) - [:div.confirm-dialog - [:div.description (tr "common.share-link.confirm-deletion-link-description")] - [:div.actions + (some? @link) [:input.btn-secondary {:type "button" - :on-click #(reset! confirm false) - :value (tr "labels.cancel")}] - [:input.btn-warning + :class "primary" + :on-click try-delete-link + :value (tr "common.share-link.destroy-link")}] + + :else + [:input.btn-primary {:type "button" - :on-click delete-link - :value (tr "common.share-link.remove-link") - }]]] + :class "primary" + :on-click create-link + :value (tr "common.share-link.get-link")}])]]] + [:div.modal-content.ops-section + [:div.manage-permissions + {:on-click manage-open-ops} + [:span.icon i/picker-hsv] + [:div.title (tr "common.share-link.manage-ops")]] + (when @open-ops + [:* + (let [all-selected? (:all-pages @opts) + pages (->> (get-in file [:data :pages]) + (map #(get-in file [:data :pages-index %]))) + selected (:pages @opts)] - (some? @link) - [:input.btn-secondary - {:type "button" - :class "primary" - :on-click try-delete-link - :value (tr "common.share-link.remove-link")}] + [:* + [:div.view-mode + [:div.subtitle + [:span.icon i/play] + (tr "common.share-link.permissions-pages")] + [:div.items + (if (= 1 (count pages)) + [:div.input-checkbox.check-primary + [:input {:type "checkbox" + :id (str "page-" (:id current-page)) + :on-change #(mark-checked-page % (:id current-page)) + :checked true}] + [:label {:for (str "page-" (:id current-page))} (:name current-page)] + [:span (str " " (tr "common.share-link.current-tag"))]] - :else - [:input.btn-primary - {:type "button" - :class "primary" - :on-click create-link - :value (tr "common.share-link.get-link")}])] + [:* + [:div.row + [:div.input-checkbox.check-primary + [:input {:type "checkbox" + :id "view-all" + :checked all-selected? + :name "pages-mode" + :on-change toggle-all}] + [:label {:for "view-all"} (tr "common.share-link.view-all")]] + [:span.count-pages (tr "common.share-link.page-shared" (i18n/c (count selected)))]] - ]])) + [:ul.pages-selection + (for [page pages] + [:li.input-checkbox.check-primary {:key (str (:id page))} + [:input {:type "checkbox" + :id (str "page-" (:id page)) + :on-change #(mark-checked-page % (:id page)) + :checked (contains? selected (:id page))}] + (if (= (:id current-page) (:id page)) + [:* + [:label {:for (str "page-" (:id page))} (:name page)] + [:span.current-tag (str " " (tr "common.share-link.current-tag"))]] + [:label {:for (str "page-" (:id page))} (:name page)])])]])]]]) + [:div.access-mode + [:div.subtitle + [:span.icon i/chat] + (tr "common.share-link.permissions-can-comment")] + [:div.items + [:select.input-select {:on-change (partial on-who-change :comment) + :value (:who-comment @opts)} + [:option {:value "team"} (tr "common.share-link.team-members")] + [:option {:value "all"} (tr "common.share-link.all-users")]]]] + [:div.inspect-mode + [:div.subtitle + [:span.icon i/code] + (tr "common.share-link.permissions-can-inspect")] + [:div.items + [:select.input-select {:on-change (partial on-who-change :inspect) + :value (:who-inspect @opts)} + [:option {:value "team"} (tr "common.share-link.team-members")] + [:option {:value "all"} (tr "common.share-link.all-users")]]]]])]]])) diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index 7849c7bc4..6ccbc169c 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -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 diff --git a/frontend/src/app/main/ui/viewer/header.cljs b/frontend/src/app/main/ui/viewer/header.cljs index c777ad9d5..5cde91686 100644 --- a/frontend/src/app/main/ui/viewer/header.cljs +++ b/frontend/src/app/main/ui/viewer/header.cljs @@ -77,7 +77,8 @@ (mf/use-callback (mf/deps page) (fn [] - (modal/show! :share-link {:page page :file file})))] + (modal/show! :share-link {:page page :file file}) + (modal/allow-click-outside!)))] [:div.options-zone (case section @@ -187,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}]] @@ -198,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)) @@ -207,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)) diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index 3963cf933..e66781a01 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -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) diff --git a/frontend/src/app/main/ui/workspace/viewport/comments.cljs b/frontend/src/app/main/ui/workspace/viewport/comments.cljs index da82aeaf9..f13a88cfc 100644 --- a/frontend/src/app/main/ui/workspace/viewport/comments.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/comments.cljs @@ -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) diff --git a/frontend/translations/ca.po b/frontend/translations/ca.po index 2d0eff142..bd43175e7 100644 --- a/frontend/translations/ca.po +++ b/frontend/translations/ca.po @@ -185,33 +185,15 @@ msgstr "S'ha copiat l'enllaç correctament" msgid "common.share-link.link-deleted-success" msgstr "S'ha eliminat l'enllaç correctament" -msgid "common.share-link.permissions-can-access" -msgstr "Pot accedir" - -msgid "common.share-link.permissions-can-view" -msgstr "Lector" - msgid "common.share-link.permissions-hint" msgstr "Qualsevol persona amb l'enllaç hi tindrà accés" msgid "common.share-link.placeholder" msgstr "L'enllaç per a compartir apareixerà aquí" -msgid "common.share-link.remove-link" -msgstr "Elimina l'enllaç" - msgid "common.share-link.title" msgstr "Compartiu prototips" -msgid "common.share-link.view-all-pages" -msgstr "Totes les pàgines" - -msgid "common.share-link.view-current-page" -msgstr "Només aquesta pàgina" - -msgid "common.share-link.view-selected-pages" -msgstr "Pàgines seleccionades" - #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" msgstr "Afegeix a la biblioteca compartida" diff --git a/frontend/translations/de.po b/frontend/translations/de.po index b6486cbd6..1884b139f 100644 --- a/frontend/translations/de.po +++ b/frontend/translations/de.po @@ -188,33 +188,15 @@ msgstr "Link wurde erfolgreich kopiert" msgid "common.share-link.link-deleted-success" msgstr "Link wurde erfolgreich gelöscht" -msgid "common.share-link.permissions-can-access" -msgstr "Freigabe für" - -msgid "common.share-link.permissions-can-view" -msgstr "Sichtbar" - msgid "common.share-link.permissions-hint" msgstr "Jeder mit dem Link kann auf die Datei zugreifen" msgid "common.share-link.placeholder" msgstr "Link zum Teilen wird hier erscheinen" -msgid "common.share-link.remove-link" -msgstr "Link entfernen" - msgid "common.share-link.title" msgstr "Prototypen teilen" -msgid "common.share-link.view-all-pages" -msgstr "Alle Seiten" - -msgid "common.share-link.view-current-page" -msgstr "Nur diese Seite" - -msgid "common.share-link.view-selected-pages" -msgstr "Ausgewählte Seiten" - #: src/app/main/ui/workspace/header.cljs, #: src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 10d2f675d..e82f1e73c 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -183,11 +183,14 @@ msgstr "Link copied successfully" msgid "common.share-link.link-deleted-success" msgstr "Link deleted successfully" -msgid "common.share-link.permissions-can-access" -msgstr "Can access" +msgid "common.share-link.permissions-can-comment" +msgstr "Can comment" -msgid "common.share-link.permissions-can-view" -msgstr "Can view" +msgid "common.share-link.permissions-can-inspect" +msgstr "Can inspect code" + +msgid "common.share-link.permissions-pages" +msgstr "Pages shared" msgid "common.share-link.permissions-hint" msgstr "Anyone with link will have access" @@ -195,20 +198,31 @@ msgstr "Anyone with link will have access" msgid "common.share-link.placeholder" msgstr "Shareable link will appear here" -msgid "common.share-link.remove-link" -msgstr "Remove link" +msgid "common.share-link.destroy-link" +msgstr "Destroy link" msgid "common.share-link.title" msgstr "Share prototypes" -msgid "common.share-link.view-all-pages" -msgstr "All pages" +msgid "common.share-link.view-all" +msgstr "Select All" -msgid "common.share-link.view-current-page" -msgstr "Only this page" +msgid "common.share-link.current-tag" +msgstr "(current)" -msgid "common.share-link.view-selected-pages" -msgstr "Selected pages" +msgid "common.share-link.manage-ops" +msgstr "Manage permissions" + +msgid "common.share-link.team-members" +msgstr "Only team members" + +msgid "common.share-link.all-users" +msgstr "All Penpot users" + +msgid "common.share-link.page-shared" +msgid_plural "common.share-link.page-shared" +msgstr[0] "1 page shared" +msgstr[1] "%s pages shared" #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index 9315aad56..a42cf3619 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -188,11 +188,14 @@ msgstr "Enlace copiado satisfactoriamente" msgid "common.share-link.link-deleted-success" msgstr "Enlace eliminado correctamente" -msgid "common.share-link.permissions-can-access" -msgstr "Puede acceder a" +msgid "common.share-link.permissions-can-comment" +msgstr "Pueden comentar" -msgid "common.share-link.permissions-can-view" -msgstr "Puede ver" +msgid "common.share-link.permissions-can-inspect" +msgstr "Pueden ver código" + +msgid "common.share-link.permissions-pages" +msgstr "Páginas compartidas" msgid "common.share-link.permissions-hint" msgstr "Cualquiera con el enlace puede acceder" @@ -200,20 +203,31 @@ msgstr "Cualquiera con el enlace puede acceder" msgid "common.share-link.placeholder" msgstr "El enlace para compartir aparecerá aquí" -msgid "common.share-link.remove-link" +msgid "common.share-link.destroy-link" msgstr "Eliminar enlace" msgid "common.share-link.title" msgstr "Compartir prototipos" -msgid "common.share-link.view-all-pages" -msgstr "Todas las paginas" +msgid "common.share-link.view-all" +msgstr "Selecctionar todas" -msgid "common.share-link.view-current-page" -msgstr "Solo esta pagina" +msgid "common.share-link.current-tag" +msgstr "(actual)" -msgid "common.share-link.view-selected-pages" -msgstr "Paginas seleccionadas" +msgid "common.share-link.manage-ops" +msgstr "Gestionar permisos" + +msgid "common.share-link.team-members" +msgstr "Sólo integrantes del equipo" + +msgid "common.share-link.all-users" +msgstr "Todo usario de Penpot" + +msgid "common.share-link.page-shared" +msgid_plural "common.share-link.page-shared" +msgstr[0] "1 página compartida" +msgstr[1] "%s páginas compartidas" #: src/app/main/ui/workspace/header.cljs, #: src/app/main/ui/dashboard/file_menu.cljs diff --git a/frontend/translations/fa.po b/frontend/translations/fa.po index 597fada27..21aaf336b 100644 --- a/frontend/translations/fa.po +++ b/frontend/translations/fa.po @@ -189,30 +189,12 @@ msgstr "لینک با موفقیت کپی شد" msgid "common.share-link.link-deleted-success" msgstr "لینک با موفقیت حذف شد" -msgid "common.share-link.permissions-can-access" -msgstr "می‌تواند دسترسی داشته باشد" - -msgid "common.share-link.permissions-can-view" -msgstr "می‌تواند مشاهده کند" - msgid "common.share-link.permissions-hint" msgstr "هر کسی که لینک داشته باشد دسترسی خواهد داشت" -msgid "common.share-link.remove-link" -msgstr "حذف لینک" - msgid "common.share-link.title" msgstr "اشتراک‌گذاری پروتوتایپ‌ها" -msgid "common.share-link.view-all-pages" -msgstr "تمام صفحات" - -msgid "common.share-link.view-current-page" -msgstr "فقط این صفحه" - -msgid "common.share-link.view-selected-pages" -msgstr "صفحات انتخاب‌شده" - #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" msgstr "افزودن به‌عنوان کتابخانه مشترک" diff --git a/frontend/translations/fr.po b/frontend/translations/fr.po index 72a3fc1bc..a7fc116dc 100644 --- a/frontend/translations/fr.po +++ b/frontend/translations/fr.po @@ -186,33 +186,15 @@ msgstr "Lien copié avec succès" msgid "common.share-link.link-deleted-success" msgstr "Lien supprimé avec succès" -msgid "common.share-link.permissions-can-access" -msgstr "Peut y accéder" - -msgid "common.share-link.permissions-can-view" -msgstr "Peut le visionner" - msgid "common.share-link.permissions-hint" msgstr "N'importe qui possédant ce lien peut y accéder" msgid "common.share-link.placeholder" msgstr "Le lien à partager apparaîtra ici" -msgid "common.share-link.remove-link" -msgstr "Supprimer le lien" - msgid "common.share-link.title" msgstr "Partager les prototypes" -msgid "common.share-link.view-all-pages" -msgstr "Toutes les pages" - -msgid "common.share-link.view-current-page" -msgstr "Seulement cette page" - -msgid "common.share-link.view-selected-pages" -msgstr "Pages sélectionnées" - #: src/app/main/ui/workspace/header.cljs, #: src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" diff --git a/frontend/translations/he.po b/frontend/translations/he.po index 7129f0cd2..64417c503 100644 --- a/frontend/translations/he.po +++ b/frontend/translations/he.po @@ -179,33 +179,15 @@ msgstr "הקישור הועתק בהצלחה" msgid "common.share-link.link-deleted-success" msgstr "הקישור נמחק בהצלחה" -msgid "common.share-link.permissions-can-access" -msgstr "יש גישה" - -msgid "common.share-link.permissions-can-view" -msgstr "אפשר לצפות" - msgid "common.share-link.permissions-hint" msgstr "כל מי שיש לו את הקישור יכול לגשת" msgid "common.share-link.placeholder" msgstr "הקישור לשיתוף יופיע כאן" -msgid "common.share-link.remove-link" -msgstr "הסרת קישור" - msgid "common.share-link.title" msgstr "שיתוף אבות טיפוס" -msgid "common.share-link.view-all-pages" -msgstr "כל העמודים" - -msgid "common.share-link.view-current-page" -msgstr "רק העמוד הזה" - -msgid "common.share-link.view-selected-pages" -msgstr "עמודים נבחרים" - #: src/app/main/ui/workspace/header.cljs, #: src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" diff --git a/frontend/translations/id.po b/frontend/translations/id.po index adc798da5..035806315 100644 --- a/frontend/translations/id.po +++ b/frontend/translations/id.po @@ -189,20 +189,10 @@ msgstr "Tautan berhasil disalin" msgid "common.share-link.link-deleted-success" msgstr "Tautan berhasil dihapus" -msgid "common.share-link.permissions-can-access" -msgstr "Dapat mengakses" - -msgid "common.share-link.permissions-can-view" -msgstr "Dapat melihat" msgid "common.share-link.permissions-hint" msgstr "Siapapun yang memiliki tautan dapat mengakses" -msgid "common.share-link.view-current-page" -msgstr "Hanya halaman ini" - -msgid "common.share-link.view-selected-pages" -msgstr "Halaman yang dipilih" #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" diff --git a/frontend/translations/lt.po b/frontend/translations/lt.po index 016e16ab9..8638740d8 100644 --- a/frontend/translations/lt.po +++ b/frontend/translations/lt.po @@ -188,33 +188,15 @@ msgstr "Nuoroda sėkmingai nukopijuota" msgid "common.share-link.link-deleted-success" msgstr "Nuoroda sėkmingai ištrinta" -msgid "common.share-link.permissions-can-access" -msgstr "Gali pasiekti" - -msgid "common.share-link.permissions-can-view" -msgstr "Galima peržiūrėti" - msgid "common.share-link.permissions-hint" msgstr "Kiekvienas, turintis nuorodą, turės prieigą" msgid "common.share-link.placeholder" msgstr "Bendrinama nuoroda bus rodoma čia" -msgid "common.share-link.remove-link" -msgstr "Pašalinti nuorodą" - msgid "common.share-link.title" msgstr "Dalinkitės prototipais" -msgid "common.share-link.view-all-pages" -msgstr "Visi puslapiai" - -msgid "common.share-link.view-current-page" -msgstr "Tik šis puslapis" - -msgid "common.share-link.view-selected-pages" -msgstr "Parinkti puslapiai" - #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" msgstr "Pridėti kaip bendrinamą biblioteką" diff --git a/frontend/translations/ml.po b/frontend/translations/ml.po index 80e721682..71beaaa81 100644 --- a/frontend/translations/ml.po +++ b/frontend/translations/ml.po @@ -189,33 +189,15 @@ msgstr "കണ്ണി വിജയകരമായി പകർത്തി" msgid "common.share-link.link-deleted-success" msgstr "കണ്ണി വിജയകരമായി മായിച്ചു" -msgid "common.share-link.permissions-can-access" -msgstr "പ്രാപ്യമാണ്" - -msgid "common.share-link.permissions-can-view" -msgstr "കാണാവുന്നതാണ്" - msgid "common.share-link.permissions-hint" msgstr "കണ്ണിയുള്ള ആർക്കും പ്രാപ്യമാകും" msgid "common.share-link.placeholder" msgstr "പങ്കുവെക്കാവുന്ന കണ്ണി ഇവിടെ ലഭ്യമാകും" -msgid "common.share-link.remove-link" -msgstr "കണ്ണി നീക്കുക" - msgid "common.share-link.title" msgstr "പ്രോട്ടോടൈപ്പുകൾ പങ്കുവെയ്ക്കുക" -msgid "common.share-link.view-all-pages" -msgstr "എല്ലാ താളുകളും" - -msgid "common.share-link.view-current-page" -msgstr "ഈ താൾ മാത്രം" - -msgid "common.share-link.view-selected-pages" -msgstr "തിരഞ്ഞെടുത്ത താളുകൾ" - #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" msgstr "പങ്കിട്ട ലൈബ്രറിയായി ചേർക്കുക" diff --git a/frontend/translations/pl.po b/frontend/translations/pl.po index 70a4ed379..0e11e03a7 100644 --- a/frontend/translations/pl.po +++ b/frontend/translations/pl.po @@ -186,33 +186,15 @@ msgstr "Link skopiowano pomyślnie" msgid "common.share-link.link-deleted-success" msgstr "Link usunięto pomyślnie" -msgid "common.share-link.permissions-can-access" -msgstr "Można uzyskać dostęp" - -msgid "common.share-link.permissions-can-view" -msgstr "Można zobaczyć" - msgid "common.share-link.permissions-hint" msgstr "Każdy, kto ma link, będzie miał dostęp" msgid "common.share-link.placeholder" msgstr "Tutaj pojawi się link do udostępniania" -msgid "common.share-link.remove-link" -msgstr "Usuń link" - msgid "common.share-link.title" msgstr "Udostępnij prototypy" -msgid "common.share-link.view-all-pages" -msgstr "Wszystkie strony" - -msgid "common.share-link.view-current-page" -msgstr "Tylko ta strona" - -msgid "common.share-link.view-selected-pages" -msgstr "Wybrane strony" - #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" msgstr "Dodaj jako Udostępnioną Bibliotekę" diff --git a/frontend/translations/ru.po b/frontend/translations/ru.po index 50cd08e0a..8dbd53626 100644 --- a/frontend/translations/ru.po +++ b/frontend/translations/ru.po @@ -186,35 +186,16 @@ msgstr "Ссылка скопирована" msgid "common.share-link.link-deleted-success" msgstr "Ссылка удалена" -#, fuzzy -msgid "common.share-link.permissions-can-access" -msgstr "Могут зайти" - -msgid "common.share-link.permissions-can-view" -msgstr "Могут видеть" - msgid "common.share-link.permissions-hint" msgstr "Доступ открыт для получателей ссылки" msgid "common.share-link.placeholder" msgstr "Ссылка появится здесь" -msgid "common.share-link.remove-link" -msgstr "Удалить ссылку" - #, fuzzy msgid "common.share-link.title" msgstr "Поделиться прототипами" -msgid "common.share-link.view-all-pages" -msgstr "Все страницы" - -msgid "common.share-link.view-current-page" -msgstr "Только эту страницу" - -msgid "common.share-link.view-selected-pages" -msgstr "Выбранные страницы" - #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" msgstr "Добавить как общую библиотеку" diff --git a/frontend/translations/tr.po b/frontend/translations/tr.po index 130cf57b6..f92cf5004 100644 --- a/frontend/translations/tr.po +++ b/frontend/translations/tr.po @@ -186,33 +186,15 @@ msgstr "Bağlantı başarıyla kopyalandı" msgid "common.share-link.link-deleted-success" msgstr "Bağlantı başarıyla silindi" -msgid "common.share-link.permissions-can-access" -msgstr "Erişebilir" - -msgid "common.share-link.permissions-can-view" -msgstr "Görüntüleyebilir" - msgid "common.share-link.permissions-hint" msgstr "Bağlantıya sahip olan herkes erişebilir" msgid "common.share-link.placeholder" msgstr "Paylaşılabilir bağlantı burada görünecek" -msgid "common.share-link.remove-link" -msgstr "Bağlantıyı kaldır" - msgid "common.share-link.title" msgstr "Prototipleri paylaş" -msgid "common.share-link.view-all-pages" -msgstr "Tüm sayfalar" - -msgid "common.share-link.view-current-page" -msgstr "Yalnızca bu sayfa" - -msgid "common.share-link.view-selected-pages" -msgstr "Seçili sayfalar" - #: src/app/main/ui/workspace/header.cljs, #: src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" diff --git a/frontend/translations/zh_CN.po b/frontend/translations/zh_CN.po index d6b44316a..76baa1a9b 100644 --- a/frontend/translations/zh_CN.po +++ b/frontend/translations/zh_CN.po @@ -177,13 +177,6 @@ msgstr "链接已复制" msgid "common.share-link.link-deleted-success" msgstr "链接已移除" -#, fuzzy -msgid "common.share-link.permissions-can-access" -msgstr "可访问" - -msgid "common.share-link.permissions-can-view" -msgstr "可浏览" - #, fuzzy msgid "common.share-link.permissions-hint" msgstr "任何人通过此链接都可访问" @@ -191,21 +184,9 @@ msgstr "任何人通过此链接都可访问" msgid "common.share-link.placeholder" msgstr "可分享的链接会在此处显示" -msgid "common.share-link.remove-link" -msgstr "移除链接" - msgid "common.share-link.title" msgstr "分享原型" -msgid "common.share-link.view-all-pages" -msgstr "全部页面" - -msgid "common.share-link.view-current-page" -msgstr "仅此页面" - -msgid "common.share-link.view-selected-pages" -msgstr "选中的页面" - #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs msgid "dashboard.add-shared" msgstr "添加为共享库" diff --git a/frontend/translations/zh_Hant.po b/frontend/translations/zh_Hant.po index eade57f69..104ee5422 100644 --- a/frontend/translations/zh_Hant.po +++ b/frontend/translations/zh_Hant.po @@ -181,33 +181,15 @@ msgstr "成功複製連結" msgid "common.share-link.link-deleted-success" msgstr "成功刪除連結" -msgid "common.share-link.permissions-can-access" -msgstr "能夠存取" - -msgid "common.share-link.permissions-can-view" -msgstr "能夠檢視" - msgid "common.share-link.permissions-hint" msgstr "任何有連結的人皆能存取" msgid "common.share-link.placeholder" msgstr "可分享的連結將會在此顯示" -msgid "common.share-link.remove-link" -msgstr "移除連結" - msgid "common.share-link.title" msgstr "分享原型" -msgid "common.share-link.view-all-pages" -msgstr "所有頁面" - -msgid "common.share-link.view-current-page" -msgstr "僅此頁面" - -msgid "common.share-link.view-selected-pages" -msgstr "選擇的頁面" - #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs #, fuzzy msgid "dashboard.add-shared"