diff --git a/client/src/app/components/users/users-table/users-table.component.html b/client/src/app/components/users/users-table/users-table.component.html
index 287e4ebc6..1d1141b7c 100644
--- a/client/src/app/components/users/users-table/users-table.component.html
+++ b/client/src/app/components/users/users-table/users-table.component.html
@@ -188,12 +188,12 @@
- {{ user.statsHash.submittedEvidenceItems }}
+ {{ user.evidenceCount }}
|
- {{ user.statsHash.revisions }}
+ {{ user.revisionCount }}
|
diff --git a/client/src/app/generated/server.model.graphql b/client/src/app/generated/server.model.graphql
index 156e2029c..b2ac1ba3b 100644
--- a/client/src/app/generated/server.model.graphql
+++ b/client/src/app/generated/server.model.graphql
@@ -1399,33 +1399,96 @@ type BrowseTherapyEdge {
}
type BrowseUser {
- acceptedLicense: Boolean
- areaOfExpertise: String
+ areaOfExpertise: AreaOfExpertise
bio: String
- countryId: Int
- createdAt: ISO8601DateTime
- deleted: Boolean
- deletedAt: ISO8601DateTime
+ country: Country
displayName: String!
email: String
+ events(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): EventConnection!
evidenceCount: Int!
facebookProfile: String
id: Int!
- lastSeenAt: ISO8601DateTime
linkedinProfile: String
mostRecentActivityTimestamp: ISO8601DateTime
+ mostRecentConflictOfInterestStatement: Coi
+ mostRecentEvent: Event
mostRecentOrganizationId: Int
name: String
+
+ """
+ Filterable list of notifications for the logged in user.
+ """
+ notifications(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Filter the response to include only notifications generated by certain actions (ex: commenting).
+ """
+ eventType: EventAction
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Filter the response to include only notifications generated by a particular subscription.
+ """
+ includeSeen: Boolean = false
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+
+ """
+ Filter the response to include only notifications of a certain type (ex: mentions).
+ """
+ notificationType: NotificationReason
+
+ """
+ Filter the response to include only notifications generated by a particular subscription.
+ """
+ subscriptionId: Int
+ ): NotificationConnection
orcid: String
organizations: [Organization!]!
profileImagePath(size: Int = 56): String
+ ranks: Ranks!
revisionCount: Int!
- role: String!
- signupComplete: Boolean
+ role: UserRole!
+ statsHash: Stats!
twitterHandle: String
- updatedAt: ISO8601DateTime
url: String
- username: String
+ username: String!
}
"""
diff --git a/client/src/app/generated/server.schema.json b/client/src/app/generated/server.schema.json
index d55e06ffa..de75f5765 100644
--- a/client/src/app/generated/server.schema.json
+++ b/client/src/app/generated/server.schema.json
@@ -6701,25 +6701,13 @@
"name": "BrowseUser",
"description": null,
"fields": [
- {
- "name": "acceptedLicense",
- "description": null,
- "args": [],
- "type": {
- "kind": "SCALAR",
- "name": "Boolean",
- "ofType": null
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
{
"name": "areaOfExpertise",
"description": null,
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "String",
+ "kind": "ENUM",
+ "name": "AreaOfExpertise",
"ofType": null
},
"isDeprecated": false,
@@ -6738,55 +6726,112 @@
"deprecationReason": null
},
{
- "name": "countryId",
+ "name": "country",
"description": null,
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "Int",
+ "kind": "OBJECT",
+ "name": "Country",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "createdAt",
+ "name": "displayName",
"description": null,
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "ISO8601DateTime",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "deleted",
+ "name": "email",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
- "name": "Boolean",
+ "name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "deletedAt",
+ "name": "events",
"description": null,
- "args": [],
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
"type": {
- "kind": "SCALAR",
- "name": "ISO8601DateTime",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "EventConnection",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "displayName",
+ "name": "evidenceCount",
"description": null,
"args": [],
"type": {
@@ -6794,7 +6839,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "String",
+ "name": "Int",
"ofType": null
}
},
@@ -6802,7 +6847,7 @@
"deprecationReason": null
},
{
- "name": "email",
+ "name": "facebookProfile",
"description": null,
"args": [],
"type": {
@@ -6814,7 +6859,7 @@
"deprecationReason": null
},
{
- "name": "evidenceCount",
+ "name": "id",
"description": null,
"args": [],
"type": {
@@ -6830,7 +6875,7 @@
"deprecationReason": null
},
{
- "name": "facebookProfile",
+ "name": "linkedinProfile",
"description": null,
"args": [],
"type": {
@@ -6842,23 +6887,7 @@
"deprecationReason": null
},
{
- "name": "id",
- "description": null,
- "args": [],
- "type": {
- "kind": "NON_NULL",
- "name": null,
- "ofType": {
- "kind": "SCALAR",
- "name": "Int",
- "ofType": null
- }
- },
- "isDeprecated": false,
- "deprecationReason": null
- },
- {
- "name": "lastSeenAt",
+ "name": "mostRecentActivityTimestamp",
"description": null,
"args": [],
"type": {
@@ -6870,24 +6899,24 @@
"deprecationReason": null
},
{
- "name": "linkedinProfile",
+ "name": "mostRecentConflictOfInterestStatement",
"description": null,
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "String",
+ "kind": "OBJECT",
+ "name": "Coi",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "mostRecentActivityTimestamp",
+ "name": "mostRecentEvent",
"description": null,
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "ISO8601DateTime",
+ "kind": "OBJECT",
+ "name": "Event",
"ofType": null
},
"isDeprecated": false,
@@ -6917,6 +6946,115 @@
"isDeprecated": false,
"deprecationReason": null
},
+ {
+ "name": "notifications",
+ "description": "Filterable list of notifications for the logged in user.",
+ "args": [
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "notificationType",
+ "description": "Filter the response to include only notifications of a certain type (ex: mentions).",
+ "type": {
+ "kind": "ENUM",
+ "name": "NotificationReason",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "eventType",
+ "description": "Filter the response to include only notifications generated by certain actions (ex: commenting).",
+ "type": {
+ "kind": "ENUM",
+ "name": "EventAction",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "subscriptionId",
+ "description": "Filter the response to include only notifications generated by a particular subscription.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "includeSeen",
+ "description": "Filter the response to include only notifications generated by a particular subscription.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Boolean",
+ "ofType": null
+ },
+ "defaultValue": "false",
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "NotificationConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
{
"name": "orcid",
"description": null,
@@ -6979,15 +7117,15 @@
"deprecationReason": null
},
{
- "name": "revisionCount",
+ "name": "ranks",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
- "kind": "SCALAR",
- "name": "Int",
+ "kind": "OBJECT",
+ "name": "Ranks",
"ofType": null
}
},
@@ -6995,7 +7133,7 @@
"deprecationReason": null
},
{
- "name": "role",
+ "name": "revisionCount",
"description": null,
"args": [],
"type": {
@@ -7003,7 +7141,7 @@
"name": null,
"ofType": {
"kind": "SCALAR",
- "name": "String",
+ "name": "Int",
"ofType": null
}
},
@@ -7011,36 +7149,44 @@
"deprecationReason": null
},
{
- "name": "signupComplete",
+ "name": "role",
"description": null,
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "Boolean",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "UserRole",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "twitterHandle",
+ "name": "statsHash",
"description": null,
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Stats",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
},
{
- "name": "updatedAt",
+ "name": "twitterHandle",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
- "name": "ISO8601DateTime",
+ "name": "String",
"ofType": null
},
"isDeprecated": false,
@@ -7063,9 +7209,13 @@
"description": null,
"args": [],
"type": {
- "kind": "SCALAR",
- "name": "String",
- "ofType": null
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
},
"isDeprecated": false,
"deprecationReason": null
diff --git a/server/app/graphql/types/browse_tables/browse_user_type.rb b/server/app/graphql/types/browse_tables/browse_user_type.rb
index b30c4cd21..5afe45824 100644
--- a/server/app/graphql/types/browse_tables/browse_user_type.rb
+++ b/server/app/graphql/types/browse_tables/browse_user_type.rb
@@ -1,36 +1,12 @@
module Types::BrowseTables
- class BrowseUserType < Types::BaseObject
+ class BrowseUserType < Types::Entities::UserType
connection_type_class(Types::Connections::BrowseTableConnection)
@@role_mapping = User.roles.invert
@@area_mapping = User.area_of_expertises.invert
- field :id, Int, null: false
- field :email, String, null: true
- field :name, String, null: true
- field :url, String, null: true
- field :username, String, null: true
- field :display_name, String, null: false
- field :created_at, GraphQL::Types::ISO8601DateTime, null: true
- field :updated_at, GraphQL::Types::ISO8601DateTime, null: true
- field :orcid, String, null: true
- field :area_of_expertise, String, null: true
- field :deleted, Boolean, null: true
- field :deleted_at, GraphQL::Types::ISO8601DateTime, null: true
- field :role, String, null: false
- field :last_seen_at, GraphQL::Types::ISO8601DateTime, null: true
- field :twitter_handle, String, null: true
- field :facebook_profile, String, null: true
- field :linkedin_profile, String, null: true
- field :accepted_license, Boolean, null: true
- field :bio, String, null: true
- field :signup_complete, Boolean, null: true
- field :country_id, Int, null: true
- field :most_recent_organization_id, Int, null: true
- field :most_recent_activity_timestamp, GraphQL::Types::ISO8601DateTime, null: true
field :revision_count, Int, null: false
field :evidence_count, Int, null: false
- field :organizations, [Types::Entities::OrganizationType], null: false
def area_of_expertise
@@area_mapping[object.area_of_expertise]
@@ -41,18 +17,11 @@ def role
end
def organizations
- Loaders::AssociationLoader.for(User, :organizations).load(object)
- end
-
- profile_image_sizes = [256, 128, 64, 32, 18, 12]
- field :profile_image_path, String, null: true do
- argument :size, Int, required: false, default_value: 56,
- validates: {
- inclusion: {
- in: profile_image_sizes,
- message: "Size must be one of [#{profile_image_sizes.join(',')}]"
- }
- }
+ Loaders::AssociationLoader.for(MaterializedViews::UserBrowseTableRow, :affiliations).load(object).then do |affil|
+ affil.map do |a|
+ Loaders::AssociationLoader.for(Affiliation, :organization).load(a)
+ end
+ end
end
end
-end
\ No newline at end of file
+end
diff --git a/server/app/jobs/refresh_materialized_views.rb b/server/app/jobs/refresh_materialized_views.rb
index af38f0b4d..eedef17e3 100644
--- a/server/app/jobs/refresh_materialized_views.rb
+++ b/server/app/jobs/refresh_materialized_views.rb
@@ -9,7 +9,9 @@ def perform(kwargs)
MaterializedViews::SourceBrowseTableRow,
MaterializedViews::VariantBrowseTableRow,
MaterializedViews::VariantGroupBrowseTableRow,
- MaterializedViews::MolecularProfileBrowseTableRow
+ MaterializedViews::MolecularProfileBrowseTableRow,
+ MaterializedViews::UserBrowseTableRow,
+ MaterializedViews::OrganizationBrowseTableRow
]
elsif views == 'features_only'
[
@@ -21,7 +23,9 @@ def perform(kwargs)
MaterializedViews::SourceBrowseTableRow,
MaterializedViews::VariantBrowseTableRow,
MaterializedViews::VariantGroupBrowseTableRow,
- MaterializedViews::MolecularProfileBrowseTableRow
+ MaterializedViews::MolecularProfileBrowseTableRow,
+ MaterializedViews::UserBrowseTableRow,
+ MaterializedViews::OrganizationBrowseTableRow
]
else
[]
diff --git a/server/app/models/materialized_views/user_browse_table_row.rb b/server/app/models/materialized_views/user_browse_table_row.rb
index 5c3c5c569..06ed321f3 100644
--- a/server/app/models/materialized_views/user_browse_table_row.rb
+++ b/server/app/models/materialized_views/user_browse_table_row.rb
@@ -1,2 +1,4 @@
class MaterializedViews::UserBrowseTableRow < MaterializedViews::MaterializedView
+ has_many :affiliations, primary_key: :id, foreign_key: :user_id
+ has_many :organizations, through: :affiliations
end