Skip to content

Commit

Permalink
feat: return latest project events (#8287)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew authored Sep 27, 2024
1 parent ed4c05d commit e540db4
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/lib/addons/feature-event-formatter-md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '../types';
import { EVENT_MAP } from './feature-event-formatter-md-events';

interface IFormattedEventData {
export interface IFormattedEventData {
label: string;
text: string;
url?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { ProjectOwnersReadModel } from '../project/project-owners-read-model';
import { FakeProjectOwnersReadModel } from '../project/fake-project-owners-read-model';
import { ProjectReadModel } from '../project/project-read-model';
import { FakeProjectReadModel } from '../project/fake-project-read-model';
import EventStore from '../../db/event-store';
import { FeatureEventFormatterMd } from '../../addons/feature-event-formatter-md';
import FakeEventStore from '../../../test/fixtures/fake-event-store';

export const createPersonalDashboardService = (
db: Db,
Expand All @@ -16,13 +19,23 @@ export const createPersonalDashboardService = (
new PersonalDashboardReadModel(db),
new ProjectOwnersReadModel(db),
new ProjectReadModel(db, config.eventBus, config.flagResolver),
new EventStore(db, config.getLogger),
new FeatureEventFormatterMd({
unleashUrl: config.server.unleashUrl,
formatStyle: 'markdown',
}),
);
};

export const createFakePersonalDashboardService = () => {
export const createFakePersonalDashboardService = (config: IUnleashConfig) => {
return new PersonalDashboardService(
new FakePersonalDashboardReadModel(),
new FakeProjectOwnersReadModel(),
new FakeProjectReadModel(),
new FakeEventStore(),
new FeatureEventFormatterMd({
unleashUrl: config.server.unleashUrl,
formatStyle: 'markdown',
}),
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ afterAll(async () => {
beforeEach(async () => {
await db.stores.featureToggleStore.deleteAll();
await db.stores.userStore.deleteAll();
await db.stores.eventStore.deleteAll();
});

test('should return personal dashboard with own flags and favorited flags', async () => {
Expand Down Expand Up @@ -178,12 +179,41 @@ test('should return projects where users are part of a group', async () => {

test('should return personal dashboard project details', async () => {
await loginUser('[email protected]');

await app.createFeature('log_feature_a');
await app.createFeature('log_feature_b');
await app.createFeature('log_feature_c');

const { body } = await app.request.get(
`/api/admin/personal-dashboard/default`,
);

expect(body).toMatchObject({
owners: [{}],
roles: [{}],
latestEvents: [
{
createdBy: '[email protected]',
summary: expect.stringContaining(
'**[email protected]** created **[log_feature_c]',
),
},
{
createdBy: '[email protected]',
summary: expect.stringContaining(
'**[email protected]** created **[log_feature_b]',
),
},
{
createdBy: '[email protected]',
summary: expect.stringContaining(
'**[email protected]** created **[log_feature_a]',
),
},
{
createdBy: 'unleash_system_user',
summary: '**unleash_system_user** created user ****',
},
],
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,17 @@ export default class PersonalDashboardController extends Controller {
): Promise<void> {
const user = req.user;

const projectDetails =
await this.personalDashboardService.getPersonalProjectDetails(
req.params.projectId,
);

this.openApiService.respondWithValidation(
200,
res,
personalDashboardProjectDetailsSchema.$id,
{
...projectDetails,
owners: [{ ownerType: 'user', name: 'placeholder' }],
roles: [{ name: 'placeholder', id: 0, type: 'project' }],
},
Expand Down
30 changes: 30 additions & 0 deletions src/lib/features/personal-dashboard/personal-dashboard-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import type {
PersonalProject,
} from './personal-dashboard-read-model-type';
import type { IProjectReadModel } from '../project/project-read-model-type';
import type { IEventStore } from '../../types';
import type { FeatureEventFormatter } from '../../addons/feature-event-formatter-md';

type PersonalProjectDetails = {
latestEvents: { summary: string; createdBy: string }[];
};

export class PersonalDashboardService {
private personalDashboardReadModel: IPersonalDashboardReadModel;
Expand All @@ -13,14 +19,22 @@ export class PersonalDashboardService {

private projectReadModel: IProjectReadModel;

private eventStore: IEventStore;

private featureEventFormatter: FeatureEventFormatter;

constructor(
personalDashboardReadModel: IPersonalDashboardReadModel,
projectOwnersReadModel: IProjectOwnersReadModel,
projectReadModel: IProjectReadModel,
eventStore: IEventStore,
featureEventFormatter: FeatureEventFormatter,
) {
this.personalDashboardReadModel = personalDashboardReadModel;
this.projectOwnersReadModel = projectOwnersReadModel;
this.projectReadModel = projectReadModel;
this.eventStore = eventStore;
this.featureEventFormatter = featureEventFormatter;
}

getPersonalFeatures(userId: number): Promise<PersonalFeature[]> {
Expand All @@ -46,4 +60,20 @@ export class PersonalDashboardService {

return normalizedProjects;
}

async getPersonalProjectDetails(
projectId: string,
): Promise<PersonalProjectDetails> {
const recentEvents = await this.eventStore.searchEvents(
{ project: projectId, limit: 4, offset: 0 },
[],
);

const formattedEvents = recentEvents.map((event) => ({
summary: this.featureEventFormatter.format(event).text,
createdBy: event.createdBy,
}));

return { latestEvents: formattedEvents };
}
}
23 changes: 23 additions & 0 deletions src/lib/openapi/spec/personal-dashboard-project-details-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,29 @@ export const personalDashboardProjectDetailsSchema = {
additionalProperties: false,
required: ['owners', 'roles'],
properties: {
latestEvents: {
type: 'array',
description: 'The latest events for the project.',
items: {
type: 'object',
description: 'An event summary',
additionalProperties: false,
required: ['summary', 'createdBy'],
properties: {
summary: {
type: 'string',
nullable: true,
description:
'**[Experimental]** A markdown-formatted summary of the event.',
},
createdBy: {
type: 'string',
description: 'Which user created this event',
example: 'johndoe',
},
},
},
},
owners: projectSchema.properties.owners,
roles: {
type: 'array',
Expand Down
2 changes: 1 addition & 1 deletion src/lib/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ export const createServices = (

const personalDashboardService = db
? createPersonalDashboardService(db, config)
: createFakePersonalDashboardService();
: createFakePersonalDashboardService(config);

return {
accessService,
Expand Down

0 comments on commit e540db4

Please sign in to comment.