Add stats, add filters, add time period selector, fix mobile view
This commit is contained in:
parent
771d593372
commit
9c4a1ecd68
|
@ -1,17 +1,79 @@
|
|||
.directory {
|
||||
.filter-name {
|
||||
float: none;
|
||||
}
|
||||
|
||||
.filters {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
> span {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.group-filter:not(.active) .select-kit-header {
|
||||
color: $primary-high;
|
||||
}
|
||||
}
|
||||
|
||||
.user-card-directory {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
||||
.user-card {
|
||||
z-index: z("base");
|
||||
position: relative;
|
||||
left: auto;
|
||||
width: 100%;
|
||||
box-shadow: none;
|
||||
margin: 0;
|
||||
|
||||
.badge-section {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.usercard-controls {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-card-container {
|
||||
// width: calc(50% - 40px);
|
||||
flex-grow: 1;
|
||||
// flex-basis: min-content;
|
||||
// width: 500px;
|
||||
margin: 50px 5px 10px 5px;
|
||||
background-color: $secondary;
|
||||
box-shadow: shadow("card");
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.user-card-directory-footer {
|
||||
background-color: $secondary;
|
||||
padding: 0px 10px 10px 10px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
|
||||
.user-card {
|
||||
position: relative;
|
||||
left: auto;
|
||||
width: 100%;
|
||||
|
||||
.stat {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 2px;
|
||||
|
||||
.label {
|
||||
font-size: $font-down-2;
|
||||
|
||||
.d-icon {
|
||||
margin-right: 0.2em;
|
||||
color: $primary-medium;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-card-container {
|
||||
width: calc(50% - 40px);
|
||||
margin: 50px 20px 10px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,54 +6,91 @@ import { ajax } from "discourse/lib/ajax";
|
|||
|
||||
export default {
|
||||
name: "user-card-directory",
|
||||
initialize(){
|
||||
initialize(container) {
|
||||
// This component provides a responsive template
|
||||
// Delete the core mobile one
|
||||
delete Ember.TEMPLATES["mobile/users"];
|
||||
|
||||
withPluginApi("0.8.7", api => {
|
||||
api.modifyClass("route:users", {
|
||||
resetController(controller, isExisting) {
|
||||
this._super(controller, isExisting);
|
||||
if (isExisting) {
|
||||
controller.set("cachedUserCardInfo", {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
api.modifyClass("controller:users", {
|
||||
cachedUserCardInfo: {},
|
||||
|
||||
|
||||
stats: [
|
||||
{ name: "likes_received", icon: "heart" },
|
||||
{ name: "likes_given", icon: "heart" },
|
||||
{ name: "topic_count" },
|
||||
{ name: "post_count" },
|
||||
{ name: "topics_entered" },
|
||||
{ name: "posts_read" },
|
||||
{ name: "days_visited" }
|
||||
],
|
||||
|
||||
@discourseComputed("site.groups")
|
||||
availableGroups(groups) {
|
||||
return groups
|
||||
.map(g => {
|
||||
// prevents group "everyone" to be listed
|
||||
if (g.id !== 0) {
|
||||
return { name: g.name, value: g.name };
|
||||
}
|
||||
})
|
||||
.filter(Boolean);
|
||||
},
|
||||
|
||||
@discourseComputed("model.content.@each")
|
||||
userCards(allUsers) {
|
||||
const toLoad = [];
|
||||
const userCardInfos = allUsers.map(u => {
|
||||
if (this.cachedUserCardInfo[u.id]) {
|
||||
return this.cachedUserCardInfo[u.id];
|
||||
}
|
||||
|
||||
const userCardInfo = this.cachedUserCardInfo[u.id] = EmberObject.create({
|
||||
user: User.create(u.user),
|
||||
loading: true
|
||||
});
|
||||
|
||||
toLoad.push(userCardInfo);
|
||||
|
||||
return userCardInfo;
|
||||
});
|
||||
|
||||
const loadMax = 50;
|
||||
|
||||
while (toLoad.length > 0) {
|
||||
const thisBatch = toLoad.splice(0, loadMax);
|
||||
const promise = ajax("/user-cards.json", {
|
||||
data: { user_ids: thisBatch.map(uc => uc.user.id).join(",") }
|
||||
});
|
||||
thisBatch.forEach(uc => {
|
||||
const convertedPromise = promise.then(data => {
|
||||
// Find the correct user from users, and put it in the user attribute
|
||||
// Use Object.assign to avoid contaminating the source object
|
||||
return Object.assign({}, data, {
|
||||
user: data.users.find(u => u.id === uc.user.id)
|
||||
});
|
||||
});
|
||||
return uc.user
|
||||
.findDetails({ existingRequest: convertedPromise })
|
||||
.then(() => uc.set("loading", false));
|
||||
});
|
||||
const toLoad = [];
|
||||
const userCardInfos = allUsers.map(u => {
|
||||
if (this.cachedUserCardInfo[u.id]) {
|
||||
return this.cachedUserCardInfo[u.id];
|
||||
}
|
||||
|
||||
return userCardInfos;
|
||||
}
|
||||
const userCardInfo = (this.cachedUserCardInfo[
|
||||
u.id
|
||||
] = EmberObject.create({
|
||||
user: User.create(u.user),
|
||||
directoryItem: u,
|
||||
loading: true
|
||||
}));
|
||||
|
||||
toLoad.push(userCardInfo);
|
||||
|
||||
return userCardInfo;
|
||||
});
|
||||
|
||||
const loadMax = 50;
|
||||
|
||||
while (toLoad.length > 0) {
|
||||
const thisBatch = toLoad.splice(0, loadMax);
|
||||
const promise = ajax("/user-cards.json", {
|
||||
data: { user_ids: thisBatch.map(uc => uc.user.id).join(",") }
|
||||
});
|
||||
thisBatch.forEach(uc => {
|
||||
const convertedPromise = promise.then(data => {
|
||||
// Find the correct user from users, and put it in the user attribute
|
||||
// Use Object.assign to avoid contaminating the source object
|
||||
return Object.assign({}, data, {
|
||||
user: data.users.find(u => u.id === uc.user.id)
|
||||
});
|
||||
});
|
||||
return uc.user
|
||||
.findDetails({ existingRequest: convertedPromise })
|
||||
.then(() => uc.set("loading", false));
|
||||
});
|
||||
}
|
||||
|
||||
return userCardInfos;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -3,8 +3,20 @@
|
|||
<div class="container">
|
||||
<div class='directory'>
|
||||
{{plugin-outlet name="users-top" connectorTagName='div' args=(hash model=model)}}
|
||||
<div class='clearfix'>
|
||||
{{text-field value=nameInput placeholderKey="directory.filter_name" class="filter-name no-blur"}}
|
||||
|
||||
<div class="filters">
|
||||
{{period-chooser period=period onChange=(action (mut period))}}
|
||||
</div>
|
||||
<div class="filters">
|
||||
<span class="group-filter {{if group "active"}}">
|
||||
{{combo-box content=availableGroups
|
||||
value=group
|
||||
options=(hash clearable=true none=(theme-prefix 'filter_by_group'))
|
||||
valueAttribute="value"}}
|
||||
</span>
|
||||
<span class="username-filter">
|
||||
{{text-field value=nameInput placeholderKey="directory.filter_name" class="filter-name no-blur"}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{{#conditional-loading-spinner condition=model.loading}}
|
||||
|
@ -18,6 +30,18 @@
|
|||
loading=userCard.loading
|
||||
username=userCard.user.username
|
||||
}}
|
||||
<div class='user-card-directory-footer'>
|
||||
{{#each stats as |stat|}}
|
||||
<span class="stat stat-{{stat.name}}">
|
||||
<span class="value">
|
||||
{{number (get userCard.directoryItem stat.name)}}
|
||||
</span>
|
||||
<span class="label">
|
||||
{{directory-toggle field=stat.name order=order asc=asc icon=stat.icon tagName="span"}}
|
||||
</span>
|
||||
</span>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
en:
|
||||
theme_metadata:
|
||||
description: Replaces the user directory with a grid of user cards
|
||||
description: Replaces the user directory with a grid of user cards
|
||||
filter_by_group: filter by group
|
Loading…
Reference in New Issue