mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-20 00:08:02 +01:00
Wrong number on the project page regarding members in that project (#1917)
* Fix project member count * Fix * Add editors to projects
This commit is contained in:
parent
9676165de9
commit
037b8eacd3
@ -29,6 +29,11 @@ export interface IEnvironmentProjectLink {
|
||||
projectId: string;
|
||||
}
|
||||
|
||||
export interface IProjectMembersCount {
|
||||
count: number;
|
||||
project: string;
|
||||
}
|
||||
|
||||
class ProjectStore implements IProjectStore {
|
||||
private db: Knex;
|
||||
|
||||
@ -89,12 +94,11 @@ class ProjectStore implements IProjectStore {
|
||||
);
|
||||
projectTimer();
|
||||
const memberTimer = this.timer('getMemberCount');
|
||||
const memberCount = await this.db.raw(
|
||||
`SELECT count(role_id) as member_count, project FROM role_user GROUP BY project`,
|
||||
);
|
||||
|
||||
const memberCount = await this.getMembersCount();
|
||||
memberTimer();
|
||||
const memberMap = new Map<string, number>(
|
||||
memberCount.rows.map((c) => [c.project, Number(c.member_count)]),
|
||||
memberCount.map((c) => [c.project, Number(c.count)]),
|
||||
);
|
||||
return projectsWithFeatureCount.map((r) => {
|
||||
return { ...r, memberCount: memberMap.get(r.id) };
|
||||
@ -247,23 +251,75 @@ class ProjectStore implements IProjectStore {
|
||||
.pluck('project_environments.environment_name');
|
||||
}
|
||||
|
||||
async getMembers(projectId: string): Promise<number> {
|
||||
const rolesFromProject = this.db('role_permission')
|
||||
.select('role_id')
|
||||
.distinct();
|
||||
|
||||
const numbers = await this.db('role_user')
|
||||
.countDistinct('user_id as members')
|
||||
.where('project', projectId)
|
||||
.whereIn('role_id', rolesFromProject)
|
||||
.first();
|
||||
const { members } = numbers;
|
||||
if (typeof members === 'string') {
|
||||
return parseInt(members, 10);
|
||||
}
|
||||
async getMembersCount(): Promise<IProjectMembersCount[]> {
|
||||
const members = await this.db
|
||||
.select('project')
|
||||
.from((db) => {
|
||||
db.select('user_id', 'project')
|
||||
.from('role_user')
|
||||
.leftJoin('roles', 'role_user.role_id', 'roles.id')
|
||||
.where((builder) => builder.whereNot('type', 'root'))
|
||||
.union((queryBuilder) => {
|
||||
queryBuilder
|
||||
.select('user_id', 'project')
|
||||
.from('group_role')
|
||||
.leftJoin(
|
||||
'group_user',
|
||||
'group_user.group_id',
|
||||
'group_role.group_id',
|
||||
);
|
||||
})
|
||||
.union((queryBuilder) => {
|
||||
queryBuilder
|
||||
.select('user_id', 'projects.name as project')
|
||||
.from('role_user')
|
||||
.leftJoin('roles', 'role_user.role_id', 'roles.id')
|
||||
.crossJoin('projects')
|
||||
.where((builder) =>
|
||||
builder
|
||||
.where('type', 'root')
|
||||
.where('roles.name', 'Editor'),
|
||||
);
|
||||
})
|
||||
.as('query');
|
||||
})
|
||||
.groupBy('project')
|
||||
.count('user_id');
|
||||
return members;
|
||||
}
|
||||
|
||||
async getMembersCountByProject(projectId?: string): Promise<number> {
|
||||
const members = await this.db
|
||||
.from((db) => {
|
||||
db.select('user_id')
|
||||
.from('role_user')
|
||||
.leftJoin('roles', 'role_user.role_id', 'roles.id')
|
||||
.where((builder) =>
|
||||
builder
|
||||
.where('project', projectId)
|
||||
.whereNot('type', 'root'),
|
||||
)
|
||||
.orWhere((builder) =>
|
||||
builder.where('type', 'root').where('name', 'Editor'),
|
||||
)
|
||||
.union((queryBuilder) => {
|
||||
queryBuilder
|
||||
.select('user_id')
|
||||
.from('group_role')
|
||||
.leftJoin(
|
||||
'group_user',
|
||||
'group_user.group_id',
|
||||
'group_role.group_id',
|
||||
)
|
||||
.where('project', projectId);
|
||||
})
|
||||
.as('query');
|
||||
})
|
||||
.count()
|
||||
.first();
|
||||
return Number(members.count);
|
||||
}
|
||||
|
||||
async count(): Promise<number> {
|
||||
return this.db
|
||||
.from(TABLE)
|
||||
|
@ -67,7 +67,9 @@ export default class ProjectHealthService {
|
||||
projectId,
|
||||
archived,
|
||||
);
|
||||
const members = await this.projectStore.getMembers(projectId);
|
||||
const members = await this.projectStore.getMembersCountByProject(
|
||||
projectId,
|
||||
);
|
||||
return {
|
||||
name: project.name,
|
||||
description: project.description,
|
||||
|
@ -573,7 +573,7 @@ export default class ProjectService {
|
||||
}
|
||||
|
||||
async getMembers(projectId: string): Promise<number> {
|
||||
return this.store.getMembers(projectId);
|
||||
return this.store.getMembersCountByProject(projectId);
|
||||
}
|
||||
|
||||
async getProjectOverview(
|
||||
@ -588,7 +588,7 @@ export default class ProjectService {
|
||||
projectId,
|
||||
archived,
|
||||
);
|
||||
const members = await this.store.getMembers(projectId);
|
||||
const members = await this.store.getMembersCountByProject(projectId);
|
||||
return {
|
||||
name: project.name,
|
||||
environments,
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { IEnvironmentProjectLink } from '../../db/project-store';
|
||||
import {
|
||||
IEnvironmentProjectLink,
|
||||
IProjectMembersCount,
|
||||
} from '../../db/project-store';
|
||||
import { IProject, IProjectWithCount } from '../model';
|
||||
import { Store } from './store';
|
||||
|
||||
@ -32,7 +35,8 @@ export interface IProjectStore extends Store<IProject, string> {
|
||||
addEnvironmentToProject(id: string, environment: string): Promise<void>;
|
||||
deleteEnvironmentForProject(id: string, environment: string): Promise<void>;
|
||||
getEnvironmentsForProject(id: string): Promise<string[]>;
|
||||
getMembers(projectId: string): Promise<number>;
|
||||
getMembersCountByProject(projectId: string): Promise<number>;
|
||||
getMembersCount(): Promise<IProjectMembersCount[]>;
|
||||
getProjectsWithCounts(query?: IProjectQuery): Promise<IProjectWithCount[]>;
|
||||
count(): Promise<number>;
|
||||
getAll(query?: IProjectQuery): Promise<IProject[]>;
|
||||
|
11
src/test/fixtures/fake-project-store.ts
vendored
11
src/test/fixtures/fake-project-store.ts
vendored
@ -5,7 +5,10 @@ import {
|
||||
} from '../../lib/types/stores/project-store';
|
||||
import { IProject, IProjectWithCount } from '../../lib/types/model';
|
||||
import NotFoundError from '../../lib/error/notfound-error';
|
||||
import { IEnvironmentProjectLink } from 'lib/db/project-store';
|
||||
import {
|
||||
IEnvironmentProjectLink,
|
||||
IProjectMembersCount,
|
||||
} from 'lib/db/project-store';
|
||||
|
||||
export default class FakeProjectStore implements IProjectStore {
|
||||
projects: IProject[] = [];
|
||||
@ -99,7 +102,7 @@ export default class FakeProjectStore implements IProjectStore {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async getMembers(projectId: string): Promise<number> {
|
||||
async getMembersCountByProject(projectId: string): Promise<number> {
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
|
||||
@ -120,4 +123,8 @@ export default class FakeProjectStore implements IProjectStore {
|
||||
this.projects.find((p) => p.id === healthUpdate.id).health =
|
||||
healthUpdate.health;
|
||||
}
|
||||
|
||||
getMembersCount(): Promise<IProjectMembersCount[]> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user