mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
🐛 Fixed infinite scroll on the team screen (#1095)
closes https://github.com/TryGhost/Ghost/issues/10307 - removed infinite scroll from the team screen - adjusted team screen behaviour to pull from the local cache and update in the background to speed up navigation to the screen - use `{{vertical-collection}}` to render the users list for faster initial render with many users
This commit is contained in:
parent
5e3de1c333
commit
434e8ba2f7
4 changed files with 77 additions and 78 deletions
|
@ -1,18 +1,17 @@
|
|||
/* eslint-disable ghost/ember/alias-model-in-controller */
|
||||
import Controller from '@ember/controller';
|
||||
import RSVP from 'rsvp';
|
||||
import {alias, sort} from '@ember/object/computed';
|
||||
import {computed} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {sort} from '@ember/object/computed';
|
||||
import {task} from 'ember-concurrency';
|
||||
|
||||
export default Controller.extend({
|
||||
session: service(),
|
||||
store: service(),
|
||||
|
||||
showInviteUserModal: false,
|
||||
|
||||
activeUsers: null,
|
||||
suspendedUsers: null,
|
||||
invites: null,
|
||||
|
||||
inviteOrder: null,
|
||||
userOrder: null,
|
||||
|
||||
|
@ -22,17 +21,67 @@ export default Controller.extend({
|
|||
this.userOrder = ['name', 'email'];
|
||||
},
|
||||
|
||||
currentUser: alias('model'),
|
||||
|
||||
sortedInvites: sort('filteredInvites', 'inviteOrder'),
|
||||
sortedActiveUsers: sort('activeUsers', 'userOrder'),
|
||||
sortedSuspendedUsers: sort('suspendedUsers', 'userOrder'),
|
||||
|
||||
invites: computed(function () {
|
||||
return this.store.peekAll('invite');
|
||||
}),
|
||||
|
||||
filteredInvites: computed('invites.@each.isNew', function () {
|
||||
return this.get('invites').filterBy('isNew', false);
|
||||
return this.invites.filterBy('isNew', false);
|
||||
}),
|
||||
|
||||
allUsers: computed(function () {
|
||||
return this.store.peekAll('user');
|
||||
}),
|
||||
|
||||
activeUsers: computed('allUsers.@each.status', function () {
|
||||
return this.allUsers.filter((user) => {
|
||||
return user.status !== 'inactive';
|
||||
});
|
||||
}),
|
||||
|
||||
suspendedUsers: computed('allUsers.@each.status', function () {
|
||||
return this.allUsers.filter((user) => {
|
||||
return user.status === 'inactive';
|
||||
});
|
||||
}),
|
||||
|
||||
actions: {
|
||||
toggleInviteUserModal() {
|
||||
this.toggleProperty('showInviteUserModal');
|
||||
}
|
||||
},
|
||||
|
||||
backgroundUpdate: task(function* () {
|
||||
let users = this.fetchUsers.perform();
|
||||
let invites = this.fetchInvites.perform();
|
||||
let roles = this.fetchRoles.perform();
|
||||
|
||||
try {
|
||||
yield RSVP.all([users, invites, roles]);
|
||||
} catch (error) {
|
||||
this.send('error', error);
|
||||
}
|
||||
}),
|
||||
|
||||
fetchUsers: task(function* () {
|
||||
yield this.store.query('user', {limit: 'all'});
|
||||
}),
|
||||
|
||||
fetchInvites: task(function* () {
|
||||
if (this.currentUser.isAuthorOrContributor) {
|
||||
return;
|
||||
}
|
||||
|
||||
return yield this.store.query('invite', {limit: 'all'});
|
||||
}),
|
||||
|
||||
fetchRoles: task(function* () {
|
||||
return yield this.store.findAll('role');
|
||||
})
|
||||
});
|
||||
|
|
|
@ -1,58 +1,27 @@
|
|||
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
|
||||
import CurrentUserSettings from 'ghost-admin/mixins/current-user-settings';
|
||||
import RSVP from 'rsvp';
|
||||
import styleBody from 'ghost-admin/mixins/style-body';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
|
||||
infinity: service(),
|
||||
session: service(),
|
||||
|
||||
titleToken: 'Team',
|
||||
classNames: ['view-team'],
|
||||
|
||||
modelPath: 'controller.activeUsers',
|
||||
perPage: 15,
|
||||
|
||||
model() {
|
||||
return this.get('session.user').then((user) => {
|
||||
let modelPath = this.get('modelPath');
|
||||
let perPage = this.get('perPage');
|
||||
|
||||
let modelPromises = {
|
||||
activeUsers: this.infinity.model('user', {
|
||||
modelPath,
|
||||
perPage,
|
||||
filter: 'status:-inactive',
|
||||
startingPage: 1,
|
||||
perPageParam: 'limit',
|
||||
totalPagesParam: 'meta.pagination.pages'
|
||||
})
|
||||
};
|
||||
|
||||
// authors do not have permission to hit the invites or suspended users endpoint
|
||||
if (!user.get('isAuthorOrContributor')) {
|
||||
modelPromises.invites = this.store.query('invite', {limit: 'all'})
|
||||
.then(() => this.store.peekAll('invite'));
|
||||
|
||||
// fetch suspended users separately so that infinite scroll still works
|
||||
modelPromises.suspendedUsers = this.store.query('user', {limit: 'all', filter: 'status:inactive'});
|
||||
}
|
||||
|
||||
// we need to load the roles into ember cache
|
||||
// invites return role_id only and we do not offer a /role/:id endpoint
|
||||
modelPromises.roles = this.get('store').query('role', {});
|
||||
|
||||
return RSVP.hash(modelPromises);
|
||||
});
|
||||
return this.session.user;
|
||||
},
|
||||
|
||||
setupController(controller, models) {
|
||||
controller.setProperties(models);
|
||||
setupController(controller) {
|
||||
this._super(...arguments);
|
||||
controller.backgroundUpdate.perform();
|
||||
},
|
||||
|
||||
actions: {
|
||||
reload() {
|
||||
this.refresh();
|
||||
this.controller.backgroundUpdate.perform();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
<section class="gh-canvas">
|
||||
<header class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>Team members</h2>
|
||||
{{!-- Do not show Invite user button to authors --}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
<section class="view-actions">
|
||||
<button class="gh-btn gh-btn-green" {{action "toggleInviteUserModal"}} ><span>Invite People</span></button>
|
||||
</section>
|
||||
{{/unless}}
|
||||
</header>
|
||||
|
||||
<div class="gh-content">
|
||||
{{gh-loading-spinner}}
|
||||
</div>
|
||||
</section>
|
|
@ -2,7 +2,7 @@
|
|||
<header class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>Team members</h2>
|
||||
{{!-- Do not show Invite user button to authors --}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
{{#unless currentUser.isAuthorOrContributor}}
|
||||
<section class="view-actions">
|
||||
<button class="gh-btn gh-btn-green" {{action "toggleInviteUserModal"}} ><span>Invite People</span></button>
|
||||
</section>
|
||||
|
@ -16,9 +16,8 @@
|
|||
{{/if}}
|
||||
|
||||
<section class="gh-team">
|
||||
|
||||
{{!-- Show invited users to everyone except authors --}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
{{#unless currentUser.isAuthorOrContributor}}
|
||||
{{#if invites}}
|
||||
<section class="apps-grid-container gh-invited-users" data-test-invited-users>
|
||||
<span class="apps-grid-title">Invited users</span>
|
||||
|
@ -75,32 +74,29 @@
|
|||
<section class="apps-grid-container gh-active-users" data-test-active-users>
|
||||
<span class="apps-grid-title">Active users</span>
|
||||
<div class="apps-grid">
|
||||
{{!-- For authors/contributors only show their own user --}}
|
||||
{{#if session.user.isAuthorOrContributor}}
|
||||
{{#with session.user as |user|}}
|
||||
{{#gh-user-active user=user as |component|}}
|
||||
{{gh-user-list-item user=user component=component}}
|
||||
{{!-- For authors/contributors, only show their own user --}}
|
||||
{{#if currentUser.isAuthorOrContributor}}
|
||||
{{#gh-user-active user=currentUser as |component|}}
|
||||
{{gh-user-list-item user=currentUser component=component}}
|
||||
{{/gh-user-active}}
|
||||
{{/with}}
|
||||
{{else}}
|
||||
{{#each sortedActiveUsers key="id" as |user|}}
|
||||
{{#vertical-collection sortedActiveUsers
|
||||
key="id"
|
||||
containerSelector=".gh-main"
|
||||
estimateHeight=75
|
||||
as |user|
|
||||
}}
|
||||
{{#gh-user-active user=user as |component|}}
|
||||
{{gh-user-list-item user=user component=component}}
|
||||
{{/gh-user-active}}
|
||||
{{/each}}
|
||||
{{/vertical-collection}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{gh-infinity-loader
|
||||
infinityModel=activeUsers
|
||||
scrollable=".gh-main"
|
||||
triggerOffset=500}}
|
||||
|
||||
</section>
|
||||
|
||||
{{!-- Don't show if we have no suspended users or logged in as an author --}}
|
||||
{{#if (and suspendedUsers (not session.user.isAuthorOrContributor))}}
|
||||
{{#if (and suspendedUsers (not currentUser.isAuthorOrContributor))}}
|
||||
<section class="apps-grid-container gh-active-users" data-test-suspended-users>
|
||||
<span class="apps-grid-title">Suspended users</span>
|
||||
<div class="apps-grid">
|
||||
|
|
Loading…
Add table
Reference in a new issue