mirror of
https://github.com/penpot/penpot.git
synced 2025-03-12 15:51:37 -05:00
✨ Simplify users loading on dashboard and workspace.
And fix some issues on teams settings page.
This commit is contained in:
parent
2dafbeddb0
commit
013c866137
13 changed files with 151 additions and 111 deletions
|
@ -185,39 +185,6 @@
|
||||||
(let [file (retrieve-file conn file-id)]
|
(let [file (retrieve-file conn file-id)]
|
||||||
(get-in file [:data :pages-index id]))))
|
(get-in file [:data :pages-index id]))))
|
||||||
|
|
||||||
;; --- Query: File users
|
|
||||||
|
|
||||||
(def ^:private sql:file-users
|
|
||||||
"select pf.id, pf.fullname, pf.photo
|
|
||||||
from profile as pf
|
|
||||||
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)
|
|
||||||
inner join project as p on (tpr.team_id = p.team_id)
|
|
||||||
inner join file as f on (p.id = f.project_id)
|
|
||||||
where f.id = ?")
|
|
||||||
|
|
||||||
(defn retrieve-file-users
|
|
||||||
[conn id]
|
|
||||||
(db/exec! conn [sql:file-users id id id]))
|
|
||||||
|
|
||||||
(s/def ::file-users
|
|
||||||
(s/keys :req-un [::profile-id ::id]))
|
|
||||||
|
|
||||||
(sq/defquery ::file-users
|
|
||||||
[{:keys [profile-id id] :as params}]
|
|
||||||
(db/with-atomic [conn db/pool]
|
|
||||||
(check-edition-permissions! conn profile-id id)
|
|
||||||
(retrieve-file-users conn id)))
|
|
||||||
|
|
||||||
;; --- Query: Shared Library Files
|
;; --- Query: Shared Library Files
|
||||||
|
|
||||||
|
|
|
@ -131,8 +131,29 @@
|
||||||
[conn team-id]
|
[conn team-id]
|
||||||
(db/exec! conn [sql:team-members team-id]))
|
(db/exec! conn [sql:team-members team-id]))
|
||||||
|
|
||||||
|
|
||||||
;; --- Query: Team Users
|
;; --- Query: Team Users
|
||||||
|
|
||||||
|
(declare retrieve-users)
|
||||||
|
(declare retrieve-team-for-file)
|
||||||
|
|
||||||
|
(s/def ::file-id ::us/uuid)
|
||||||
|
(s/def ::team-users
|
||||||
|
(s/and (s/keys :req-un [::profile-id]
|
||||||
|
:opt-un [::team-id ::file-id])
|
||||||
|
#(or (:team-id %) (:file-id %))))
|
||||||
|
|
||||||
|
(sq/defquery ::team-users
|
||||||
|
[{:keys [profile-id team-id file-id]}]
|
||||||
|
(with-open [conn (db/open)]
|
||||||
|
(if team-id
|
||||||
|
(do
|
||||||
|
(check-edition-permissions! conn profile-id team-id)
|
||||||
|
(retrieve-users conn team-id))
|
||||||
|
(let [{team-id :id} (retrieve-team-for-file conn file-id)]
|
||||||
|
(check-edition-permissions! conn profile-id team-id)
|
||||||
|
(retrieve-users conn team-id)))))
|
||||||
|
|
||||||
;; This is a similar query to team members but can contain more data
|
;; 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
|
;; because some user can be explicitly added to project or file (not
|
||||||
;; implemented in UI)
|
;; implemented in UI)
|
||||||
|
@ -156,12 +177,38 @@
|
||||||
inner join project as p on (f.project_id = p.id)
|
inner join project as p on (f.project_id = p.id)
|
||||||
where p.team_id = ?")
|
where p.team_id = ?")
|
||||||
|
|
||||||
(s/def ::team-users
|
(def sql:team-by-file
|
||||||
|
"select p.team_id as id
|
||||||
|
from project as p
|
||||||
|
join file as f on (p.id = f.project_id)
|
||||||
|
where f.id = ?")
|
||||||
|
|
||||||
|
(defn retrieve-users
|
||||||
|
[conn team-id]
|
||||||
|
(db/exec! conn [sql:team-users team-id team-id team-id]))
|
||||||
|
|
||||||
|
(defn retrieve-team-for-file
|
||||||
|
[conn file-id]
|
||||||
|
(->> [sql:team-by-file file-id]
|
||||||
|
(db/exec-one! conn)))
|
||||||
|
|
||||||
|
;; --- Query: Team Stats
|
||||||
|
|
||||||
|
(declare retrieve-team-stats)
|
||||||
|
|
||||||
|
(s/def ::team-stats
|
||||||
(s/keys :req-un [::profile-id ::team-id]))
|
(s/keys :req-un [::profile-id ::team-id]))
|
||||||
|
|
||||||
(sq/defquery ::team-users
|
(sq/defquery ::team-stats
|
||||||
[{:keys [profile-id team-id]}]
|
[{:keys [profile-id team-id]}]
|
||||||
(with-open [conn (db/open)]
|
(with-open [conn (db/open)]
|
||||||
(check-edition-permissions! conn profile-id team-id)
|
(check-read-permissions! conn profile-id team-id)
|
||||||
(db/exec! conn [sql:team-users team-id team-id team-id])))
|
(retrieve-team-stats conn team-id)))
|
||||||
|
|
||||||
|
(def sql:team-stats
|
||||||
|
"select (select count(*) from project where team_id = ?) as projects,
|
||||||
|
(select count(*) from file as f join project as p on (p.id = f.project_id) where p.team_id = ?) as files")
|
||||||
|
|
||||||
|
(defn retrieve-team-stats
|
||||||
|
[conn team-id]
|
||||||
|
(db/exec-one! conn [sql:team-stats team-id team-id]))
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
[app.db :as db]
|
[app.db :as db]
|
||||||
[app.services.queries :as sq]
|
[app.services.queries :as sq]
|
||||||
[app.services.queries.files :as files]
|
[app.services.queries.files :as files]
|
||||||
|
[app.services.queries.teams :as teams]
|
||||||
[clojure.spec.alpha :as s]))
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
;; --- Query: Viewer Bundle (by Page ID)
|
;; --- Query: Viewer Bundle (by Page ID)
|
||||||
|
@ -50,13 +51,14 @@
|
||||||
file (merge (dissoc file :data)
|
file (merge (dissoc file :data)
|
||||||
(select-keys (:data file) [:colors :media :typographies]))
|
(select-keys (:data file) [:colors :media :typographies]))
|
||||||
libs (files/retrieve-file-libraries conn false file-id)
|
libs (files/retrieve-file-libraries conn false file-id)
|
||||||
users (files/retrieve-file-users conn file-id)
|
users (teams/retrieve-users conn (:team-id project))
|
||||||
|
|
||||||
bundle {:file file
|
bundle {:file file
|
||||||
:page page
|
:page page
|
||||||
:users users
|
:users users
|
||||||
:project project
|
:project project
|
||||||
:libraries libs}]
|
:libraries libs}]
|
||||||
|
|
||||||
(if (string? token)
|
(if (string? token)
|
||||||
(do
|
(do
|
||||||
(check-shared-token! conn file-id page-id token)
|
(check-shared-token! conn file-id page-id token)
|
||||||
|
|
|
@ -460,6 +460,19 @@
|
||||||
"es" : "+ Nuevo proyecto"
|
"es" : "+ Nuevo proyecto"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"labels.num-of-projects" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : ["1 project", "%s projects"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"labels.num-of-files" : {
|
||||||
|
"translations" : {
|
||||||
|
"en" : ["1 file", "%s files"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"dashboard.no-matches-for" : {
|
"dashboard.no-matches-for" : {
|
||||||
"used-in" : [ "src/app/main/ui/dashboard/search.cljs:48" ],
|
"used-in" : [ "src/app/main/ui/dashboard/search.cljs:48" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
|
[app.main.data.users :as du]
|
||||||
[app.util.router :as rt]
|
[app.util.router :as rt]
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
|
@ -89,18 +90,14 @@
|
||||||
(->> (rp/query :team-members {:team-id id})
|
(->> (rp/query :team-members {:team-id id})
|
||||||
(rx/map #(partial fetched %)))))))
|
(rx/map #(partial fetched %)))))))
|
||||||
|
|
||||||
|
(defn fetch-team-stats
|
||||||
(defn fetch-team-users
|
[{:keys [id] :as team}]
|
||||||
[{:keys [id] :as params}]
|
|
||||||
(us/assert ::us/uuid id)
|
(us/assert ::us/uuid id)
|
||||||
(letfn [(fetched [users state]
|
(ptk/reify ::fetch-team-members
|
||||||
(->> (map #(avatars/assoc-avatar % :fullname) users)
|
ptk/WatchEvent
|
||||||
(d/index-by :id)
|
(watch [_ state stream]
|
||||||
(assoc-in state [:team-users id])))]
|
(let [fetched #(assoc-in %2 [:team-stats id] %1)]
|
||||||
(ptk/reify ::fetch-team-users
|
(->> (rp/query :team-stats {:team-id id})
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
(->> (rp/query :team-users {:team-id id})
|
|
||||||
(rx/map #(partial fetched %)))))))
|
(rx/map #(partial fetched %)))))))
|
||||||
|
|
||||||
;; --- Fetch Projects
|
;; --- Fetch Projects
|
||||||
|
@ -125,7 +122,7 @@
|
||||||
(let [profile (:profile state)]
|
(let [profile (:profile state)]
|
||||||
(->> (rx/merge (ptk/watch (fetch-team params) state stream)
|
(->> (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))
|
(ptk/watch (du/fetch-users {:team-id id}) state stream))
|
||||||
(rx/catch (fn [{:keys [type code] :as error}]
|
(rx/catch (fn [{:keys [type code] :as error}]
|
||||||
(cond
|
(cond
|
||||||
(and (= :not-found type)
|
(and (= :not-found type)
|
||||||
|
|
|
@ -2,25 +2,29 @@
|
||||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
;; 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/.
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
|
;; 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.data.users
|
(ns app.main.data.users
|
||||||
(:require
|
(:require
|
||||||
|
[app.config :as cfg]
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.spec :as us]
|
||||||
|
[app.main.data.media :as di]
|
||||||
|
[app.main.data.messages :as dm]
|
||||||
|
[app.main.repo :as rp]
|
||||||
|
[app.main.store :as st]
|
||||||
|
[app.util.avatars :as avatars]
|
||||||
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
[app.util.router :as rt]
|
||||||
|
[app.util.storage :refer [storage]]
|
||||||
|
[app.util.theme :as theme]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[cljs.spec.alpha :as s]
|
[cljs.spec.alpha :as s]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]))
|
||||||
[app.common.spec :as us]
|
|
||||||
[app.config :as cfg]
|
|
||||||
[app.main.store :as st]
|
|
||||||
[app.main.repo :as rp]
|
|
||||||
[app.main.data.messages :as dm]
|
|
||||||
[app.main.data.media :as di]
|
|
||||||
[app.util.router :as rt]
|
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
|
||||||
[app.util.storage :refer [storage]]
|
|
||||||
[app.util.avatars :as avatars]
|
|
||||||
[app.util.theme :as theme]))
|
|
||||||
|
|
||||||
;; --- Common Specs
|
;; --- Common Specs
|
||||||
|
|
||||||
|
@ -179,3 +183,18 @@
|
||||||
(rx/map (constantly fetch-profile))
|
(rx/map (constantly fetch-profile))
|
||||||
(rx/catch on-error))))))
|
(rx/catch on-error))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn fetch-users
|
||||||
|
[{:keys [team-id] :as params}]
|
||||||
|
(us/assert ::us/uuid team-id)
|
||||||
|
(letfn [(fetched [users state]
|
||||||
|
(->> (map #(avatars/assoc-avatar % :fullname) users)
|
||||||
|
(d/index-by :id)
|
||||||
|
(assoc state :users)))]
|
||||||
|
(ptk/reify ::fetch-team-users
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(->> (rp/query :team-users {:team-id team-id})
|
||||||
|
(rx/map #(partial fetched %)))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -203,7 +203,6 @@
|
||||||
:workspace-file
|
:workspace-file
|
||||||
:workspace-project
|
:workspace-project
|
||||||
:workspace-media-objects
|
:workspace-media-objects
|
||||||
:workspace-users
|
|
||||||
:workspace-persistence))
|
:workspace-persistence))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
|
|
|
@ -163,7 +163,7 @@
|
||||||
(ptk/reify ::handle-presence
|
(ptk/reify ::handle-presence
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [profiles (:workspace-users state)]
|
(let [profiles (:users state)]
|
||||||
(update state :workspace-presence update-sessions profiles))))))
|
(update state :workspace-presence update-sessions profiles))))))
|
||||||
|
|
||||||
(defn handle-pointer-update
|
(defn handle-pointer-update
|
||||||
|
|
|
@ -207,7 +207,7 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(->> (rx/zip (rp/query :file {:id file-id})
|
(->> (rx/zip (rp/query :file {:id file-id})
|
||||||
(rp/query :file-users {:id file-id})
|
(rp/query :team-users {:file-id file-id})
|
||||||
(rp/query :project {:id project-id})
|
(rp/query :project {:id project-id})
|
||||||
(rp/query :file-libraries {:file-id file-id}))
|
(rp/query :file-libraries {:file-id file-id}))
|
||||||
(rx/first)
|
(rx/first)
|
||||||
|
@ -238,11 +238,11 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [users (map avatars/assoc-profile-avatar users)]
|
(let [users (map avatars/assoc-profile-avatar users)]
|
||||||
(assoc state
|
(assoc state
|
||||||
|
:users (d/index-by :id users)
|
||||||
:workspace-undo {}
|
:workspace-undo {}
|
||||||
:workspace-project project
|
:workspace-project project
|
||||||
:workspace-file file
|
:workspace-file file
|
||||||
:workspace-data (:data file)
|
:workspace-data (:data file)
|
||||||
:workspace-users (d/index-by :id users)
|
|
||||||
:workspace-libraries (d/index-by :id libraries))))))
|
:workspace-libraries (d/index-by :id libraries))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -122,9 +122,6 @@
|
||||||
(def workspace-libraries
|
(def workspace-libraries
|
||||||
(l/derived :workspace-libraries st/state))
|
(l/derived :workspace-libraries st/state))
|
||||||
|
|
||||||
(def workspace-users
|
|
||||||
(l/derived :workspace-users st/state))
|
|
||||||
|
|
||||||
(def workspace-presence
|
(def workspace-presence
|
||||||
(l/derived :workspace-presence st/state))
|
(l/derived :workspace-presence st/state))
|
||||||
|
|
||||||
|
@ -214,3 +211,6 @@
|
||||||
(def comments-local
|
(def comments-local
|
||||||
(l/derived :comments-local st/state))
|
(l/derived :comments-local st/state))
|
||||||
|
|
||||||
|
(def users
|
||||||
|
(l/derived :users st/state))
|
||||||
|
|
||||||
|
|
|
@ -35,14 +35,8 @@
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.alpha :as mf]))
|
[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
|
(mf/defc comments-section
|
||||||
[{:keys [profile team]}]
|
[{:keys [profile team]}]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
(st/emitf (dcm/retrieve-unread-comment-threads (:id team))))
|
(st/emitf (dcm/retrieve-unread-comment-threads (:id team))))
|
||||||
|
@ -51,9 +45,7 @@
|
||||||
show-dropdown (mf/use-fn #(reset! show-dropdown? true))
|
show-dropdown (mf/use-fn #(reset! show-dropdown? true))
|
||||||
hide-dropdown (mf/use-fn #(reset! show-dropdown? false))
|
hide-dropdown (mf/use-fn #(reset! show-dropdown? false))
|
||||||
threads-map (mf/deref refs/comment-threads)
|
threads-map (mf/deref refs/comment-threads)
|
||||||
|
users (mf/deref refs/users)
|
||||||
users-ref (mf/use-memo (mf/deps team) #(team-members-ref team))
|
|
||||||
users (mf/deref users-ref)
|
|
||||||
|
|
||||||
tgroups (->> (vals threads-map)
|
tgroups (->> (vals threads-map)
|
||||||
(sort-by :modified-at)
|
(sort-by :modified-at)
|
||||||
|
@ -61,7 +53,6 @@
|
||||||
(dcm/apply-filters {} profile)
|
(dcm/apply-filters {} profile)
|
||||||
(dcm/group-threads-by-file-and-page))
|
(dcm/group-threads-by-file-and-page))
|
||||||
|
|
||||||
|
|
||||||
on-navigate
|
on-navigate
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(fn [thread]
|
(fn [thread]
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
[app.main.ui.dashboard.team-form]
|
[app.main.ui.dashboard.team-form]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [t tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.router :as rt]
|
[app.util.router :as rt]
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[cljs.spec.alpha :as s]
|
[cljs.spec.alpha :as s]
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
(mf/defc header
|
(mf/defc header
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [section locale team] :as props}]
|
[{:keys [section team] :as props}]
|
||||||
(let [go-members
|
(let [go-members
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
|
@ -57,19 +57,19 @@
|
||||||
[:header.dashboard-header
|
[:header.dashboard-header
|
||||||
[:div.dashboard-title
|
[:div.dashboard-title
|
||||||
[:h1 (cond
|
[:h1 (cond
|
||||||
members-section? (t locale "labels.members")
|
members-section? (tr "labels.members")
|
||||||
settings-section? (t locale "labels.settings")
|
settings-section? (tr "labels.settings")
|
||||||
nil)]]
|
nil)]]
|
||||||
[:nav
|
[:nav
|
||||||
[:ul
|
[:ul
|
||||||
[:li {:class (when members-section? "active")}
|
[:li {:class (when members-section? "active")}
|
||||||
[:a {:on-click go-members} (t locale "labels.members")]]
|
[:a {:on-click go-members} (tr "labels.members")]]
|
||||||
[:li {:class (when settings-section? "active")}
|
[:li {:class (when settings-section? "active")}
|
||||||
[:a {:on-click go-settings} (t locale "labels.settings")]]]]
|
[:a {:on-click go-settings} (tr "labels.settings")]]]]
|
||||||
|
|
||||||
(if members-section?
|
(if members-section?
|
||||||
[:a.btn-secondary.btn-small {:on-click invite-member}
|
[:a.btn-secondary.btn-small {:on-click invite-member}
|
||||||
(t locale "dashboard.invite-profile")]
|
(tr "dashboard.invite-profile")]
|
||||||
[:div])]))
|
[:div])]))
|
||||||
|
|
||||||
(s/def ::email ::us/email)
|
(s/def ::email ::us/email)
|
||||||
|
@ -220,13 +220,12 @@
|
||||||
[:& team-member {:member item :team team :profile profile :key (:id item)}])]]))
|
[:& team-member {:member item :team team :profile profile :key (:id item)}])]]))
|
||||||
|
|
||||||
(defn- members-ref
|
(defn- members-ref
|
||||||
[team-id]
|
[{:keys [id] :as team}]
|
||||||
(l/derived (l/in [:team-members team-id]) st/state))
|
(l/derived (l/in [:team-members id]) st/state))
|
||||||
|
|
||||||
(mf/defc team-members-page
|
(mf/defc team-members-page
|
||||||
[{:keys [team profile] :as props}]
|
[{:keys [team profile] :as props}]
|
||||||
(let [locale (mf/deref i18n/locale)
|
(let [members-ref (mf/use-memo (mf/deps team) #(members-ref team))
|
||||||
members-ref (mf/use-memo (mf/deps team) #(members-ref (:id team)))
|
|
||||||
members-map (mf/deref members-ref)]
|
members-map (mf/deref members-ref)]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
|
@ -234,24 +233,30 @@
|
||||||
(st/emitf (dd/fetch-team-members team)))
|
(st/emitf (dd/fetch-team-members team)))
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:& header {:locale locale
|
[:& header {:section :dashboard-team-members
|
||||||
:section :dashboard-team-members
|
|
||||||
:team team}]
|
:team team}]
|
||||||
[:section.dashboard-container.dashboard-team-members
|
[:section.dashboard-container.dashboard-team-members
|
||||||
[:& team-members {:locale locale
|
[:& team-members {:profile profile
|
||||||
:profile profile
|
|
||||||
:team team
|
:team team
|
||||||
:members-map members-map}]]]))
|
:members-map members-map}]]]))
|
||||||
|
|
||||||
|
(defn- stats-ref
|
||||||
|
[{:keys [id] :as team}]
|
||||||
|
(l/derived (l/in [:team-stats id]) st/state))
|
||||||
|
|
||||||
(mf/defc team-settings-page
|
(mf/defc team-settings-page
|
||||||
[{:keys [team profile] :as props}]
|
[{:keys [team profile] :as props}]
|
||||||
(let [locale (mf/deref i18n/locale)
|
(let [finput (mf/use-ref)
|
||||||
finput (mf/use-ref)
|
|
||||||
|
|
||||||
members-ref (mf/use-memo (mf/deps team) #(members-ref (:id team)))
|
members-ref (mf/use-memo (mf/deps team) #(members-ref team))
|
||||||
members-map (mf/deref members-ref)
|
members-map (mf/deref members-ref)
|
||||||
|
|
||||||
|
owner (->> (vals members-map)
|
||||||
|
(d/seek :is-owner))
|
||||||
|
|
||||||
|
stats-ref (mf/use-memo (mf/deps team) #(stats-ref team))
|
||||||
|
stats (mf/deref stats-ref)
|
||||||
|
|
||||||
on-image-click
|
on-image-click
|
||||||
(mf/use-callback #(dom/click (mf/ref-val finput)))
|
(mf/use-callback #(dom/click (mf/ref-val finput)))
|
||||||
|
|
||||||
|
@ -264,17 +269,17 @@
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps team)
|
(mf/deps team)
|
||||||
(st/emitf (dd/fetch-team-members team)))
|
(st/emitf (dd/fetch-team-members team)
|
||||||
|
(dd/fetch-team-stats team)))
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:& header {:locale locale
|
[:& header {:section :dashboard-team-settings
|
||||||
:section :dashboard-team-settings
|
|
||||||
:team team}]
|
:team team}]
|
||||||
[:section.dashboard-container.dashboard-team-settings
|
[:section.dashboard-container.dashboard-team-settings
|
||||||
[:div.team-settings
|
[:div.team-settings
|
||||||
[:div.horizontal-blocks
|
[:div.horizontal-blocks
|
||||||
[:div.block.info-block
|
[:div.block.info-block
|
||||||
[:div.label (t locale "dashboard.team-info")]
|
[:div.label (tr "dashboard.team-info")]
|
||||||
[:div.name (:name team)]
|
[:div.name (:name team)]
|
||||||
[:div.icon
|
[:div.icon
|
||||||
[:span.update-overlay {:on-click on-image-click} i/exit]
|
[:span.update-overlay {:on-click on-image-click} i/exit]
|
||||||
|
@ -285,19 +290,19 @@
|
||||||
:on-selected on-file-selected}]]]
|
:on-selected on-file-selected}]]]
|
||||||
|
|
||||||
[:div.block.owner-block
|
[:div.block.owner-block
|
||||||
[:div.label (t locale "dashboard.team-members")]
|
[:div.label (tr "dashboard.team-members")]
|
||||||
[:div.owner
|
[:div.owner
|
||||||
[:span.icon [:img {:src (cfg/resolve-media-path (:photo-uri profile))}]]
|
[:span.icon [:img {:src (cfg/resolve-media-path (:photo owner))}]]
|
||||||
[:span.text (str (:fullname profile) " (" (t locale "labels.owner") ")") ]]
|
[:span.text (str (:name owner) " (" (tr "labels.owner") ")") ]]
|
||||||
[:div.summary
|
[:div.summary
|
||||||
[:span.icon i/user]
|
[:span.icon i/user]
|
||||||
[:span.text (t locale "dashboard.num-of-members" (count members-map))]]]
|
[:span.text (tr "dashboard.num-of-members" (count members-map))]]]
|
||||||
|
|
||||||
[:div.block.stats-block
|
[:div.block.stats-block
|
||||||
[:div.label (t locale "dashboard.team-projects")]
|
[:div.label (tr "dashboard.team-projects")]
|
||||||
[:div.projects
|
[:div.projects
|
||||||
[:span.icon i/folder]
|
[:span.icon i/folder]
|
||||||
[:span.text "4 projects"]]
|
[:span.text (tr "labels.num-of-projects" (i18n/c (:projects stats)))]]
|
||||||
[:div.files
|
[:div.files
|
||||||
[:span.icon i/file-html]
|
[:span.icon i/file-html]
|
||||||
[:span.text "4 files"]]]]]]]))
|
[:span.text (tr "labels.num-of-files" (i18n/c (:files stats)))]]]]]]]))
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
pos-y (* (- (:y vbox)) zoom)
|
pos-y (* (- (:y vbox)) zoom)
|
||||||
|
|
||||||
profile (mf/deref refs/profile)
|
profile (mf/deref refs/profile)
|
||||||
users (mf/deref refs/workspace-users)
|
users (mf/deref refs/users)
|
||||||
local (mf/deref refs/comments-local)
|
local (mf/deref refs/comments-local)
|
||||||
threads-map (mf/deref threads-ref)
|
threads-map (mf/deref threads-ref)
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@
|
||||||
[]
|
[]
|
||||||
(let [threads-map (mf/deref threads-ref)
|
(let [threads-map (mf/deref threads-ref)
|
||||||
profile (mf/deref refs/profile)
|
profile (mf/deref refs/profile)
|
||||||
users (mf/deref refs/workspace-users)
|
users (mf/deref refs/users)
|
||||||
local (mf/deref refs/comments-local)
|
local (mf/deref refs/comments-local)
|
||||||
options? (mf/use-state false)
|
options? (mf/use-state false)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue