diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj
index 0936f6c5e..6c9ebdba2 100644
--- a/backend/src/app/migrations.clj
+++ b/backend/src/app/migrations.clj
@@ -113,6 +113,9 @@
{:name "0032-del-unused-tables"
:fn (mg/resource "app/migrations/sql/0032-del-unused-tables.sql")}
+
+ {:name "0033-mod-comment-thread-table"
+ :fn (mg/resource "app/migrations/sql/0033-mod-comment-thread-table.sql")}
]})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/backend/src/app/migrations/sql/0033-mod-comment-thread-table.sql b/backend/src/app/migrations/sql/0033-mod-comment-thread-table.sql
new file mode 100644
index 000000000..0e98ef6d1
--- /dev/null
+++ b/backend/src/app/migrations/sql/0033-mod-comment-thread-table.sql
@@ -0,0 +1,2 @@
+ALTER TABLE comment_thread
+ ADD COLUMN page_name text NULL;
diff --git a/backend/src/app/services/mutations/comments.clj b/backend/src/app/services/mutations/comments.clj
index af798bb07..8fd4ce4f7 100644
--- a/backend/src/app/services/mutations/comments.clj
+++ b/backend/src/app/services/mutations/comments.clj
@@ -29,12 +29,13 @@
(declare upsert-comment-thread-status!)
(declare create-comment-thread)
+(declare retrieve-page-name)
+(s/def ::page-id ::us/uuid)
(s/def ::file-id ::us/uuid)
(s/def ::profile-id ::us/uuid)
(s/def ::position ::us/point)
(s/def ::content ::us/string)
-(s/def ::page-id ::us/uuid)
(s/def ::create-comment-thread
(s/keys :req-un [::profile-id ::file-id ::position ::content ::page-id]))
@@ -53,13 +54,14 @@
(defn- create-comment-thread*
[conn {:keys [profile-id file-id page-id position content] :as params}]
- (let [seqn (retrieve-next-seqn conn file-id)
- now (dt/now)
-
+ (let [seqn (retrieve-next-seqn conn file-id)
+ now (dt/now)
+ pname (retrieve-page-name conn params)
thread (db/insert! conn :comment-thread
{:file-id file-id
:owner-id profile-id
:participants (db/tjson #{profile-id})
+ :page-name pname
:page-id page-id
:created-at now
:modified-at now
@@ -81,10 +83,7 @@
{:comment-thread-seqn seqn}
{:id file-id})
- (-> (assoc thread
- :content content
- :comment comment)
- (comments/decode-row))))
+ (select-keys thread [:id :file-id :page-id])))
(defn- create-comment-thread
[conn params]
@@ -104,6 +103,12 @@
:else res))))
+(defn- retrieve-page-name
+ [conn {:keys [file-id page-id]}]
+ (let [{:keys [data]} (db/get-by-id conn :file file-id)
+ data (blob/decode data)]
+ (get-in data [:pages-index page-id :name])))
+
;; --- Mutation: Update Comment Thread Status
@@ -164,14 +169,21 @@
[{:keys [profile-id thread-id content] :as params}]
(db/with-atomic [conn db/pool]
(let [thread (-> (db/get-by-id conn :comment-thread thread-id {:for-update true})
- (comments/decode-row))]
+ (comments/decode-row))
+ pname (retrieve-page-name conn thread)]
;; Standard Checks
- (when-not thread
- (ex/raise :type :not-found))
+ (when-not thread (ex/raise :type :not-found))
+ ;; Permission Checks
(files/check-read-permissions! conn profile-id (:file-id thread))
+ ;; Update the page-name cachedattribute on comment thread table.
+ (when (not= pname (:page-name thread))
+ (db/update! conn :comment-thread
+ {:page-name pname}
+ {:id thread-id}))
+
;; NOTE: is important that all timestamptz related fields are
;; created or updated on the database level for avoid clock
;; inconsistencies (some user sees something read that is not
@@ -216,15 +228,19 @@
(let [comment (db/get-by-id conn :comment id {:for-update true})
_ (when-not comment (ex/raise :type :not-found))
thread (db/get-by-id conn :comment-thread (:thread-id comment) {:for-update true})
- _ (when-not thread (ex/raise :type :not-found))]
+ _ (when-not thread (ex/raise :type :not-found))
+ pname (retrieve-page-name conn thread)]
(files/check-read-permissions! conn profile-id (:file-id thread))
+
(db/update! conn :comment
{:content content
:modified-at (dt/now)}
{:id (:id comment)})
+
(db/update! conn :comment-thread
- {:modified-at (dt/now)}
+ {:modified-at (dt/now)
+ :page-name pname}
{:id (:id thread)})
nil)))
@@ -244,6 +260,7 @@
(db/delete! conn :comment-thread {:id id})
nil)))
+
;; --- Mutation: Delete comment
(s/def ::delete-comment
diff --git a/backend/src/app/services/queries/comments.clj b/backend/src/app/services/queries/comments.clj
index 5b000b212..4d2d569b3 100644
--- a/backend/src/app/services/queries/comments.clj
+++ b/backend/src/app/services/queries/comments.clj
@@ -16,6 +16,7 @@
[app.db :as db]
[app.services.queries :as sq]
[app.services.queries.files :as files]
+ [app.services.queries.teams :as teams]
[app.util.time :as dt]
[app.util.transit :as t]
[clojure.spec.alpha :as s]
@@ -32,9 +33,13 @@
(declare retrieve-comment-threads)
+(s/def ::team-id ::us/uuid)
(s/def ::file-id ::us/uuid)
+
(s/def ::comment-threads
- (s/keys :req-un [::profile-id ::file-id]))
+ (s/and (s/keys :req-un [::profile-id]
+ :opt-un [::file-id ::team-id])
+ #(or (:file-id %) (:team-id %))))
(sq/defquery ::comment-threads
[{:keys [profile-id file-id] :as params}]
@@ -45,6 +50,8 @@
(def sql:comment-threads
"select distinct on (ct.id)
ct.*,
+ f.name as file_name,
+ f.project_id as project_id,
first_value(c.content) over w as content,
(select count(1)
from comment as c
@@ -55,6 +62,7 @@
and c.created_at >= coalesce(cts.modified_at, ct.created_at)) as count_unread_comments
from comment_thread as ct
inner join comment as c on (c.thread_id = ct.id)
+ inner join file as f on (f.id = ct.file_id)
left join comment_thread_status as cts
on (cts.thread_id = ct.id and
cts.profile_id = ?)
@@ -62,10 +70,59 @@
window w as (partition by c.thread_id order by c.created_at asc)")
(defn- retrieve-comment-threads
- [conn {:keys [profile-id file-id]}]
+ [conn {:keys [profile-id file-id team-id]}]
+ (files/check-read-permissions! conn profile-id file-id)
(->> (db/exec! conn [sql:comment-threads profile-id file-id])
(into [] (map decode-row))))
+
+;; --- Query: Unread Comment Threads
+
+(declare retrieve-unread-comment-threads)
+
+(s/def ::team-id ::us/uuid)
+(s/def ::unread-comment-threads
+ (s/keys :req-un [::profile-id ::team-id]))
+
+(sq/defquery ::unread-comment-threads
+ [{:keys [profile-id team-id] :as params}]
+ (with-open [conn (db/open)]
+ (teams/check-read-permissions! conn profile-id team-id)
+ (retrieve-unread-comment-threads conn params)))
+
+(def sql:comment-threads-by-team
+ "select distinct on (ct.id)
+ ct.*,
+ f.name as file_name,
+ f.project_id as project_id,
+ first_value(c.content) over w as content,
+ (select count(1)
+ from comment as c
+ where c.thread_id = ct.id) as count_comments,
+ (select count(1)
+ from comment as c
+ where c.thread_id = ct.id
+ and c.created_at >= coalesce(cts.modified_at, ct.created_at)) as count_unread_comments
+ from comment_thread as ct
+ inner join comment as c on (c.thread_id = ct.id)
+ inner join file as f on (f.id = ct.file_id)
+ inner join project as p on (p.id = f.project_id)
+ left join comment_thread_status as cts
+ on (cts.thread_id = ct.id and
+ cts.profile_id = ?)
+ where p.team_id = ?
+ window w as (partition by c.thread_id order by c.created_at asc)")
+
+(def sql:unread-comment-threads-by-team
+ (str "with threads as (" sql:comment-threads-by-team ")"
+ "select * from threads where count_unread_comments > 0"))
+
+(defn retrieve-unread-comment-threads
+ [conn {:keys [profile-id team-id]}]
+ (->> (db/exec! conn [sql:unread-comment-threads-by-team profile-id team-id])
+ (into [] (map decode-row))))
+
+
;; --- Query: Single Comment Thread
(s/def ::id ::us/uuid)
diff --git a/backend/src/app/services/queries/files.clj b/backend/src/app/services/queries/files.clj
index 2f8edc315..12b2764ea 100644
--- a/backend/src/app/services/queries/files.clj
+++ b/backend/src/app/services/queries/files.clj
@@ -193,6 +193,12 @@
inner join file_profile_rel as fpr on (fpr.profile_id = pf.id)
where fpr.file_id = ?
union
+ select pf.id, pf.fullname, pf.photo
+ from profile as pf
+ inner join project_profile_rel as ppr on (ppr.profile_id = pf.id)
+ inner join file as f on (f.project_id = ppr.project_id)
+ where f.id = ?
+ union
select pf.id, pf.fullname, pf.photo
from profile as pf
inner join team_profile_rel as tpr on (tpr.profile_id = pf.id)
@@ -202,7 +208,7 @@
(defn retrieve-file-users
[conn id]
- (db/exec! conn [sql:file-users id id]))
+ (db/exec! conn [sql:file-users id id id]))
(s/def ::file-users
(s/keys :req-un [::profile-id ::id]))
@@ -215,17 +221,8 @@
;; --- Query: Shared Library Files
-;; TODO: remove the counts, because they are no longer needed.
-
(def ^:private sql:shared-files
- "select f.*,
- (select count(*) from color as c
- where c.file_id = f.id
- and c.deleted_at is null) as colors_count,
- (select count(*) from media_object as m
- where m.file_id = f.id
- and m.is_local = false
- and m.deleted_at is null) as graphics_count
+ "select f.*
from file as f
inner join project as p on (p.id = f.project_id)
where f.is_shared = true
diff --git a/backend/src/app/services/queries/teams.clj b/backend/src/app/services/queries/teams.clj
index cddd8b5ab..594ba5633 100644
--- a/backend/src/app/services/queries/teams.clj
+++ b/backend/src/app/services/queries/teams.clj
@@ -130,3 +130,38 @@
(defn retrieve-team-members
[conn team-id]
(db/exec! conn [sql:team-members team-id]))
+
+;; --- Query: Team Users
+
+;; This is a similar query to team members but can contain more data
+;; because some user can be explicitly added to project or file (not
+;; implemented in UI)
+
+(def sql:team-users
+ "select pf.id, pf.fullname, pf.photo
+ from profile as pf
+ inner join team_profile_rel as tpr on (tpr.profile_id = pf.id)
+ where tpr.team_id = ?
+ union
+ select pf.id, pf.fullname, pf.photo
+ from profile as pf
+ inner join project_profile_rel as ppr on (ppr.profile_id = pf.id)
+ inner join project as p on (ppr.project_id = p.id)
+ where p.team_id = ?
+ union
+ select pf.id, pf.fullname, pf.photo
+ from profile as pf
+ inner join file_profile_rel as fpr on (fpr.profile_id = pf.id)
+ inner join file as f on (fpr.file_id = f.id)
+ inner join project as p on (f.project_id = p.id)
+ where p.team_id = ?")
+
+(s/def ::team-users
+ (s/keys :req-un [::profile-id ::team-id]))
+
+(sq/defquery ::team-users
+ [{:keys [profile-id team-id]}]
+ (with-open [conn (db/open)]
+ (check-edition-permissions! conn profile-id team-id)
+ (db/exec! conn [sql:team-users team-id team-id team-id])))
+
diff --git a/frontend/gulpfile.js b/frontend/gulpfile.js
index 11a4c8a6b..c962a72da 100644
--- a/frontend/gulpfile.js
+++ b/frontend/gulpfile.js
@@ -1,20 +1,21 @@
const fs = require("fs");
-const path = require("path");
const l = require("lodash");
+const path = require("path");
const gulp = require("gulp");
-const gulpSass = require("gulp-sass");
+const gulpConcat = require("gulp-concat");
const gulpGzip = require("gulp-gzip");
const gulpMustache = require("gulp-mustache");
-const gulpRename = require("gulp-rename");
-const svgSprite = require("gulp-svg-sprite");
const gulpPostcss = require("gulp-postcss");
+const gulpRename = require("gulp-rename");
+const gulpSass = require("gulp-sass");
+const svgSprite = require("gulp-svg-sprite");
+const autoprefixer = require("autoprefixer")
+const clean = require("postcss-clean");
const mkdirp = require("mkdirp");
const rimraf = require("rimraf");
const sass = require("sass");
-const autoprefixer = require("autoprefixer")
-const clean = require("postcss-clean");
const mapStream = require("map-stream");
const paths = {};
@@ -52,7 +53,8 @@ function readManifest() {
const content = JSON.parse(fs.readFileSync(path, {encoding: "utf8"}));
const index = {
- "config": "/js/config.js?ts=" + Date.now()
+ "config": "/js/config.js?ts=" + Date.now(),
+ "polyfills": "js/polyfills.js?ts=" + Date.now(),
};
for (let item of content) {
@@ -64,6 +66,7 @@ function readManifest() {
console.error("Error on reading manifest, using default.");
return {
"config": "/js/config.js",
+ "polyfills": "js/polyfills.js",
"main": "/js/main.js",
"shared": "/js/shared.js",
"worker": "/js/worker.js"
@@ -123,7 +126,7 @@ gulp.task("scss", function() {
.pipe(gulpSass().on('error', gulpSass.logError))
.pipe(gulpPostcss([
autoprefixer,
- clean({format: "keep-breaks", level: 1})
+ // clean({format: "keep-breaks", level: 1})
]))
.pipe(gulp.dest(paths.output + "css/"));
});
@@ -142,6 +145,12 @@ gulp.task("template:main", templatePipeline({
gulp.task("templates", gulp.series("svg:sprite", "template:main"));
+gulp.task("polyfills", function() {
+ return gulp.src(paths.resources + "polyfills/*.js")
+ .pipe(gulpConcat("polyfills.js"))
+ .pipe(gulp.dest(paths.output + "js/"));
+});
+
/***********************************************
* Development
***********************************************/
@@ -177,7 +186,7 @@ gulp.task("watch:main", function() {
gulp.series("templates"));
});
-gulp.task("build", gulp.parallel("scss", "templates", "copy:assets"));
+gulp.task("build", gulp.parallel("polyfills", "scss", "templates", "copy:assets"));
gulp.task("watch", gulp.series("dev:dirs", "build", "watch:main"));
/***********************************************
diff --git a/frontend/package.json b/frontend/package.json
index 10098e858..2bffc5c7a 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -15,6 +15,7 @@
"devDependencies": {
"autoprefixer": "^10.0.1",
"gulp": "4.0.2",
+ "gulp-concat": "^2.6.1",
"gulp-gzip": "^1.4.2",
"gulp-mustache": "^5.0.0",
"gulp-postcss": "^9.0.0",
diff --git a/frontend/resources/images/icons/comment.svg b/frontend/resources/images/icons/comment.svg
new file mode 100644
index 000000000..f6c098e08
--- /dev/null
+++ b/frontend/resources/images/icons/comment.svg
@@ -0,0 +1,4 @@
+
diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json
index 0c1951a89..f08ce41e8 100644
--- a/frontend/resources/locales.json
+++ b/frontend/resources/locales.json
@@ -18,7 +18,7 @@
}
},
"auth.create-demo-account" : {
- "used-in" : [ "src/app/main/ui/auth/login.cljs:147" ],
+ "used-in" : [ "src/app/main/ui/auth/register.cljs:136", "src/app/main/ui/auth/login.cljs:147" ],
"translations" : {
"en" : "Create demo account",
"fr" : "Vous voulez juste essayer?",
@@ -27,7 +27,7 @@
}
},
"auth.create-demo-profile" : {
- "used-in" : [ "src/app/main/ui/auth/login.cljs:144", "src/app/main/ui/auth/register.cljs:133", "src/app/main/ui/auth/register.cljs:136" ],
+ "used-in" : [ "src/app/main/ui/auth/register.cljs:133", "src/app/main/ui/auth/login.cljs:144" ],
"translations" : {
"en" : "Just wanna try it?",
"fr" : "Vous voulez juste essayer?",
@@ -45,7 +45,7 @@
}
},
"auth.email" : {
- "used-in" : [ "src/app/main/ui/auth/login.cljs:92", "src/app/main/ui/auth/register.cljs:101", "src/app/main/ui/auth/recovery_request.cljs:47" ],
+ "used-in" : [ "src/app/main/ui/auth/register.cljs:101", "src/app/main/ui/auth/recovery_request.cljs:47", "src/app/main/ui/auth/login.cljs:92" ],
"translations" : {
"en" : "Email",
"fr" : "Adresse email",
@@ -186,7 +186,7 @@
}
},
"auth.password" : {
- "used-in" : [ "src/app/main/ui/auth/login.cljs:99", "src/app/main/ui/auth/register.cljs:106" ],
+ "used-in" : [ "src/app/main/ui/auth/register.cljs:106", "src/app/main/ui/auth/login.cljs:99" ],
"translations" : {
"en" : "Password",
"fr" : "Mot de passe",
@@ -249,7 +249,7 @@
}
},
"auth.register-submit" : {
- "used-in" : [ "src/app/main/ui/auth/login.cljs:128", "src/app/main/ui/auth/register.cljs:110" ],
+ "used-in" : [ "src/app/main/ui/auth/register.cljs:110", "src/app/main/ui/auth/login.cljs:128" ],
"translations" : {
"en" : "Create an account",
"fr" : "Créer un compte",
@@ -303,20 +303,20 @@
}
},
"dashboard.create-new-team" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:155" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:159" ],
"translations" : {
"en" : "+ Create new team",
"es" : "+ Crear nuevo equipo"
}
},
"dashboard.default-team-name" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:325" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:329" ],
"translations" : {
"en" : "Your penpot"
}
},
"dashboard.delete-team" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:309" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:313" ],
"translations" : {
"en" : "Delete team"
}
@@ -340,14 +340,14 @@
}
},
"dashboard.invite-profile" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:69" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:72" ],
"translations" : {
"en" : "Invite to team",
"es" : "Invitar al equipo"
}
},
"dashboard.leave-team" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:302", "src/app/main/ui/dashboard/sidebar.cljs:305" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:306", "src/app/main/ui/dashboard/sidebar.cljs:309" ],
"translations" : {
"en" : "Leave team"
}
@@ -470,7 +470,7 @@
}
},
"dashboard.no-projects-placeholder" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:423" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:424" ],
"translations" : {
"en" : "Pinned projects will appear here"
}
@@ -503,7 +503,7 @@
}
},
"dashboard.num-of-members" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:291" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:294" ],
"translations" : {
"en" : "%s members"
}
@@ -527,7 +527,7 @@
}
},
"dashboard.promote-to-owner" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:193" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:196" ],
"translations" : {
"en" : "Promote to owner"
}
@@ -551,7 +551,7 @@
}
},
"dashboard.search-placeholder" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:110" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:113" ],
"translations" : {
"en" : "Search...",
"fr" : "Rechercher...",
@@ -603,25 +603,25 @@
"unused" : true
},
"dashboard.switch-team" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:140" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:144" ],
"translations" : {
"en" : "Switch Team"
}
},
"dashboard.team-info" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:274" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:277" ],
"translations" : {
"en" : "Team info"
}
},
"dashboard.team-members" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:285" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:288" ],
"translations" : {
"en" : "Team members"
}
},
"dashboard.team-projects" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:294" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:297" ],
"translations" : {
"en" : "Team projects"
}
@@ -645,7 +645,7 @@
}
},
"dashboard.update-settings" : {
- "used-in" : [ "src/app/main/ui/settings/options.cljs:72", "src/app/main/ui/settings/profile.cljs:80", "src/app/main/ui/settings/password.cljs:96" ],
+ "used-in" : [ "src/app/main/ui/settings/profile.cljs:80", "src/app/main/ui/settings/password.cljs:96", "src/app/main/ui/settings/options.cljs:72" ],
"translations" : {
"en" : "Update settings",
"fr" : "Mettre à jour les paramètres",
@@ -679,7 +679,7 @@
}
},
"dashboard.your-penpot" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:144" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:148" ],
"translations" : {
"en" : "Your penpot"
}
@@ -766,7 +766,7 @@
}
},
"errors.email-already-exists" : {
- "used-in" : [ "src/app/main/ui/settings/change_email.cljs:47", "src/app/main/ui/auth/verify_token.cljs:80" ],
+ "used-in" : [ "src/app/main/ui/auth/verify_token.cljs:80", "src/app/main/ui/settings/change_email.cljs:47" ],
"translations" : {
"en" : "Email already used",
"fr" : "Adresse e-mail déjà utilisée",
@@ -793,7 +793,7 @@
}
},
"errors.generic" : {
- "used-in" : [ "src/app/main/ui/settings/options.cljs:32", "src/app/main/ui/settings/profile.cljs:40", "src/app/main/ui/auth/verify_token.cljs:89" ],
+ "used-in" : [ "src/app/main/ui/auth/verify_token.cljs:89", "src/app/main/ui/settings/profile.cljs:40", "src/app/main/ui/settings/options.cljs:32" ],
"translations" : {
"en" : "Something wrong has happened.",
"fr" : "Quelque chose c'est mal passé.",
@@ -820,7 +820,7 @@
}
},
"errors.media-type-mismatch" : {
- "used-in" : [ "src/app/main/data/media.cljs:61", "src/app/main/data/workspace/persistence.cljs:421" ],
+ "used-in" : [ "src/app/main/data/workspace/persistence.cljs:390", "src/app/main/data/media.cljs:61" ],
"translations" : {
"en" : "Seems that the contents of the image does not match the file extension.",
"fr" : "",
@@ -829,7 +829,7 @@
}
},
"errors.media-type-not-allowed" : {
- "used-in" : [ "src/app/main/data/media.cljs:58", "src/app/main/data/workspace/persistence.cljs:418" ],
+ "used-in" : [ "src/app/main/data/workspace/persistence.cljs:387", "src/app/main/data/media.cljs:58" ],
"translations" : {
"en" : "Seems that this is not a valid image.",
"fr" : "",
@@ -874,7 +874,7 @@
}
},
"errors.unexpected-error" : {
- "used-in" : [ "src/app/main/data/media.cljs:64", "src/app/main/ui/auth/register.cljs:45", "src/app/main/ui/workspace/sidebar/options/exports.cljs:66" ],
+ "used-in" : [ "src/app/main/data/media.cljs:64", "src/app/main/ui/workspace/sidebar/options/exports.cljs:66", "src/app/main/ui/auth/register.cljs:45", "src/app/main/ui/handoff/exports.cljs:41" ],
"translations" : {
"en" : "An unexpected error occurred.",
"fr" : "Une erreur inattendue c'est produite",
@@ -901,31 +901,31 @@
}
},
"handoff.attributes.blur" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/blur.cljs:33" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/blur.cljs:34" ],
"translations" : {
"en" : "Blur"
}
},
"handoff.attributes.blur.value" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/blur.cljs:39" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/blur.cljs:40" ],
"translations" : {
"en" : "Value"
}
},
"handoff.attributes.color.hex" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/common.cljs:72" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/common.cljs:70" ],
"translations" : {
"en" : "HEX"
}
},
"handoff.attributes.color.hsla" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/common.cljs:78" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/common.cljs:76" ],
"translations" : {
"en" : "HSLA"
}
},
"handoff.attributes.color.rgba" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/common.cljs:75" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/common.cljs:73" ],
"translations" : {
"en" : "RGBA"
}
@@ -937,97 +937,97 @@
"unused" : true
},
"handoff.attributes.fill" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/fill.cljs:58" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/fill.cljs:57" ],
"translations" : {
"en" : "Fill"
}
},
"handoff.attributes.image.download" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/image.cljs:44" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/image.cljs:45" ],
"translations" : {
"en" : "Dowload source image"
}
},
"handoff.attributes.image.height" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/image.cljs:36" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/image.cljs:37" ],
"translations" : {
"en" : "Height"
}
},
"handoff.attributes.image.width" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/image.cljs:31" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/image.cljs:32" ],
"translations" : {
"en" : "Width"
}
},
"handoff.attributes.layout" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:76" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:76" ],
"translations" : {
"en" : "Layout"
}
},
"handoff.attributes.layout.height" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:36" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:43" ],
"translations" : {
"en" : "Height"
}
},
"handoff.attributes.layout.left" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:44" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:49" ],
"translations" : {
"en" : "Left"
}
},
"handoff.attributes.layout.radius" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:60" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:61" ],
"translations" : {
"en" : "Radius"
}
},
"handoff.attributes.layout.rotation" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:60" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:67" ],
"translations" : {
"en" : "Rotation"
}
},
"handoff.attributes.layout.top" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:52" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:55" ],
"translations" : {
"en" : "Top"
}
},
"handoff.attributes.layout.width" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/layout.cljs:29" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/layout.cljs:38" ],
"translations" : {
"en" : "Width"
}
},
"handoff.attributes.shadow" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:71" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:71" ],
"translations" : {
"en" : "Shadow"
}
},
"handoff.attributes.shadow.shorthand.blur" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:44" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:53" ],
"translations" : {
"en" : "B"
}
},
"handoff.attributes.shadow.shorthand.offset-x" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:36" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:45" ],
"translations" : {
"en" : "X"
}
},
"handoff.attributes.shadow.shorthand.offset-y" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:40" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:49" ],
"translations" : {
"en" : "Y"
}
},
"handoff.attributes.shadow.shorthand.spread" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/shadow.cljs:48" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/shadow.cljs:57" ],
"translations" : {
"en" : "S"
}
@@ -1045,7 +1045,7 @@
"unused" : true
},
"handoff.attributes.stroke" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/stroke.cljs:75" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/stroke.cljs:75" ],
"translations" : {
"en" : "Stroke"
}
@@ -1099,49 +1099,49 @@
"unused" : true
},
"handoff.attributes.stroke.width" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/stroke.cljs:57" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/stroke.cljs:63" ],
"translations" : {
"en" : "Width"
}
},
"handoff.attributes.typography" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:159" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:190" ],
"translations" : {
"en" : "Typography"
}
},
"handoff.attributes.typography.font-family" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:89" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:121" ],
"translations" : {
"en" : "Font Family"
}
},
"handoff.attributes.typography.font-size" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:101" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:133" ],
"translations" : {
"en" : "Font Size"
}
},
"handoff.attributes.typography.font-style" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:95" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:127" ],
"translations" : {
"en" : "Font Style"
}
},
"handoff.attributes.typography.letter-spacing" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:113" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:145" ],
"translations" : {
"en" : "Letter Spacing"
}
},
"handoff.attributes.typography.line-height" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:107" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:139" ],
"translations" : {
"en" : "Line Height"
}
},
"handoff.attributes.typography.text-decoration" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:119" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:151" ],
"translations" : {
"en" : "Text Decoration"
}
@@ -1165,7 +1165,7 @@
"unused" : true
},
"handoff.attributes.typography.text-transform" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:125" ],
+ "used-in" : [ "src/app/main/ui/handoff/attributes/text.cljs:157" ],
"translations" : {
"en" : "Text Transform"
}
@@ -1195,7 +1195,7 @@
"unused" : true
},
"handoff.tabs.code" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/right_sidebar.cljs:78" ],
+ "used-in" : [ "src/app/main/ui/handoff/right_sidebar.cljs:65" ],
"translations" : {
"en" : "Code"
}
@@ -1231,7 +1231,7 @@
"unused" : true
},
"handoff.tabs.code.selected.multiple" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/right_sidebar.cljs:65" ],
+ "used-in" : [ "src/app/main/ui/handoff/right_sidebar.cljs:48" ],
"translations" : {
"en" : "%s Selected"
}
@@ -1255,7 +1255,7 @@
"unused" : true
},
"handoff.tabs.info" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/right_sidebar.cljs:74" ],
+ "used-in" : [ "src/app/main/ui/handoff/right_sidebar.cljs:59" ],
"translations" : {
"en" : "Info"
}
@@ -1270,13 +1270,13 @@
"unused" : true
},
"labels.admin" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:82", "src/app/main/ui/dashboard/team.cljs:171", "src/app/main/ui/dashboard/team.cljs:187" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:85", "src/app/main/ui/dashboard/team.cljs:174", "src/app/main/ui/dashboard/team.cljs:190" ],
"translations" : {
"en" : "Admin"
}
},
"labels.cancel" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:199" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:203" ],
"translations" : {
"en" : "Cancel",
"fr" : "Annuler",
@@ -1284,6 +1284,12 @@
"es" : "Cancelar"
}
},
+ "labels.comments" : {
+ "used-in" : [ "src/app/main/ui/dashboard/comments.cljs:75" ],
+ "translations" : {
+ "en" : "Comments"
+ }
+ },
"labels.confirm-password" : {
"used-in" : [ "src/app/main/ui/settings/password.cljs:93" ],
"translations" : {
@@ -1300,7 +1306,7 @@
}
},
"labels.delete" : {
- "used-in" : [ "src/app/main/ui/dashboard/files.cljs:85", "src/app/main/ui/dashboard/grid.cljs:177" ],
+ "used-in" : [ "src/app/main/ui/dashboard/grid.cljs:177", "src/app/main/ui/dashboard/files.cljs:85" ],
"translations" : {
"en" : "Delete",
"fr" : "Supprimer",
@@ -1308,8 +1314,20 @@
"es" : "Borrar"
}
},
+ "labels.delete-comment" : {
+ "used-in" : [ "src/app/main/ui/comments.cljs:273" ],
+ "translations" : {
+ "en" : "Delete comment"
+ }
+ },
+ "labels.delete-comment-thread" : {
+ "used-in" : [ "src/app/main/ui/comments.cljs:272" ],
+ "translations" : {
+ "en" : "Delete thread"
+ }
+ },
"labels.drafts" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:402" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:404" ],
"translations" : {
"en" : "Drafts",
"fr" : "Brouillons",
@@ -1317,14 +1335,20 @@
"es" : "Borradores"
}
},
+ "labels.edit" : {
+ "used-in" : [ "src/app/main/ui/comments.cljs:270" ],
+ "translations" : {
+ "en" : "Edit"
+ }
+ },
"labels.editor" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:83", "src/app/main/ui/dashboard/team.cljs:174", "src/app/main/ui/dashboard/team.cljs:188" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:86", "src/app/main/ui/dashboard/team.cljs:177", "src/app/main/ui/dashboard/team.cljs:191" ],
"translations" : {
"en" : "Editor"
}
},
"labels.email" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:109", "src/app/main/ui/dashboard/team.cljs:212" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:112", "src/app/main/ui/dashboard/team.cljs:215" ],
"translations" : {
"en" : "Email",
"fr" : "Adresse email",
@@ -1332,6 +1356,12 @@
"es" : "Correo electrónico"
}
},
+ "labels.hide-resolved-comments" : {
+ "used-in" : [ "src/app/main/ui/workspace/comments.cljs:129", "src/app/main/ui/viewer/header.cljs:175" ],
+ "translations" : {
+ "en" : "Hide resolved comments"
+ }
+ },
"labels.language" : {
"used-in" : [ "src/app/main/ui/settings/options.cljs:54" ],
"translations" : {
@@ -1342,7 +1372,7 @@
}
},
"labels.logout" : {
- "used-in" : [ "src/app/main/ui/settings.cljs:31", "src/app/main/ui/dashboard/sidebar.cljs:457" ],
+ "used-in" : [ "src/app/main/ui/settings.cljs:31", "src/app/main/ui/dashboard/sidebar.cljs:456" ],
"translations" : {
"en" : "Logout",
"fr" : "Quitter",
@@ -1351,13 +1381,13 @@
}
},
"labels.members" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:295", "src/app/main/ui/dashboard/team.cljs:59", "src/app/main/ui/dashboard/team.cljs:63" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:60", "src/app/main/ui/dashboard/team.cljs:66", "src/app/main/ui/dashboard/sidebar.cljs:299" ],
"translations" : {
"en" : "Members"
}
},
"labels.name" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:211" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:214" ],
"translations" : {
"en" : "Name",
"fr" : "Nom",
@@ -1374,6 +1404,12 @@
"es" : "Nueva contraseña"
}
},
+ "labels.no-comments-available" : {
+ "translations" : {
+ "en" : "No comments"
+ },
+ "unused" : true
+ },
"labels.old-password" : {
"used-in" : [ "src/app/main/ui/settings/password.cljs:81" ],
"translations" : {
@@ -1384,13 +1420,13 @@
}
},
"labels.owner" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:168" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:171", "src/app/main/ui/dashboard/team.cljs:291" ],
"translations" : {
"en" : "Owner"
}
},
"labels.password" : {
- "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:75", "src/app/main/ui/dashboard/sidebar.cljs:454" ],
+ "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:75", "src/app/main/ui/dashboard/sidebar.cljs:453" ],
"translations" : {
"en" : "Password",
"fr" : "Mot de passe",
@@ -1399,14 +1435,14 @@
}
},
"labels.permissions" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:213" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:216" ],
"translations" : {
"en" : "Permissions",
"es" : "Permisos"
}
},
"labels.profile" : {
- "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:70", "src/app/main/ui/dashboard/sidebar.cljs:451" ],
+ "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:70", "src/app/main/ui/dashboard/sidebar.cljs:450" ],
"translations" : {
"en" : "Profile",
"fr" : "Profil",
@@ -1415,7 +1451,7 @@
}
},
"labels.projects" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:397" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:400" ],
"translations" : {
"en" : "Projects",
"fr" : "Projetes",
@@ -1424,7 +1460,7 @@
}
},
"labels.remove" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:91", "src/app/main/ui/dashboard/team.cljs:199" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:92", "src/app/main/ui/dashboard/team.cljs:202" ],
"translations" : {
"en" : "Remove",
"fr" : "",
@@ -1433,20 +1469,20 @@
}
},
"labels.rename" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:298", "src/app/main/ui/dashboard/files.cljs:84", "src/app/main/ui/dashboard/grid.cljs:176" ],
+ "used-in" : [ "src/app/main/ui/dashboard/grid.cljs:176", "src/app/main/ui/dashboard/sidebar.cljs:302", "src/app/main/ui/dashboard/files.cljs:84" ],
"translations" : {
"en" : "Rename",
"es" : "Renombrar"
}
},
"labels.role" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:81" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:84" ],
"translations" : {
"en" : "Role"
}
},
"labels.settings" : {
- "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:80", "src/app/main/ui/dashboard/sidebar.cljs:296", "src/app/main/ui/dashboard/team.cljs:65" ],
+ "used-in" : [ "src/app/main/ui/settings/sidebar.cljs:80", "src/app/main/ui/dashboard/team.cljs:61", "src/app/main/ui/dashboard/team.cljs:68", "src/app/main/ui/dashboard/sidebar.cljs:300" ],
"translations" : {
"en" : "Settings",
"fr" : "Settings",
@@ -1455,7 +1491,7 @@
}
},
"labels.shared-libraries" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:408" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:409" ],
"translations" : {
"en" : "Shared Libraries",
"fr" : "",
@@ -1463,6 +1499,18 @@
"es" : "Bibliotecas Compartidas"
}
},
+ "labels.show-all-comments" : {
+ "used-in" : [ "src/app/main/ui/workspace/comments.cljs:117", "src/app/main/ui/viewer/header.cljs:163" ],
+ "translations" : {
+ "en" : "Show all comments"
+ }
+ },
+ "labels.show-your-comments" : {
+ "used-in" : [ "src/app/main/ui/workspace/comments.cljs:122", "src/app/main/ui/viewer/header.cljs:168" ],
+ "translations" : {
+ "en" : "Show only yours comments"
+ }
+ },
"labels.update" : {
"used-in" : [ "src/app/main/ui/settings/profile.cljs:106" ],
"translations" : {
@@ -1473,14 +1521,20 @@
}
},
"labels.viewer" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:84", "src/app/main/ui/dashboard/team.cljs:177", "src/app/main/ui/dashboard/team.cljs:189" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:87", "src/app/main/ui/dashboard/team.cljs:180", "src/app/main/ui/dashboard/team.cljs:192" ],
"translations" : {
"en" : "Viewer",
"es" : "Visualizador"
}
},
+ "labels.write-new-comment" : {
+ "used-in" : [ "src/app/main/ui/comments.cljs:151" ],
+ "translations" : {
+ "en" : "Write new comment"
+ }
+ },
"media.loading" : {
- "used-in" : [ "src/app/main/data/media.cljs:43", "src/app/main/data/workspace/persistence.cljs:402" ],
+ "used-in" : [ "src/app/main/data/workspace/persistence.cljs:371", "src/app/main/data/media.cljs:43" ],
"translations" : {
"en" : "Loading image...",
"fr" : "Chargement de l'image...",
@@ -1606,19 +1660,19 @@
}
},
"modals.delete-comment-thread.accept" : {
- "used-in" : [ "src/app/main/ui/workspace/comments.cljs:236" ],
+ "used-in" : [ "src/app/main/ui/comments.cljs:222" ],
"translations" : {
"en" : "Delete conversation"
}
},
"modals.delete-comment-thread.message" : {
- "used-in" : [ "src/app/main/ui/workspace/comments.cljs:235" ],
+ "used-in" : [ "src/app/main/ui/comments.cljs:221" ],
"translations" : {
"en" : "Are you sure you want to delete this conversation? All comments in this thread will be deleted."
}
},
"modals.delete-comment-thread.title" : {
- "used-in" : [ "src/app/main/ui/workspace/comments.cljs:234" ],
+ "used-in" : [ "src/app/main/ui/comments.cljs:220" ],
"translations" : {
"en" : "Delete conversation"
}
@@ -1660,109 +1714,109 @@
}
},
"modals.delete-team-confirm.accept" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:285" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:289" ],
"translations" : {
"en" : "Delete team"
}
},
"modals.delete-team-confirm.message" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:284" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:288" ],
"translations" : {
"en" : "Are you sure you want to delete this team? All projects and files associated with team will be permanently deleted."
}
},
"modals.delete-team-confirm.title" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:283" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:287" ],
"translations" : {
"en" : "Deleting team"
}
},
"modals.delete-team-member-confirm.accept" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:157" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:160" ],
"translations" : {
"en" : "Delete member"
}
},
"modals.delete-team-member-confirm.message" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:156" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:159" ],
"translations" : {
"en" : "Are you sure wan't to delete this user from team?"
}
},
"modals.delete-team-member-confirm.title" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:155" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:158" ],
"translations" : {
"en" : "Delete team member"
}
},
"modals.invite-member.title" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:105" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:108" ],
"translations" : {
"en" : "Invite a new team member"
}
},
"modals.leave-and-reassign.hint1" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:188" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:192" ],
"translations" : {
"en" : "You are %s owner."
}
},
"modals.leave-and-reassign.hint2" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:189" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:193" ],
"translations" : {
"en" : "Select an other member to promote before leave"
}
},
"modals.leave-and-reassign.promote-and-leave" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:206" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:210" ],
"translations" : {
"en" : "Promote and leave"
}
},
"modals.leave-and-reassign.select-memeber-to-promote" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:166" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:170" ],
"translations" : {
"en" : "Select a member to promote"
}
},
"modals.leave-and-reassign.title" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:183" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:187" ],
"translations" : {
"en" : "Select a member to promote"
}
},
"modals.leave-confirm.accept" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:260" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:264" ],
"translations" : {
"en" : "Leave team"
}
},
"modals.leave-confirm.message" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:259" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:263" ],
"translations" : {
"en" : "Are you sure you want to leave this team?"
}
},
"modals.leave-confirm.title" : {
- "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:258" ],
+ "used-in" : [ "src/app/main/ui/dashboard/sidebar.cljs:262" ],
"translations" : {
"en" : "Leaving team"
}
},
"modals.promote-owner-confirm.accept" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:144" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:147" ],
"translations" : {
"en" : "Promote"
}
},
"modals.promote-owner-confirm.message" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:143" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:146" ],
"translations" : {
"en" : "Are you sure you wan't to promote this user to owner?"
}
},
"modals.promote-owner-confirm.title" : {
- "used-in" : [ "src/app/main/ui/dashboard/team.cljs:142" ],
+ "used-in" : [ "src/app/main/ui/dashboard/team.cljs:145" ],
"translations" : {
"en" : "Promote to owner"
}
@@ -1804,7 +1858,7 @@
}
},
"notifications.profile-saved" : {
- "used-in" : [ "src/app/main/ui/settings/options.cljs:36", "src/app/main/ui/settings/profile.cljs:36" ],
+ "used-in" : [ "src/app/main/ui/settings/profile.cljs:36", "src/app/main/ui/settings/options.cljs:36" ],
"translations" : {
"en" : "Profile saved successfully!",
"fr" : "Profil enregistré avec succès!",
@@ -1813,7 +1867,7 @@
}
},
"notifications.validation-email-sent" : {
- "used-in" : [ "src/app/main/ui/settings/change_email.cljs:56", "src/app/main/ui/auth/register.cljs:54" ],
+ "used-in" : [ "src/app/main/ui/auth/register.cljs:54", "src/app/main/ui/settings/change_email.cljs:56" ],
"translations" : {
"en" : "Verification email sent to %s; check your email!"
}
@@ -1828,7 +1882,7 @@
}
},
"settings.multiple" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:153", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:163", "src/app/main/ui/workspace/sidebar/options/typography.cljs:99", "src/app/main/ui/workspace/sidebar/options/typography.cljs:149", "src/app/main/ui/workspace/sidebar/options/typography.cljs:162", "src/app/main/ui/workspace/sidebar/options/stroke.cljs:147" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/stroke.cljs:147", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:153", "src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:163", "src/app/main/ui/workspace/sidebar/options/typography.cljs:99", "src/app/main/ui/workspace/sidebar/options/typography.cljs:149", "src/app/main/ui/workspace/sidebar/options/typography.cljs:162" ],
"translations" : {
"en" : "Mixed",
"fr" : null,
@@ -1855,7 +1909,7 @@
"unused" : true
},
"viewer.empty-state" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff.cljs:56", "src/app/main/ui/viewer.cljs:42" ],
+ "used-in" : [ "src/app/main/ui/handoff.cljs:55", "src/app/main/ui/viewer.cljs:193" ],
"translations" : {
"en" : "No frames found on the page.",
"fr" : "Aucun cadre trouvé sur la page.",
@@ -1864,7 +1918,7 @@
}
},
"viewer.frame-not-found" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff.cljs:60", "src/app/main/ui/viewer.cljs:46" ],
+ "used-in" : [ "src/app/main/ui/handoff.cljs:59", "src/app/main/ui/viewer.cljs:197" ],
"translations" : {
"en" : "Frame not found.",
"fr" : "Cadre introuvable.",
@@ -1872,12 +1926,8 @@
"es" : "No se encuentra el tablero."
}
},
- "labels.show-all-comments": "Show all comments",
- "labels.show-your-comments": "Show only yours comments",
- "labels.hide-resolved-comments": "Hide resolved comments",
-
"viewer.header.dont-show-interactions" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:68" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:124" ],
"translations" : {
"en" : "Don't show interactions",
"fr" : "Ne pas afficher les interactions",
@@ -1886,7 +1936,7 @@
}
},
"viewer.header.edit-page" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:183" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:264" ],
"translations" : {
"en" : "Edit page",
"fr" : "Editer la page",
@@ -1895,7 +1945,7 @@
}
},
"viewer.header.fullscreen" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:194" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:275" ],
"translations" : {
"en" : "Full Screen",
"fr" : "Plein écran",
@@ -1904,7 +1954,7 @@
}
},
"viewer.header.share.copy-link" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:113" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:92" ],
"translations" : {
"en" : "Copy link",
"fr" : "Copier lien",
@@ -1913,7 +1963,7 @@
}
},
"viewer.header.share.create-link" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:122" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:101" ],
"translations" : {
"en" : "Create link",
"fr" : "Créer lien",
@@ -1922,7 +1972,7 @@
}
},
"viewer.header.share.placeholder" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:114" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:93" ],
"translations" : {
"en" : "Share link will appear here",
"fr" : "Le lien de partage apparaîtra ici",
@@ -1931,7 +1981,7 @@
}
},
"viewer.header.share.remove-link" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:120" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:99" ],
"translations" : {
"en" : "Remove link",
"fr" : "Supprimer le lien",
@@ -1940,7 +1990,7 @@
}
},
"viewer.header.share.subtitle" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:116" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:95" ],
"translations" : {
"en" : "Anyone with the link will have access",
"fr" : "Toute personne disposant du lien aura accès",
@@ -1949,7 +1999,7 @@
}
},
"viewer.header.share.title" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:99", "src/app/main/ui/viewer/header.cljs:101", "src/app/main/ui/viewer/header.cljs:107" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:78", "src/app/main/ui/viewer/header.cljs:80", "src/app/main/ui/viewer/header.cljs:86" ],
"translations" : {
"en" : "Share link",
"fr" : "Lien de partage",
@@ -1958,7 +2008,7 @@
}
},
"viewer.header.show-interactions" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:72" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:129" ],
"translations" : {
"en" : "Show interactions",
"fr" : "Afficher les interactions",
@@ -1967,7 +2017,7 @@
}
},
"viewer.header.show-interactions-on-click" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:76" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:134" ],
"translations" : {
"en" : "Show interactions on click",
"fr" : "Afficher les interactions au clic",
@@ -1976,7 +2026,7 @@
}
},
"viewer.header.sitemap" : {
- "used-in" : [ "src/app/main/ui/viewer/header.cljs:156" ],
+ "used-in" : [ "src/app/main/ui/viewer/header.cljs:223" ],
"translations" : {
"en" : "Sitemap",
"fr" : "Plan du site",
@@ -2057,7 +2107,7 @@
}
},
"workspace.assets.assets" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:630" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:668" ],
"translations" : {
"en" : "Assets",
"fr" : "",
@@ -2066,7 +2116,7 @@
}
},
"workspace.assets.box-filter-all" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:650" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:688" ],
"translations" : {
"en" : "All assets",
"fr" : "",
@@ -2093,7 +2143,7 @@
"unused" : true
},
"workspace.assets.colors" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:330", "src/app/main/ui/workspace/sidebar/assets.cljs:653" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:366", "src/app/main/ui/workspace/sidebar/assets.cljs:691" ],
"translations" : {
"en" : "Colors",
"fr" : "",
@@ -2102,7 +2152,7 @@
}
},
"workspace.assets.components" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:84", "src/app/main/ui/workspace/sidebar/assets.cljs:651" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:109", "src/app/main/ui/workspace/sidebar/assets.cljs:689" ],
"translations" : {
"en" : "Components",
"fr" : "",
@@ -2111,7 +2161,7 @@
}
},
"workspace.assets.delete" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:104", "src/app/main/ui/workspace/sidebar/assets.cljs:192", "src/app/main/ui/workspace/sidebar/assets.cljs:306", "src/app/main/ui/workspace/sidebar/assets.cljs:434" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:140", "src/app/main/ui/workspace/sidebar/assets.cljs:228", "src/app/main/ui/workspace/sidebar/assets.cljs:342", "src/app/main/ui/workspace/sidebar/assets.cljs:470" ],
"translations" : {
"en" : "Delete",
"fr" : "",
@@ -2120,6 +2170,7 @@
}
},
"workspace.assets.duplicate" : {
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:139" ],
"translations" : {
"en" : "Duplicate",
"fr" : "",
@@ -2128,7 +2179,7 @@
}
},
"workspace.assets.edit" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:305", "src/app/main/ui/workspace/sidebar/assets.cljs:433" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:341", "src/app/main/ui/workspace/sidebar/assets.cljs:469" ],
"translations" : {
"en" : "Edit",
"fr" : "",
@@ -2137,7 +2188,7 @@
}
},
"workspace.assets.file-library" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:532" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:568" ],
"translations" : {
"en" : "File library",
"fr" : "",
@@ -2146,7 +2197,7 @@
}
},
"workspace.assets.graphics" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:165", "src/app/main/ui/workspace/sidebar/assets.cljs:652" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:201", "src/app/main/ui/workspace/sidebar/assets.cljs:690" ],
"translations" : {
"en" : "Graphics",
"fr" : "",
@@ -2155,7 +2206,7 @@
}
},
"workspace.assets.libraries" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:633" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:671" ],
"translations" : {
"en" : "Libraries",
"fr" : "",
@@ -2164,7 +2215,7 @@
}
},
"workspace.assets.not-found" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:593" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:629" ],
"translations" : {
"en" : "No assets found",
"fr" : "",
@@ -2173,7 +2224,7 @@
}
},
"workspace.assets.rename" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:304", "src/app/main/ui/workspace/sidebar/assets.cljs:432" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:138", "src/app/main/ui/workspace/sidebar/assets.cljs:340", "src/app/main/ui/workspace/sidebar/assets.cljs:468" ],
"translations" : {
"en" : "Rename",
"fr" : "",
@@ -2182,7 +2233,7 @@
}
},
"workspace.assets.search" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:637" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:675" ],
"translations" : {
"en" : "Search assets",
"fr" : "",
@@ -2191,7 +2242,7 @@
}
},
"workspace.assets.shared" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:534" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:570" ],
"translations" : {
"en" : "SHARED",
"fr" : "",
@@ -2200,7 +2251,7 @@
}
},
"workspace.assets.typography" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:421", "src/app/main/ui/workspace/sidebar/assets.cljs:654" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/assets.cljs:457", "src/app/main/ui/workspace/sidebar/assets.cljs:692" ],
"translations" : {
"en" : "Typographies"
}
@@ -2242,7 +2293,7 @@
}
},
"workspace.assets.typography.sample" : {
- "used-in" : [ "src/app/main/ui/viewer/handoff/attributes/text.cljs:65", "src/app/main/ui/workspace/sidebar/options/typography.cljs:255" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/typography.cljs:255", "src/app/main/ui/handoff/attributes/text.cljs:97", "src/app/main/ui/handoff/attributes/text.cljs:106" ],
"translations" : {
"en" : "Ag"
}
@@ -2254,13 +2305,13 @@
}
},
"workspace.gradients.linear" : {
- "used-in" : [ "src/app/main/data/workspace/libraries.cljs:39", "src/app/main/ui/components/color_bullet.cljs:31" ],
+ "used-in" : [ "src/app/main/data/workspace/libraries.cljs:42", "src/app/main/ui/components/color_bullet.cljs:31" ],
"translations" : {
"en" : "Linear gradient"
}
},
"workspace.gradients.radial" : {
- "used-in" : [ "src/app/main/data/workspace/libraries.cljs:40", "src/app/main/ui/components/color_bullet.cljs:32" ],
+ "used-in" : [ "src/app/main/data/workspace/libraries.cljs:43", "src/app/main/ui/components/color_bullet.cljs:32" ],
"translations" : {
"en" : "Radial gradient"
}
@@ -2425,7 +2476,7 @@
}
},
"workspace.libraries.add" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:115" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:116" ],
"translations" : {
"en" : "Add",
"fr" : "",
@@ -2434,7 +2485,7 @@
}
},
"workspace.libraries.colors" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:43" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:44" ],
"translations" : {
"en" : "%s colors",
"fr" : "",
@@ -2473,7 +2524,7 @@
}
},
"workspace.libraries.components" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:37" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:38" ],
"translations" : {
"en" : "%s components",
"fr" : "",
@@ -2482,7 +2533,7 @@
}
},
"workspace.libraries.file-library" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:84" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:85" ],
"translations" : {
"en" : "File library",
"fr" : "",
@@ -2491,7 +2542,7 @@
}
},
"workspace.libraries.graphics" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:40" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:41" ],
"translations" : {
"en" : "%s graphics",
"fr" : "",
@@ -2500,7 +2551,7 @@
}
},
"workspace.libraries.in-this-file" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:81" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:82" ],
"translations" : {
"en" : "LIBRARIES IN THIS FILE",
"fr" : "",
@@ -2509,7 +2560,7 @@
}
},
"workspace.libraries.libraries" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:175" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:177" ],
"translations" : {
"en" : "LIBRARIES",
"fr" : "",
@@ -2518,7 +2569,7 @@
}
},
"workspace.libraries.library" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:135" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:136" ],
"translations" : {
"en" : "LIBRARY",
"fr" : "",
@@ -2527,7 +2578,7 @@
}
},
"workspace.libraries.no-libraries-need-sync" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:133" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:134" ],
"translations" : {
"en" : "There are no Shared Libraries that need update",
"fr" : "",
@@ -2536,7 +2587,7 @@
}
},
"workspace.libraries.no-matches-for" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:121" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:122" ],
"translations" : {
"en" : "No matches found for “%s“",
"fr" : "Aucune correspondance pour “%s“",
@@ -2545,7 +2596,7 @@
}
},
"workspace.libraries.no-shared-libraries-available" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:120" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:121" ],
"translations" : {
"en" : "There are no Shared Libraries available",
"fr" : "",
@@ -2554,7 +2605,7 @@
}
},
"workspace.libraries.search-shared-libraries" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:98" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:99" ],
"translations" : {
"en" : "Search shared libraries",
"fr" : "",
@@ -2563,7 +2614,7 @@
}
},
"workspace.libraries.shared-libraries" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:95" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:96" ],
"translations" : {
"en" : "SHARED LIBRARIES",
"fr" : "",
@@ -2584,13 +2635,13 @@
}
},
"workspace.libraries.typography" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:46" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:47" ],
"translations" : {
"en" : "%s typographies"
}
},
"workspace.libraries.update" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:142" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:143" ],
"translations" : {
"en" : "Update",
"fr" : "",
@@ -2599,7 +2650,7 @@
}
},
"workspace.libraries.updates" : {
- "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:179" ],
+ "used-in" : [ "src/app/main/ui/workspace/libraries.cljs:181" ],
"translations" : {
"en" : "UPDATES",
"fr" : "",
@@ -2689,6 +2740,7 @@
}
},
"workspace.options.component" : {
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:62" ],
"translations" : {
"en" : "Component",
"es" : "Componente"
@@ -2704,21 +2756,21 @@
}
},
"workspace.options.export" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:123" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:123", "src/app/main/ui/handoff/exports.cljs:96" ],
"translations" : {
"en" : "Export",
"ru" : "Экспорт"
}
},
"workspace.options.export-object" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:156" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:156", "src/app/main/ui/handoff/exports.cljs:131" ],
"translations" : {
"en" : "Export shape",
"ru" : "Экспорт фигуры"
}
},
"workspace.options.exporting-object" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:155" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/exports.cljs:155", "src/app/main/ui/handoff/exports.cljs:130" ],
"translations" : {
"en" : "Exporting...",
"ru" : "Экспортирую ..."
@@ -2959,7 +3011,7 @@
}
},
"workspace.options.position" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/options/frame.cljs:127", "src/app/main/ui/workspace/sidebar/options/measures.cljs:146" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/measures.cljs:146", "src/app/main/ui/workspace/sidebar/options/frame.cljs:127" ],
"translations" : {
"en" : "Position",
"fr" : "Position",
@@ -3073,7 +3125,7 @@
}
},
"workspace.options.size" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/options/frame.cljs:100", "src/app/main/ui/workspace/sidebar/options/measures.cljs:116" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/measures.cljs:116", "src/app/main/ui/workspace/sidebar/options/frame.cljs:100" ],
"translations" : {
"en" : "Size",
"fr" : "Taille",
@@ -3280,7 +3332,7 @@
}
},
"workspace.options.text-options.none" : {
- "used-in" : [ "src/app/main/ui/workspace/sidebar/options/typography.cljs:178", "src/app/main/ui/workspace/sidebar/options/text.cljs:154" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/text.cljs:154", "src/app/main/ui/workspace/sidebar/options/typography.cljs:178" ],
"translations" : {
"en" : "None",
"fr" : "Aucune",
@@ -3377,138 +3429,139 @@
}
},
"workspace.shape.menu.back" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:103" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:104" ],
"translations" : {
"en" : "Send to back"
}
},
"workspace.shape.menu.backward" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:100" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:101" ],
"translations" : {
"en" : "Send backward"
}
},
"workspace.shape.menu.copy" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:81" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:82" ],
"translations" : {
"en" : "Copy"
}
},
"workspace.shape.menu.create-component" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:145" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:147" ],
"translations" : {
"en" : "Create component"
}
},
"workspace.shape.menu.cut" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:84" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:85" ],
"translations" : {
"en" : "Cut"
}
},
"workspace.shape.menu.delete" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:163" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:177" ],
"translations" : {
"en" : "Delete"
}
},
"workspace.shape.menu.detach-instance" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:152" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:76", "src/app/main/ui/workspace/sidebar/options/component.cljs:81", "src/app/main/ui/workspace/context_menu.cljs:159", "src/app/main/ui/workspace/context_menu.cljs:169" ],
"translations" : {
"en" : "Detach instance"
}
},
"workspace.shape.menu.duplicate" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:90" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:91" ],
"translations" : {
"en" : "Duplicate"
}
},
"workspace.shape.menu.forward" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:94" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:95" ],
"translations" : {
"en" : "Bring forward"
}
},
"workspace.shape.menu.front" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:97" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:98" ],
"translations" : {
"en" : "Bring to front"
}
},
"workspace.shape.menu.go-master" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:159" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:83", "src/app/main/ui/workspace/context_menu.cljs:173" ],
"translations" : {
"en" : "Go to master component file"
}
},
- "workspace.shape.menu.show-master" : {
- "translations" : {
- "en" : "Show master component"
- }
- },
"workspace.shape.menu.group" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:110" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:111" ],
"translations" : {
"en" : "Group"
}
},
"workspace.shape.menu.hide" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:133" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:134" ],
"translations" : {
"en" : "Hide"
}
},
"workspace.shape.menu.lock" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:139" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:140" ],
"translations" : {
"en" : "Lock"
}
},
"workspace.shape.menu.mask" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:113" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:114" ],
"translations" : {
"en" : "Mask"
}
},
"workspace.shape.menu.paste" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:87", "src/app/main/ui/workspace/context_menu.cljs:172" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:88", "src/app/main/ui/workspace/context_menu.cljs:186" ],
"translations" : {
"en" : "Paste"
}
},
"workspace.shape.menu.reset-overrides" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:154" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:77", "src/app/main/ui/workspace/sidebar/options/component.cljs:82", "src/app/main/ui/workspace/context_menu.cljs:161", "src/app/main/ui/workspace/context_menu.cljs:171" ],
"translations" : {
"en" : "Reset overrides"
}
},
"workspace.shape.menu.show" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:131" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:132" ],
"translations" : {
"en" : "Show"
}
},
+ "workspace.shape.menu.show-master" : {
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:79", "src/app/main/ui/workspace/context_menu.cljs:165" ],
+ "translations" : {
+ "en" : "Show master component"
+ }
+ },
"workspace.shape.menu.ungroup" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:119" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:120" ],
"translations" : {
"en" : "Ungroup"
}
},
"workspace.shape.menu.unlock" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:137" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:138" ],
"translations" : {
"en" : "Unlock"
}
},
"workspace.shape.menu.unmask" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:123" ],
+ "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:124" ],
"translations" : {
"en" : "Unmask"
}
},
"workspace.shape.menu.update-master" : {
- "used-in" : [ "src/app/main/ui/workspace/context_menu.cljs:157" ],
+ "used-in" : [ "src/app/main/ui/workspace/sidebar/options/component.cljs:78", "src/app/main/ui/workspace/context_menu.cljs:163" ],
"translations" : {
"en" : "Update master component"
}
@@ -3860,7 +3913,7 @@
}
},
"workspace.updates.dismiss" : {
- "used-in" : [ "src/app/main/data/workspace/libraries.cljs:541" ],
+ "used-in" : [ "src/app/main/data/workspace/libraries.cljs:638" ],
"translations" : {
"en" : "Dismiss",
"fr" : "",
@@ -3869,7 +3922,7 @@
}
},
"workspace.updates.there-are-updates" : {
- "used-in" : [ "src/app/main/data/workspace/libraries.cljs:537" ],
+ "used-in" : [ "src/app/main/data/workspace/libraries.cljs:634" ],
"translations" : {
"en" : "There are updates in shared libraries",
"fr" : "",
@@ -3878,7 +3931,7 @@
}
},
"workspace.updates.update" : {
- "used-in" : [ "src/app/main/data/workspace/libraries.cljs:539" ],
+ "used-in" : [ "src/app/main/data/workspace/libraries.cljs:636" ],
"translations" : {
"en" : "Update",
"fr" : "",
diff --git a/frontend/resources/polyfills/scrollIntoViewIfNeeded.js b/frontend/resources/polyfills/scrollIntoViewIfNeeded.js
new file mode 100644
index 000000000..a341b3e40
--- /dev/null
+++ b/frontend/resources/polyfills/scrollIntoViewIfNeeded.js
@@ -0,0 +1,27 @@
+;(function() {
+ if (!Element.prototype.scrollIntoViewIfNeeded) {
+ Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) {
+ centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded;
+
+ var parent = this.parentNode,
+ parentComputedStyle = window.getComputedStyle(parent, null),
+ parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
+ parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
+ overTop = this.offsetTop - parent.offsetTop < parent.scrollTop,
+ overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight),
+ overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft,
+ overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth),
+ alignWithTop = overTop && !overBottom;
+
+ if ((overTop || overBottom) && centerIfNeeded) {
+ parent.scrollTop = this.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + this.clientHeight / 2;
+ }
+ if ((overLeft || overRight) && centerIfNeeded) {
+ parent.scrollLeft = this.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + this.clientWidth / 2;
+ }
+ if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
+ this.scrollIntoView(alignWithTop);
+ }
+ };
+ }
+})()
diff --git a/frontend/resources/styles/main-default.scss b/frontend/resources/styles/main-default.scss
index b8860a4b4..a18f57a44 100644
--- a/frontend/resources/styles/main-default.scss
+++ b/frontend/resources/styles/main-default.scss
@@ -80,6 +80,6 @@
@import 'main/partials/user-settings';
@import 'main/partials/workspace';
@import 'main/partials/workspace-header';
-@import 'main/partials/workspace-comments';
+@import 'main/partials/comments';
@import 'main/partials/color-bullet';
@import "main/partials/handoff";
diff --git a/frontend/resources/styles/main/layouts/main-layout.scss b/frontend/resources/styles/main/layouts/main-layout.scss
index 22a1cd54c..b7045cd39 100644
--- a/frontend/resources/styles/main/layouts/main-layout.scss
+++ b/frontend/resources/styles/main/layouts/main-layout.scss
@@ -23,7 +23,7 @@
.dashboard-sidebar {
grid-row: 1 / span 2;
grid-column: 1 / span 2;
- overflow: hidden;
+ // overflow: hidden;
}
.dashboard-content {
diff --git a/frontend/resources/styles/main/partials/workspace-comments.scss b/frontend/resources/styles/main/partials/comments.scss
similarity index 67%
rename from frontend/resources/styles/main/partials/workspace-comments.scss
rename to frontend/resources/styles/main/partials/comments.scss
index 1f425ae71..b15588d89 100644
--- a/frontend/resources/styles/main/partials/workspace-comments.scss
+++ b/frontend/resources/styles/main/partials/comments.scss
@@ -1,31 +1,4 @@
-.viewer-comments {
- width: 100%;
- height: 100%;
- z-index: 1000;
- position: absolute;
- top: 0px;
- left: 0px;
-}
-
-.viewer-comments, .workspace-comments {
-
- .comments-layer {
-
- width: 100%;
- height: 100%;
- grid-column: 1/span 2;
- grid-row: 1/span 2;
- z-index: 1000;
- pointer-events: none;
- overflow: hidden;
-
- .threads {
- position: absolute;
- top: 0px;
- left: 0px;
- }
- }
-
+.comments-section {
.thread-bubble {
position: absolute;
display: flex;
@@ -101,6 +74,8 @@
padding: $small;
resize: none;
width: 100%;
+ border-radius: 2px;
+ border: 1px solid $color-gray-10;
}
.buttons {
@@ -142,7 +117,7 @@
.fullname {
font-weight: 700;
color: $color-gray-60;
- font-size: $fs13;
+ font-size: $fs10;
@include text-ellipsis;
width: 150px;
@@ -150,7 +125,7 @@
}
.timeago {
margin-top: -2px;
- font-size: $fs11;
+ font-size: $fs10;
color: $color-gray-30;
}
}
@@ -163,8 +138,8 @@
img {
border-radius: 50%;
flex-shrink: 0;
- height: 24px;
- width: 24px;
+ height: 20px;
+ width: 20px;
}
}
@@ -205,9 +180,8 @@
}
.content {
- margin: $medium 0;
- // margin-left: 26px;
- font-size: $fs13;
+ margin: 10px 0;
+ font-size: $fs10;
color: $color-black;
.text {
margin-left: 26px;
@@ -225,51 +199,51 @@
border: 1px solid #B1B2B5;
}
-
}
-.workspace-comments-sidebar {
- pointer-events: auto;
+.workspace-comment-threads-sidebar-header {
+ display: flex;
+ background-color: $color-black;
+ height: 34px;
+ align-items: center;
+ padding: 0px 9px;
+ color: $color-gray-10;
+ font-size: $fs12;
+ justify-content: space-between;
- .sidebar-title {
+ .options {
display: flex;
- background-color: $color-black;
- height: 34px;
- align-items: center;
- padding: 0px 9px;
- color: $color-gray-10;
- font-size: $fs12;
- justify-content: space-between;
+ margin-right: 3px;
+ cursor: pointer;
- .options {
+ .label {
+ padding-right: 8px;
+ }
+
+ .icon {
display: flex;
- margin-right: 3px;
- cursor: pointer;
+ align-items: center;
+ }
- .label {
- padding-right: 8px;
- }
-
- .icon {
- display: flex;
- align-items: center;
- }
-
- svg {
- fill: $color-gray-10;
- width: 10px;
- height: 10px;
- }
+ svg {
+ fill: $color-gray-10;
+ width: 10px;
+ height: 10px;
}
}
- .sidebar-options-dropdown {
+ .dropdown {
top: 80px;
right: 7px;
}
+}
- .threads {
+
+.comment-threads-section {
+ pointer-events: auto;
+
+ .thread-groups {
hr {
border: 0;
height: 1px;
@@ -278,7 +252,7 @@
}
}
- .page-section {
+ .thread-group {
display: flex;
flex-direction: column;
font-size: $fs12;
@@ -292,6 +266,9 @@
}
.label {
+ &.filename {
+ font-weight: 700;
+ }
}
svg {
@@ -312,6 +289,7 @@
}
.comment {
+ cursor: pointer;
.author {
margin-bottom: 10px;
.name {
@@ -351,3 +329,118 @@
}
}
}
+
+
+.viewer-comments-container {
+ width: 100%;
+ height: 100%;
+ z-index: 1000;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+}
+
+.workspace-comments-container {
+ width: 100%;
+ height: 100%;
+ grid-column: 1/span 2;
+ grid-row: 1/span 2;
+ z-index: 1000;
+ pointer-events: none;
+ overflow: hidden;
+
+ .threads {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ }
+}
+
+.dashboard-comments-section {
+ width: 25px;
+ height: 25px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: $color-dashboard;
+ border-radius: 3px;
+ position: relative;
+
+ .button {
+ width: 25px;
+ height: 25px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: $color-dashboard;
+ border-radius: 3px;
+
+ svg {
+ width: 15px;
+ height: 15px;
+ }
+
+ &.unread {
+ background-color: $color-warning;
+ }
+
+ &.open {
+ background-color: $color-black;
+ svg { fill: $color-primary; }
+ }
+ }
+
+ .dropdown {
+ width: 233px;
+ bottom: 35px;
+ left: 0px;
+ border-radius: 3px;
+ }
+
+ .header {
+ display: flex;
+ height: 40px;
+ align-items: center;
+ padding: 0px 11px;
+
+ h3 {
+ font-weight: 400;
+ color: $color-black;
+ font-size: $fs12;
+ line-height: $fs18;
+ flex-grow: 1;
+ }
+
+ .close {
+ display: flex;
+ align-items: center;
+ }
+
+
+ svg {
+ width: 15px;
+ height: 15px;
+ transform: rotate(45deg);
+ }
+ }
+
+ .thread-groups-placeholder {
+ padding: 16px;
+ }
+
+ .thread-group {
+ .section-title {
+ color: $color-black;
+ }
+ }
+
+ .comment {
+ .author .name .fullname {
+ color: $color-gray-40;
+ }
+ .content {
+ color: $color-black;
+ }
+ }
+}
+
diff --git a/frontend/resources/styles/main/partials/dashboard-sidebar.scss b/frontend/resources/styles/main/partials/dashboard-sidebar.scss
index 04f1daf17..658411737 100644
--- a/frontend/resources/styles/main/partials/dashboard-sidebar.scss
+++ b/frontend/resources/styles/main/partials/dashboard-sidebar.scss
@@ -363,26 +363,32 @@
padding: 10px 15px;
position: relative;
- span {
- @include text-ellipsis;
- color: $color-black;
- margin: 10px 5px;
- font-size: $fs14;
- max-width: 160px;
- }
+ .profile {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ flex-grow: 1;
- img {
- border-radius: 50%;
- flex-shrink: 0;
- height: 25px;
- width: 25px;
- }
+ span {
+ @include text-ellipsis;
+ color: $color-black;
+ margin: 10px 5px;
+ font-size: $fs14;
+ max-width: 160px;
+ }
- svg {
- height: 10px;
- margin-left: auto;
- margin-right: $small;
- width: 10px;
+ img {
+ border-radius: 50%;
+ flex-shrink: 0;
+ height: 25px;
+ width: 25px;
+ }
+ svg {
+ height: 10px;
+ margin-left: auto;
+ margin-right: $small;
+ width: 10px;
+ }
}
.dropdown {
@@ -400,6 +406,8 @@
svg {
fill: $color-gray-20;
+ margin-right: $small;
+
height: 12px;
width: 12px;
}
diff --git a/frontend/resources/templates/index.mustache b/frontend/resources/templates/index.mustache
index 99da48768..801633eb1 100644
--- a/frontend/resources/templates/index.mustache
+++ b/frontend/resources/templates/index.mustache
@@ -20,6 +20,7 @@
{{# manifest}}
+
{{/manifest}}
diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs
index 79b5995a9..75a1faaea 100644
--- a/frontend/src/app/main/data/comments.cljs
+++ b/frontend/src/app/main/data/comments.cljs
@@ -40,11 +40,14 @@
(s/def ::count-unread-comments ::us/integer)
(s/def ::created-at ::us/inst)
(s/def ::file-id ::us/uuid)
+(s/def ::file-name ::us/string)
(s/def ::modified-at ::us/inst)
(s/def ::owner-id ::us/uuid)
(s/def ::page-id ::us/uuid)
+(s/def ::page-name ::us/string)
(s/def ::participants (s/every ::us/uuid :kind set?))
(s/def ::position ::us/point)
+(s/def ::project-id ::us/uuid)
(s/def ::seqn ::us/integer)
(s/def ::thread-id ::us/uuid)
@@ -52,15 +55,18 @@
(s/keys :req-un [::us/id
::page-id
::file-id
+ ::project-id
+ ::page-name
+ ::file-name
::seqn
::content
::participants
- ::count-unread-comments
- ::count-comments
::created-at
::modified-at
::owner-id
- ::position]))
+ ::position]
+ :opt-un [::count-unread-comments
+ ::count-comments]))
(s/def ::comment
(s/keys :req-un [::us/id
@@ -92,20 +98,18 @@
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/mutation :create-comment-thread params)
+ (rx/mapcat #(rp/query :comment-thread {:file-id (:file-id %) :id (:id %)}))
(rx/map #(partial created %)))))))
(defn update-comment-thread-status
[{:keys [id] :as thread}]
(us/assert ::comment-thread thread)
(ptk/reify ::update-comment-thread-status
- ptk/UpdateEvent
- (update [_ state]
- (d/update-in-when state [:comment-threads id] assoc :count-unread-comments 0))
-
ptk/WatchEvent
(watch [_ state stream]
- (->> (rp/mutation :update-comment-thread-status {:id id})
- (rx/ignore)))))
+ (let [done #(d/update-in-when % [:comment-threads id] assoc :count-unread-comments 0)]
+ (->> (rp/mutation :update-comment-thread-status {:id id})
+ (rx/map (constantly done)))))))
(defn update-comment-thread
@@ -211,6 +215,18 @@
(->> (rp/query :comments {:thread-id thread-id})
(rx/map #(partial fetched %)))))))
+(defn retrieve-unread-comment-threads
+ "A event used mainly in dashboard for retrieve all unread threads of a team."
+ [team-id]
+ (us/assert ::us/uuid team-id)
+ (ptk/reify ::retrieve-unread-comment-threads
+ ptk/WatchEvent
+ (watch [_ state stream]
+ (let [fetched #(assoc %2 :comment-threads (d/index-by :id %1))]
+ (->> (rp/query :unread-comment-threads {:team-id team-id})
+ (rx/map #(partial fetched %)))))))
+
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Local State
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -221,6 +237,7 @@
(ptk/reify ::open-thread
ptk/UpdateEvent
(update [_ state]
+ (prn "open-thread" id)
(-> state
(update :comments-local assoc :open id)
(update :workspace-drawing dissoc :comment)))))
@@ -230,6 +247,7 @@
(ptk/reify ::close-thread
ptk/UpdateEvent
(update [_ state]
+ (prn "close-thread")
(-> state
(update :comments-local dissoc :open :draft)
(update :workspace-drawing dissoc :comment)))))
@@ -282,11 +300,31 @@
(if (= (:page-id current) (:page-id thread))
(cons (update current :items conj thread)
(rest result))
- (cons {:page-id (:page-id thread) :items [thread]}
+ (cons {:page-id (:page-id thread)
+ :page-name (:page-name thread)
+ :items [thread]}
result))))]
(reverse
(reduce group-by-page nil threads))))
+
+(defn group-threads-by-file-and-page
+ [threads]
+ (letfn [(group-by-file-and-page [result thread]
+ (let [current (first result)]
+ (if (and (= (:page-id current) (:page-id thread))
+ (= (:file-id current) (:file-id thread)))
+ (cons (update current :items conj thread)
+ (rest result))
+ (cons {:page-id (:page-id thread)
+ :page-name (:page-name thread)
+ :file-id (:file-id thread)
+ :file-name (:file-name thread)
+ :items [thread]}
+ result))))]
+ (reverse
+ (reduce group-by-file-and-page nil threads))))
+
(defn apply-filters
[cstate profile threads]
(let [{:keys [show mode open]} cstate]
diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs
index 52ae6f79a..862a90ba7 100644
--- a/frontend/src/app/main/data/dashboard.cljs
+++ b/frontend/src/app/main/data/dashboard.cljs
@@ -64,13 +64,6 @@
;; --- Fetch Team
-(defn assoc-team-avatar
- [{:keys [photo name] :as team}]
- (us/assert ::team team)
- (cond-> team
- (or (nil? photo) (empty? photo))
- (assoc :photo (avatars/generate {:name name}))))
-
(defn fetch-team
[{:keys [id] :as params}]
(letfn [(fetched [team state]
@@ -80,20 +73,36 @@
(watch [_ state stream]
(let [profile (:profile state)]
(->> (rp/query :team params)
- (rx/map assoc-team-avatar)
+ (rx/map #(avatars/assoc-avatar % :name))
(rx/map #(partial fetched %))))))))
(defn fetch-team-members
[{:keys [id] :as params}]
(us/assert ::us/uuid id)
(letfn [(fetched [members state]
- (assoc-in state [:team-members id] (d/index-by :id members)))]
+ (->> (map #(avatars/assoc-avatar % :name) members)
+ (d/index-by :id)
+ (assoc-in state [:team-members id])))]
(ptk/reify ::fetch-team-members
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query :team-members {:team-id id})
(rx/map #(partial fetched %)))))))
+
+(defn fetch-team-users
+ [{:keys [id] :as params}]
+ (us/assert ::us/uuid id)
+ (letfn [(fetched [users state]
+ (->> (map #(avatars/assoc-avatar % :fullname) users)
+ (d/index-by :id)
+ (assoc-in state [:team-users id])))]
+ (ptk/reify ::fetch-team-users
+ ptk/WatchEvent
+ (watch [_ state stream]
+ (->> (rp/query :team-users {:team-id id})
+ (rx/map #(partial fetched %)))))))
+
;; --- Fetch Projects
(defn fetch-projects
@@ -115,7 +124,8 @@
(watch [_ state stream]
(let [profile (:profile state)]
(->> (rx/merge (ptk/watch (fetch-team params) state stream)
- (ptk/watch (fetch-projects {:team-id id}) state stream))
+ (ptk/watch (fetch-projects {:team-id id}) state stream)
+ (ptk/watch (fetch-team-users params) state stream))
(rx/catch (fn [{:keys [type code] :as error}]
(cond
(and (= :not-found type)
diff --git a/frontend/src/app/main/data/users.cljs b/frontend/src/app/main/data/users.cljs
index 2e990f7d0..56b624ae9 100644
--- a/frontend/src/app/main/data/users.cljs
+++ b/frontend/src/app/main/data/users.cljs
@@ -55,8 +55,8 @@
(update [_ state]
(assoc state :profile
(cond-> data
- (nil? (:photo-uri data))
- (assoc :photo-uri (avatars/generate {:name fullname}))
+ (empty? (:photo data))
+ (assoc :photo (avatars/generate {:name fullname}))
(nil? (:lang data))
(assoc :lang cfg/default-language)
diff --git a/frontend/src/app/main/data/workspace/comments.cljs b/frontend/src/app/main/data/workspace/comments.cljs
index ac1d16c05..ccbbd8c30 100644
--- a/frontend/src/app/main/data/workspace/comments.cljs
+++ b/frontend/src/app/main/data/workspace/comments.cljs
@@ -14,10 +14,12 @@
[app.common.math :as mth]
[app.common.spec :as us]
[app.main.constants :as c]
+ [app.main.data.workspace :as dw]
[app.main.data.workspace.common :as dwc]
[app.main.data.comments :as dcm]
[app.main.store :as st]
[app.main.streams :as ms]
+ [app.util.router :as rt]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[potok.core :as ptk]))
@@ -82,12 +84,31 @@
(update [_ state]
(update state :workspace-local
(fn [{:keys [vbox vport zoom] :as local}]
+ (prn "center-to-comment-thread" vbox)
(let [pw (/ 50 zoom)
ph (/ 200 zoom)
nw (mth/round (- (/ (:width vbox) 2) pw))
nh (mth/round (- (/ (:height vbox) 2) ph))
nx (- (:x position) nw)
ny (- (:y position) nh)]
- (update local :vbox assoc :x nx :y ny)))))))
+ (update local :vbox assoc :x nx :y ny)))))))
+
+(defn navigate
+ [{:keys [project-id file-id page-id] :as thread}]
+ (us/assert ::dcm/comment-thread thread)
+ (ptk/reify ::navigate
+ ptk/WatchEvent
+ (watch [_ state stream]
+ (let [pparams {:project-id (:project-id thread)
+ :file-id (:file-id thread)}
+ qparams {:page-id (:page-id thread)}]
+ (rx/merge
+ (rx/of (rt/nav :workspace pparams qparams)
+ (dw/select-for-drawing :comments))
+ (->> stream
+ (rx/filter (ptk/type? ::dw/initialize-viewport))
+ (rx/take 1)
+ (rx/mapcat #(rx/of (center-to-comment-thread thread)
+ (dcm/open-thread thread)))))))))
diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs
index 37d5b7200..58fa20a6e 100644
--- a/frontend/src/app/main/refs.cljs
+++ b/frontend/src/app/main/refs.cljs
@@ -208,6 +208,9 @@
(def viewer-local
(l/derived :viewer-local st/state))
+(def comment-threads
+ (l/derived :comment-threads st/state))
+
(def comments-local
(l/derived :comments-local st/state))
diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs
index 3cf96c363..d681003d2 100644
--- a/frontend/src/app/main/ui/comments.cljs
+++ b/frontend/src/app/main/ui/comments.cljs
@@ -148,7 +148,7 @@
:left (str (+ pos-x 14) "px")}
:on-click dom/stop-propagation}
[:div.reply-form
- [:& resizing-textarea {:placeholder "Write new comment"
+ [:& resizing-textarea {:placeholder (tr "labels.write-new-comment")
:value (or content "")
:on-esc on-esc
:on-change on-change}]
@@ -267,10 +267,10 @@
[:& dropdown {:show @options
:on-close on-hide-options}
[:ul.dropdown.comment-options-dropdown
- [:li {:on-click on-edit-clicked} "Edit"]
+ [:li {:on-click on-edit-clicked} (tr "labels.edit")]
(if thread
- [:li {:on-click on-delete-thread} "Delete thread"]
- [:li {:on-click on-delete-comment} "Delete comment"])]]]))
+ [:li {:on-click on-delete-thread} (tr "labels.delete-comment-thread")]
+ [:li {:on-click on-delete-comment} (tr "labels.delete-comment")])]]]))
(defn comments-ref
[{:keys [id] :as thread}]
@@ -289,12 +289,13 @@
(sort-by :created-at))
comment (first comments)]
- (mf/use-effect
- (st/emitf (dcm/update-comment-thread-status thread)))
+ (mf/use-layout-effect
+ (mf/deps thread)
+ (st/emitf (dcm/retrieve-comments (:id thread))))
(mf/use-effect
(mf/deps thread)
- (st/emitf (dcm/retrieve-comments (:id thread))))
+ (st/emitf (dcm/update-comment-thread-status thread)))
(mf/use-layout-effect
(mf/deps thread comments-map)
@@ -338,3 +339,62 @@
:unread (pos? (:count-unread-comments thread)))
:on-click on-click*}
[:span (:seqn thread)]]))
+
+(mf/defc comment-thread
+ [{:keys [item users on-click] :as props}]
+ (let [profile (get users (:owner-id item))
+
+ on-click*
+ (mf/use-callback
+ (mf/deps item)
+ (fn [event]
+ (dom/stop-propagation event)
+ (dom/prevent-default event)
+ (when (fn? on-click)
+ (on-click item))))]
+
+ [:div.comment {:on-click on-click*}
+ [:div.author
+ [:div.thread-bubble
+ {:class (dom/classnames
+ :resolved (:is-resolved item)
+ :unread (pos? (:count-unread-comments item)))}
+ (:seqn item)]
+ [:div.avatar
+ [:img {:src (cfg/resolve-media-path (:photo profile))}]]
+ [:div.name
+ [:div.fullname (:fullname profile) ", "]
+ [:div.timeago (dt/timeago (:modified-at item))]]]
+ [:div.content
+ [:span.text (:content item)]]
+ [:div.content.replies
+ (let [unread (:count-unread-comments item ::none)
+ total (:count-comments item 1)]
+ [:*
+ (when (> total 1)
+ (if (= total 2)
+ [:span.total-replies "1 reply"]
+ [:span.total-replies (str (dec total) " replies")]))
+
+ (when (and (> total 1) (> unread 0))
+ (if (= unread 1)
+ [:span.new-replies "1 new reply"]
+ [:span.new-replies (str unread " new replies")]))])]]))
+
+(mf/defc comment-thread-group
+ [{:keys [group users on-thread-click]}]
+ [:div.thread-group
+ (if (:file-name group)
+ [:div.section-title
+ [:span.label.filename (:file-name group) ", "]
+ [:span.label (:page-name group)]]
+ [:div.section-title
+ [:span.icon i/file-html]
+ [:span.label (:page-name group)]])
+ [:div.threads
+ (for [item (:items group)]
+ [:& comment-thread
+ {:item item
+ :on-click on-thread-click
+ :users users
+ :key (:id item)}])]])
diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs
new file mode 100644
index 000000000..3febd79e1
--- /dev/null
+++ b/frontend/src/app/main/ui/dashboard/comments.cljs
@@ -0,0 +1,104 @@
+;; This Source Code Form is subject to the terms of the Mozilla Public
+;; License, v. 2.0. If a copy of the MPL was not distributed with this
+;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;;
+;; This Source Code Form is "Incompatible With Secondary Licenses", as
+;; defined by the Mozilla Public License, v. 2.0.
+;;
+;; Copyright (c) 2020 UXBOX Labs SL
+
+(ns app.main.ui.dashboard.comments
+ (:require
+ [okulary.core :as l]
+ [app.common.data :as d]
+ [app.common.spec :as us]
+ [app.config :as cfg]
+ [app.main.data.auth :as da]
+ [app.main.data.dashboard :as dd]
+ [app.main.data.workspace :as dw]
+ [app.main.data.workspace.comments :as dwcm]
+ [app.main.data.comments :as dcm]
+ [app.main.refs :as refs]
+ [app.main.repo :as rp]
+ [app.main.store :as st]
+ [app.main.ui.components.dropdown :refer [dropdown]]
+ [app.main.ui.comments :as cmt]
+ [app.main.ui.icons :as i]
+ [app.util.dom :as dom]
+ [app.util.i18n :as i18n :refer [t tr]]
+ [app.util.object :as obj]
+ [app.util.router :as rt]
+ [app.util.time :as dt]
+ [app.util.timers :as tm]
+ [beicon.core :as rx]
+ [cljs.spec.alpha :as s]
+ [cuerdas.core :as str]
+ [rumext.alpha :as mf]))
+
+
+(defn team-members-ref
+ [{:keys [id] :as team}]
+ (l/derived (l/in [:team-users id]) st/state))
+
+(mf/defc comments-section
+ [{:keys [profile team]}]
+
+ (mf/use-effect
+ (mf/deps team)
+ (st/emitf (dcm/retrieve-unread-comment-threads (:id team))))
+
+ (let [show-dropdown? (mf/use-state false)
+ 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-ref (mf/use-memo (mf/deps team) #(team-members-ref team))
+ users (mf/deref users-ref)
+
+ tgroups (->> (vals threads-map)
+ (sort-by :modified-at)
+ (reverse)
+ (dcm/apply-filters {} profile)
+ (dcm/group-threads-by-file-and-page))
+
+
+ on-navigate
+ (mf/use-callback
+ (fn [thread]
+ (st/emit! (dwcm/navigate thread))))]
+
+ [:div.dashboard-comments-section
+ [:div.button
+ {:on-click show-dropdown
+ :class (dom/classnames :open @show-dropdown?
+ :unread (boolean (seq tgroups)))}
+ i/chat]
+
+ [:& dropdown {:show @show-dropdown? :on-close hide-dropdown}
+ [:div.dropdown.comments-section.comment-threads-section.
+ [:div.header
+ [:h3 (tr "labels.comments")]
+ [:span.close {:on-click hide-dropdown} i/close]]
+
+ [:hr]
+
+ (if (seq tgroups)
+ [:div.thread-groups
+ [:& cmt/comment-thread-group
+ {:group (first tgroups)
+ :on-thread-click on-navigate
+ :show-file-name true
+ :users users}]
+ (for [tgroup (rest tgroups)]
+ [:*
+ [:hr]
+
+ [:& cmt/comment-thread-group
+ {:group tgroup
+ :on-thread-click on-navigate
+ :show-file-name true
+ :users users
+ :key (:page-id tgroup)}]])]
+
+ [:div.thread-groups-placeholder
+ (tr "labels.no-comments-available")])]]]))
diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs
index e05f064ca..73554a514 100644
--- a/frontend/src/app/main/ui/dashboard/sidebar.cljs
+++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs
@@ -15,21 +15,24 @@
[app.main.data.auth :as da]
[app.main.data.dashboard :as dd]
[app.main.data.messages :as dm]
+ [app.main.data.modal :as modal]
+ [app.main.data.comments :as dcm]
[app.main.refs :as refs]
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
- [app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.components.forms :as fm]
+ [app.main.ui.dashboard.comments :refer [comments-section]]
+ [app.main.ui.dashboard.inline-edition :refer [inline-edition]]
[app.main.ui.dashboard.team-form]
[app.main.ui.icons :as i]
[app.main.ui.keyboard :as kbd]
- [app.main.data.modal :as modal]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [t tr]]
[app.util.object :as obj]
[app.util.router :as rt]
[app.util.time :as dt]
+ [app.util.avatars :as avatars]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[cuerdas.core :as str]
@@ -133,7 +136,8 @@
(mf/deps (:id team))
(fn []
(->> (rp/query! :teams)
- (rx/map #(mapv dd/assoc-team-avatar %))
+ (rx/map (fn [teams]
+ (mapv #(avatars/assoc-avatar % :name) teams)))
(rx/subs #(reset! teams %)))))
[:ul.dropdown.teams-dropdown
@@ -421,12 +425,9 @@
(mf/defc profile-section
- [{:keys [profile locale] :as props}]
+ [{:keys [profile locale team] :as props}]
(let [show (mf/use-state false)
- photo (:photo-uri profile "")
- photo (if (str/empty? photo)
- "/images/avatar.jpg"
- photo)
+ photo (cfg/resolve-media-path (:photo profile))
on-click
(mf/use-callback
@@ -436,10 +437,10 @@
(st/emit! (rt/nav section))
(st/emit! section))))]
- [:div.profile-section {:on-click #(reset! show true)}
- [:img {:src photo}]
- [:span (:fullname profile)]
- i/arrow-down
+ [:div.profile-section
+ [:div.profile {:on-click #(reset! show true)}
+ [:img {:src photo}]
+ [:span (:fullname profile)]
[:& dropdown {:on-close #(reset! show false)
:show @show}
@@ -452,17 +453,25 @@
[:span.text (t locale "labels.password")]]
[:li {:on-click (partial on-click (da/logout))}
[:span.icon i/exit]
- [:span.text (t locale "labels.logout")]]]]]))
+ [:span.text (t locale "labels.logout")]]]]]
+
+ (when (and team profile)
+ [:& comments-section {:profile profile
+ :team team}])]))
(mf/defc sidebar
{::mf/wrap-props false
::mf/wrap [mf/memo]}
[props]
(let [locale (mf/deref i18n/locale)
+ team (obj/get props "team")
profile (obj/get props "profile")
props (-> (obj/clone props)
(obj/set! "locale" locale))]
[:div.dashboard-sidebar
[:div.sidebar-inside
[:> sidebar-content props]
- [:& profile-section {:profile profile :locale locale}]]]))
+ [:& profile-section
+ {:profile profile
+ :team team
+ :locale locale}]]]))
diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs
index 6633f236b..73017aaeb 100644
--- a/frontend/src/app/main/ui/viewer.cljs
+++ b/frontend/src/app/main/ui/viewer.cljs
@@ -106,8 +106,8 @@
(dcm/close-thread)))))
]
- [:div.viewer-comments {:on-click on-click}
- [:div.comments-layer
+ [:div.comments-section {:on-click on-click}
+ [:div.viewer-comments-container
[:div.threads
(for [item threads]
[:& cmt/thread-bubble {:thread item
diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs
index f2f113e88..25a69c9f8 100644
--- a/frontend/src/app/main/ui/workspace/comments.cljs
+++ b/frontend/src/app/main/ui/workspace/comments.cljs
@@ -60,7 +60,6 @@
#_(dcm/close-thread))))
]
-
(mf/use-effect
(mf/deps file-id)
(fn []
@@ -68,8 +67,8 @@
(fn []
(st/emit! ::dwcm/finalize))))
- [:div.workspace-comments
- [:div.comments-layer
+ [:div.comments-section
+ [:div.workspace-comments-container
{:style {:width (str (:width vport) "px")
:height (str (:height vport) "px")}}
[:div.threads {:style {:transform (str/format "translate(%spx, %spx)" pos-x pos-y)}}
@@ -96,66 +95,6 @@
;; Sidebar
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(mf/defc sidebar-group-item
- [{:keys [item] :as props}]
- (let [profile (get @refs/workspace-users (:owner-id item))
- page-id (mf/use-ctx ctx/current-page-id)
- file-id (mf/use-ctx ctx/current-file-id)
-
- on-click
- (mf/use-callback
- (mf/deps item page-id)
- (fn []
- (when (not= page-id (:page-id item))
- (st/emit! (dw/go-to-page (:page-id item))))
- (tm/schedule
- (st/emitf (dwcm/center-to-comment-thread item)
- (dcm/open-thread item)))))]
-
- [:div.comment {:on-click on-click}
- [:div.author
- [:div.thread-bubble
- {:class (dom/classnames
- :resolved (:is-resolved item)
- :unread (pos? (:count-unread-comments item)))}
- (:seqn item)]
- [:div.avatar
- [:img {:src (cfg/resolve-media-path (:photo profile))}]]
- [:div.name
- [:div.fullname (:fullname profile) ", "]
- [:div.timeago (dt/timeago (:modified-at item))]]]
- [:div.content
- [:span.text (:content item)]]
- [:div.content.replies
- (let [unread (:count-unread-comments item ::none)
- total (:count-comments item 1)]
- [:*
- (when (> total 1)
- (if (= total 2)
- [:span.total-replies "1 reply"]
- [:span.total-replies (str (dec total) " replies")]))
-
- (when (and (> total 1) (> unread 0))
- (if (= unread 1)
- [:span.new-replies "1 new reply"]
- [:span.new-replies (str unread " new replies")]))])]]))
-
-(defn page-name-ref
- [id]
- (l/derived (l/in [:workspace-data :pages-index id :name]) st/state))
-
-(mf/defc sidebar-item
- [{:keys [group]}]
- (let [page-name-ref (mf/use-memo (mf/deps (:page-id group)) #(page-name-ref (:page-id group)))
- page-name (mf/deref page-name-ref)]
- [:div.page-section
- [:div.section-title
- [:span.icon i/file-html]
- [:span.label page-name]]
- [:div.comments-container
- (for [item (:items group)]
- [:& sidebar-group-item {:item item :key (:id item)}])]]))
-
(mf/defc sidebar-options
[{:keys [local] :as props}]
(let [{cmode :mode cshow :show} (mf/deref refs/comments-local)
@@ -171,7 +110,7 @@
(fn [mode]
(st/emit! (dcm/update-filters {:show mode}))))]
- [:ul.dropdown.with-check.sidebar-options-dropdown
+ [:ul.dropdown.with-check
[:li {:class (dom/classnames :selected (or (= :all cmode) (nil? cmode)))
:on-click #(update-mode :all)}
[:span.icon i/tick]
@@ -193,6 +132,7 @@
[]
(let [threads-map (mf/deref threads-ref)
profile (mf/deref refs/profile)
+ users (mf/deref refs/workspace-users)
local (mf/deref refs/comments-local)
options? (mf/use-state false)
@@ -200,28 +140,45 @@
(sort-by :modified-at)
(reverse)
(dcm/apply-filters local profile)
- (dcm/group-threads-by-page))]
+ (dcm/group-threads-by-page))
- [:div.workspace-comments.workspace-comments-sidebar
- [:div.sidebar-title
+ page-id (mf/use-ctx ctx/current-page-id)
+
+ on-thread-click
+ (mf/use-callback
+ (fn [thread]
+ (when (not= page-id (:page-id thread))
+ (st/emit! (dw/go-to-page (:page-id thread))))
+ (tm/schedule
+ (st/emitf (dwcm/center-to-comment-thread thread)
+ (dcm/open-thread thread)))))]
+
+ [:div.comments-section.comment-threads-section
+ [:div.workspace-comment-threads-sidebar-header
[:div.label "Comments"]
[:div.options {:on-click #(reset! options? true)}
- [:div.label (case (:filter local)
+ [:div.label (case (:mode local)
(nil :all) "All"
:yours "Only yours")]
- [:div.icon i/arrow-down]]]
+ [:div.icon i/arrow-down]]
- [:& dropdown {:show @options?
- :on-close #(reset! options? false)}
- [:& sidebar-options {:local local}]]
+ [:& dropdown {:show @options?
+ :on-close #(reset! options? false)}
+ [:& sidebar-options {:local local}]]]
(when (seq tgroups)
- [:div.threads
- [:& sidebar-item {:group (first tgroups)}]
+ [:div.thread-groups
+ [:& cmt/comment-thread-group
+ {:group (first tgroups)
+ :on-thread-click on-thread-click
+ :users users}]
(for [tgroup (rest tgroups)]
[:*
[:hr]
- [:& sidebar-item {:group tgroup
- :key (:page-id tgroup)}]])])]))
+ [:& cmt/comment-thread-group
+ {:group tgroup
+ :on-thread-click on-thread-click
+ :users users
+ :key (:page-id tgroup)}]])])]))
diff --git a/frontend/src/app/util/avatars.cljs b/frontend/src/app/util/avatars.cljs
index 64a79e1ee..04a9bd38c 100644
--- a/frontend/src/app/util/avatars.cljs
+++ b/frontend/src/app/util/avatars.cljs
@@ -36,8 +36,13 @@
(.toDataURL canvas)))
-(defn assoc-profile-avatar
- [{:keys [photo fullname] :as profile}]
- (cond-> profile
+(defn assoc-avatar
+ [{:keys [photo] :as object} key]
+ (cond-> object
(or (nil? photo) (empty? photo))
- (assoc :photo (generate {:name fullname}))))
+ (assoc :photo (generate {:name (get object key)}))))
+
+(defn assoc-profile-avatar
+ [object]
+ (assoc-avatar object :fullname))
+
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 9515c97bf..0225cfb40 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -933,6 +933,13 @@ concat-stream@^1.6.0, concat-stream@^1.6.2:
readable-stream "^2.2.2"
typedarray "^0.0.6"
+concat-with-sourcemaps@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e"
+ integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==
+ dependencies:
+ source-map "^0.6.1"
+
config-chain@^1.1.12:
version "1.1.12"
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
@@ -2033,6 +2040,15 @@ gulp-cli@^2.2.0:
v8flags "^3.2.0"
yargs "^7.1.0"
+gulp-concat@^2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/gulp-concat/-/gulp-concat-2.6.1.tgz#633d16c95d88504628ad02665663cee5a4793353"
+ integrity sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=
+ dependencies:
+ concat-with-sourcemaps "^1.0.0"
+ through2 "^2.0.0"
+ vinyl "^2.0.0"
+
gulp-gzip@^1.4.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/gulp-gzip/-/gulp-gzip-1.4.2.tgz#0422a94014248655b5b1a9eea1c2abee1d4f4337"