Skip to content

Commit

Permalink
feat: activity chart polish (#8665)
Browse files Browse the repository at this point in the history
  • Loading branch information
sjaanus authored Nov 6, 2024
1 parent ba72be6 commit d6e722b
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,25 @@ import type { ProjectActivitySchema } from '../../../../openapi';
import { styled, Tooltip } from '@mui/material';

const StyledContainer = styled('div')(({ theme }) => ({
gap: theme.spacing(1),
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
gap: theme.spacing(2),
}));

const TitleContainer = styled('h4')({
margin: 0,
width: '100%',
});

type Output = { date: string; count: number; level: number };

export function transformData(inputData: ProjectActivitySchema): Output[] {
const resultMap: Record<string, number> = {};

// Step 1: Count the occurrences of each date
inputData.forEach((item) => {
const formattedDate = new Date(item.date).toISOString().split('T')[0];
resultMap[formattedDate] = (resultMap[formattedDate] || 0) + 1;
});
const countArray = inputData.map((item) => item.count);

// Step 2: Get all counts, sort them, and find the cut-off values for percentiles
const counts = Object.values(resultMap).sort((a, b) => a - b);
const counts = Object.values(countArray).sort((a, b) => a - b);

const percentile = (percent: number) => {
const index = Math.floor((percent / 100) * counts.length);
Expand All @@ -43,13 +46,13 @@ export function transformData(inputData: ProjectActivitySchema): Output[] {
};

// Step 4: Convert the map back to an array and assign levels
return Object.entries(resultMap)
.map(([date, count]) => ({
return inputData
.map(({ date, count }) => ({
date,
count,
level: calculateLevel(count),
}))
.reverse(); // Optional: reverse the order if needed
.reverse();
}

export const ProjectActivity = () => {
Expand All @@ -64,10 +67,10 @@ export const ProjectActivity = () => {
const levelledData = transformData(data.activityCountByDate);

return (
<StyledContainer>
<>
{data.activityCountByDate.length > 0 ? (
<>
<span>Activity in project</span>
<StyledContainer>
<TitleContainer>Activity in project</TitleContainer>
<ActivityCalendar
theme={explicitTheme}
data={levelledData}
Expand All @@ -81,10 +84,10 @@ export const ProjectActivity = () => {
</Tooltip>
)}
/>
</>
</StyledContainer>
) : (
<span>No activity</span>
)}
</StyledContainer>
</>
);
};
7 changes: 6 additions & 1 deletion src/lib/features/events/event-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ class EventStore implements IEventStore {
}));
}

async getProjectEventActivity(
async getProjectRecentEventActivity(
project: string,
): Promise<ProjectActivitySchema> {
const result = await this.db('events')
Expand All @@ -418,6 +418,11 @@ class EventStore implements IEventStore {
)
.count('* AS count')
.where('project', project)
.andWhere(
'created_at',
'>=',
this.db.raw("NOW() - INTERVAL '1 year'"),
)
.groupBy(this.db.raw("TO_CHAR(created_at::date, 'YYYY-MM-DD')"))
.orderBy('date', 'asc');

Expand Down
2 changes: 1 addition & 1 deletion src/lib/features/project-status/project-status-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class ProjectStatusService {
),
},
activityCountByDate:
await this.eventStore.getProjectEventActivity(projectId),
await this.eventStore.getProjectRecentEventActivity(projectId),
};
}
}
4 changes: 3 additions & 1 deletion src/lib/types/stores/event-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,7 @@ export interface IEventStore
queryCount(operations: IQueryOperations[]): Promise<number>;
setCreatedByUserId(batchSize: number): Promise<number | undefined>;
getEventCreators(): Promise<Array<{ id: number; name: string }>>;
getProjectEventActivity(project: string): Promise<ProjectActivitySchema>;
getProjectRecentEventActivity(
project: string,
): Promise<ProjectActivitySchema>;
}
4 changes: 3 additions & 1 deletion src/test/fixtures/fake-event-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ class FakeEventStore implements IEventStore {
this.events = [];
}

getProjectEventActivity(project: string): Promise<ProjectActivitySchema> {
getProjectRecentEventActivity(
project: string,
): Promise<ProjectActivitySchema> {
throw new Error('Method not implemented.');
}

Expand Down

0 comments on commit d6e722b

Please sign in to comment.