mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-09 00:18:00 +01:00
feat: exclude archived projects from insights and project stats (#7843)
This commit is contained in:
parent
0934c6ccd8
commit
fcf1329816
@ -1,9 +1,9 @@
|
|||||||
import type { IEnvironmentStore } from '../../../lib/features/project-environments/environment-store-type';
|
import type { IEnvironmentStore } from '../project-environments/environment-store-type';
|
||||||
|
|
||||||
import dbInit, { type ITestDb } from '../helpers/database-init';
|
import dbInit, { type ITestDb } from '../../../test/e2e/helpers/database-init';
|
||||||
import getLogger from '../../fixtures/no-logger';
|
import getLogger from '../../../test/fixtures/no-logger';
|
||||||
import type { IProjectStore, IUnleashStores } from '../../../lib/types';
|
import type { IProjectStore, IUnleashStores } from '../../types';
|
||||||
import type { IProjectInsert } from '../../../lib/features/project/project-store-type';
|
import type { IProjectInsert } from './project-store-type';
|
||||||
|
|
||||||
let stores: IUnleashStores;
|
let stores: IUnleashStores;
|
||||||
let db: ITestDb;
|
let db: ITestDb;
|
||||||
@ -11,7 +11,9 @@ let projectStore: IProjectStore;
|
|||||||
let environmentStore: IEnvironmentStore;
|
let environmentStore: IEnvironmentStore;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
db = await dbInit('project_store_serial', getLogger);
|
db = await dbInit('project_store_serial', getLogger, {
|
||||||
|
experimental: { flags: { archiveProjects: true } },
|
||||||
|
});
|
||||||
stores = db.stores;
|
stores = db.stores;
|
||||||
projectStore = stores.projectStore;
|
projectStore = stores.projectStore;
|
||||||
environmentStore = stores.environmentStore;
|
environmentStore = stores.environmentStore;
|
||||||
@ -21,6 +23,25 @@ afterAll(async () => {
|
|||||||
await db.destroy();
|
await db.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should exclude archived projects', async () => {
|
||||||
|
const project = {
|
||||||
|
id: 'archive-me',
|
||||||
|
name: 'archive-me',
|
||||||
|
description: 'Blah',
|
||||||
|
mode: 'open' as const,
|
||||||
|
};
|
||||||
|
await projectStore.create(project);
|
||||||
|
await projectStore.archive(project.id);
|
||||||
|
|
||||||
|
const allProjects = await projectStore.getAll();
|
||||||
|
const count = await projectStore.count();
|
||||||
|
const modeCounts = await projectStore.getProjectModeCounts();
|
||||||
|
|
||||||
|
expect(allProjects).toMatchObject([{ id: 'default' }]);
|
||||||
|
expect(count).toBe(1);
|
||||||
|
expect(modeCounts).toMatchObject([{ mode: 'open', count: 1 }]);
|
||||||
|
});
|
||||||
|
|
||||||
test('should have default project', async () => {
|
test('should have default project', async () => {
|
||||||
const project = await projectStore.get('default');
|
const project = await projectStore.get('default');
|
||||||
expect(project).toBeDefined();
|
expect(project).toBeDefined();
|
@ -131,8 +131,9 @@ class ProjectStore implements IProjectStore {
|
|||||||
)
|
)
|
||||||
.leftJoin('project_stats', 'project_stats.project', 'projects.id')
|
.leftJoin('project_stats', 'project_stats.project', 'projects.id')
|
||||||
.orderBy('projects.name', 'asc');
|
.orderBy('projects.name', 'asc');
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('archiveProjects')) {
|
if (this.flagResolver.isEnabled('archiveProjects')) {
|
||||||
projects = projects.where('projects.archived_at', null);
|
projects = projects.where(`${TABLE}.archived_at`, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query) {
|
if (query) {
|
||||||
@ -221,12 +222,18 @@ class ProjectStore implements IProjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAll(query: IProjectQuery = {}): Promise<IProject[]> {
|
async getAll(query: IProjectQuery = {}): Promise<IProject[]> {
|
||||||
const rows = await this.db
|
let projects = this.db
|
||||||
.select(COLUMNS)
|
.select(COLUMNS)
|
||||||
.from(TABLE)
|
.from(TABLE)
|
||||||
.where(query)
|
.where(query)
|
||||||
.orderBy('name', 'asc');
|
.orderBy('name', 'asc');
|
||||||
|
|
||||||
|
if (this.flagResolver.isEnabled('archiveProjects')) {
|
||||||
|
projects = projects.where(`${TABLE}.archived_at`, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = await projects;
|
||||||
|
|
||||||
return rows.map(this.mapRow);
|
return rows.map(this.mapRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,14 +713,17 @@ class ProjectStore implements IProjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async count(): Promise<number> {
|
async count(): Promise<number> {
|
||||||
return this.db
|
let count = this.db.from(TABLE).count('*');
|
||||||
.from(TABLE)
|
|
||||||
.count('*')
|
if (this.flagResolver.isEnabled('archiveProjects')) {
|
||||||
.then((res) => Number(res[0].count));
|
count = count.where(`${TABLE}.archived_at`, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return count.then((res) => Number(res[0].count));
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjectModeCounts(): Promise<ProjectModeCount[]> {
|
async getProjectModeCounts(): Promise<ProjectModeCount[]> {
|
||||||
const result: ProjectModeCount[] = await this.db
|
let query = this.db
|
||||||
.select(
|
.select(
|
||||||
this.db.raw(
|
this.db.raw(
|
||||||
`COALESCE(${SETTINGS_TABLE}.project_mode, 'open') as mode`,
|
`COALESCE(${SETTINGS_TABLE}.project_mode, 'open') as mode`,
|
||||||
@ -729,11 +739,18 @@ class ProjectStore implements IProjectStore {
|
|||||||
.groupBy(
|
.groupBy(
|
||||||
this.db.raw(`COALESCE(${SETTINGS_TABLE}.project_mode, 'open')`),
|
this.db.raw(`COALESCE(${SETTINGS_TABLE}.project_mode, 'open')`),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (this.flagResolver.isEnabled('archiveProjects')) {
|
||||||
|
query = query.where(`${TABLE}.archived_at`, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: ProjectModeCount[] = await query;
|
||||||
|
|
||||||
return result.map(this.mapProjectModeCount);
|
return result.map(this.mapProjectModeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
mapProjectModeCount(row): ProjectModeCount {
|
private mapProjectModeCount(row): ProjectModeCount {
|
||||||
return {
|
return {
|
||||||
mode: row.mode,
|
mode: row.mode,
|
||||||
count: Number(row.count),
|
count: Number(row.count),
|
||||||
@ -741,7 +758,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
mapLinkRow(row): IEnvironmentProjectLink {
|
private mapLinkRow(row): IEnvironmentProjectLink {
|
||||||
return {
|
return {
|
||||||
environmentName: row.environment_name,
|
environmentName: row.environment_name,
|
||||||
projectId: row.project_id,
|
projectId: row.project_id,
|
||||||
@ -749,7 +766,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
mapRow(row): IProject {
|
private mapRow(row): IProject {
|
||||||
if (!row) {
|
if (!row) {
|
||||||
throw new NotFoundError('No project found');
|
throw new NotFoundError('No project found');
|
||||||
}
|
}
|
||||||
@ -772,7 +789,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
mapProjectEnvironmentRow(row: {
|
private mapProjectEnvironmentRow(row: {
|
||||||
environment_name: string;
|
environment_name: string;
|
||||||
default_strategy: CreateFeatureStrategySchema;
|
default_strategy: CreateFeatureStrategySchema;
|
||||||
}): ProjectEnvironment {
|
}): ProjectEnvironment {
|
||||||
@ -785,7 +802,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
getAggregatedApplicationsData(rows): IProjectApplication[] {
|
private getAggregatedApplicationsData(rows): IProjectApplication[] {
|
||||||
const entriesMap = new Map<string, IProjectApplication>();
|
const entriesMap = new Map<string, IProjectApplication>();
|
||||||
|
|
||||||
rows.forEach((row) => {
|
rows.forEach((row) => {
|
||||||
|
7
src/test/fixtures/fake-project-store.ts
vendored
7
src/test/fixtures/fake-project-store.ts
vendored
@ -50,7 +50,7 @@ export default class FakeProjectStore implements IProjectStore {
|
|||||||
|
|
||||||
async getProjectsWithCounts(): Promise<IProjectWithCount[]> {
|
async getProjectsWithCounts(): Promise<IProjectWithCount[]> {
|
||||||
return this.projects
|
return this.projects
|
||||||
.filter((project) => project.archivedAt !== null)
|
.filter((project) => project.archivedAt === null)
|
||||||
.map((project) => {
|
.map((project) => {
|
||||||
return {
|
return {
|
||||||
...project,
|
...project,
|
||||||
@ -105,7 +105,8 @@ export default class FakeProjectStore implements IProjectStore {
|
|||||||
destroy(): void {}
|
destroy(): void {}
|
||||||
|
|
||||||
async count(): Promise<number> {
|
async count(): Promise<number> {
|
||||||
return this.projects.length;
|
return this.projects.filter((project) => project.archivedAt === null)
|
||||||
|
.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(key: string): Promise<IProject> {
|
async get(key: string): Promise<IProject> {
|
||||||
@ -117,7 +118,7 @@ export default class FakeProjectStore implements IProjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAll(): Promise<IProject[]> {
|
async getAll(): Promise<IProject[]> {
|
||||||
return this.projects;
|
return this.projects.filter((project) => project.archivedAt === null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
Loading…
Reference in New Issue
Block a user