diff --git a/frontend/src/component/project/Project/ProjectStats/ProjectStats.tsx b/frontend/src/component/project/Project/ProjectStats/ProjectStats.tsx
index a4748ec5b7..9ca09bd511 100644
--- a/frontend/src/component/project/Project/ProjectStats/ProjectStats.tsx
+++ b/frontend/src/component/project/Project/ProjectStats/ProjectStats.tsx
@@ -35,6 +35,12 @@ const StyledWidget = styled(Box)(({ theme }) => ({
},
}));
+const StyledTimeToProductionDescription = styled(Typography)(({ theme }) => ({
+ color: theme.palette.text.secondary,
+ fontSize: theme.typography.body2.fontSize,
+ lineHeight: theme.typography.body2.lineHeight,
+}));
+
interface IProjectStatsProps {
stats: ProjectStatsSchema;
}
@@ -95,16 +101,18 @@ export const ProjectStats = ({ stats }: IProjectStatsProps) => {
days
}
- change={calculatePercentage(
- avgTimeToProdCurrentWindow,
- avgTimeToProdPastWindow
- )}
+ customChangeElement={
+
+ In project life
+
+ }
percentage
>
How long did it take on average from a feature toggle
was created until it was enabled in an environment of
- type production.
+ type production. This is calculated only from feature
+ toggles with the type of "release".
diff --git a/frontend/src/component/project/Project/ProjectStats/StatusBox.tsx b/frontend/src/component/project/Project/ProjectStats/StatusBox.tsx
index dce85d7e55..fd8c5e4736 100644
--- a/frontend/src/component/project/Project/ProjectStats/StatusBox.tsx
+++ b/frontend/src/component/project/Project/ProjectStats/StatusBox.tsx
@@ -33,8 +33,9 @@ const StyledTypographyChange = styled(Typography)(({ theme }) => ({
interface IStatusBoxProps {
title?: string;
boxText: ReactNode;
- change: number;
+ change?: number;
percentage?: boolean;
+ customChangeElement?: ReactNode;
}
const resolveIcon = (change: number) => {
@@ -59,6 +60,7 @@ export const StatusBox: FC = ({
change,
percentage,
children,
+ customChangeElement,
}) => (
<>
= ({
>
{boxText}
-
- {resolveIcon(change)}
-
- {change > 0 ? '+' : ''}
- {change}
- {percentage ? '%' : ''}
-
-
-
- this month
-
+ {customChangeElement}
}
elseShow={
-
-
- No change
-
-
+
+
+ {resolveIcon(change as number)}
+
+ {(change as number) > 0 ? '+' : ''}
+ {change}
+ {percentage ? '%' : ''}
+
+
+
+ this month
+
+
+ }
+ elseShow={
+
+
+ No change
+
+
+ }
+ />
}
/>
diff --git a/src/lib/db/project-stats-store.ts b/src/lib/db/project-stats-store.ts
index 8a5e24a5b2..3fd2491e3f 100644
--- a/src/lib/db/project-stats-store.ts
+++ b/src/lib/db/project-stats-store.ts
@@ -11,7 +11,6 @@ const TABLE = 'project_stats';
const PROJECT_STATS_COLUMNS = [
'avg_time_to_prod_current_window',
- 'avg_time_to_prod_past_window',
'project',
'features_created_current_window',
'features_created_past_window',
@@ -24,7 +23,6 @@ const PROJECT_STATS_COLUMNS = [
interface IProjectStatsRow {
avg_time_to_prod_current_window: number;
- avg_time_to_prod_past_window: number;
features_created_current_window: number;
features_created_past_window: number;
features_archived_current_window: number;
@@ -59,7 +57,6 @@ class ProjectStatsStore implements IProjectStatsStore {
.insert({
avg_time_to_prod_current_window:
status.avgTimeToProdCurrentWindow,
- avg_time_to_prod_past_window: status.avgTimeToProdPastWindow,
project: projectId,
features_created_current_window: status.createdCurrentWindow,
features_created_past_window: status.createdPastWindow,
@@ -88,7 +85,6 @@ class ProjectStatsStore implements IProjectStatsStore {
if (!row) {
return {
avgTimeToProdCurrentWindow: 0,
- avgTimeToProdPastWindow: 0,
createdCurrentWindow: 0,
createdPastWindow: 0,
archivedCurrentWindow: 0,
@@ -101,7 +97,6 @@ class ProjectStatsStore implements IProjectStatsStore {
return {
avgTimeToProdCurrentWindow: row.avg_time_to_prod_current_window,
- avgTimeToProdPastWindow: row.avg_time_to_prod_past_window,
createdCurrentWindow: row.features_created_current_window,
createdPastWindow: row.features_created_past_window,
archivedCurrentWindow: row.features_archived_current_window,
diff --git a/src/lib/openapi/spec/project-stats-schema.ts b/src/lib/openapi/spec/project-stats-schema.ts
index 041ddba94f..0630d56e83 100644
--- a/src/lib/openapi/spec/project-stats-schema.ts
+++ b/src/lib/openapi/spec/project-stats-schema.ts
@@ -6,7 +6,6 @@ export const projectStatsSchema = {
additionalProperties: false,
required: [
'avgTimeToProdCurrentWindow',
- 'avgTimeToProdPastWindow',
'createdCurrentWindow',
'createdPastWindow',
'archivedCurrentWindow',
@@ -27,12 +26,6 @@ Stats are divided into current and previous **windows**.
description:
'The average time from when a feature was created to when it was enabled in the "production" environment during the current window',
},
- avgTimeToProdPastWindow: {
- type: 'number',
- example: 10,
- description:
- 'The average time from when a feature was created to when it was enabled in the "production" environment during the previous window',
- },
createdCurrentWindow: {
type: 'number',
example: 15,
diff --git a/src/lib/services/project-service.ts b/src/lib/services/project-service.ts
index 7ddd9ebb31..047b30e1a4 100644
--- a/src/lib/services/project-service.ts
+++ b/src/lib/services/project-service.ts
@@ -65,7 +65,6 @@ type Count = number;
export interface IProjectStats {
avgTimeToProdCurrentWindow: Days;
- avgTimeToProdPastWindow: Days;
createdCurrentWindow: Count;
createdPastWindow: Count;
archivedCurrentWindow: Count;
@@ -679,6 +678,12 @@ export default class ProjectService {
project: projectId,
});
+ const archivedFeatures = await this.featureToggleStore.getAll({
+ archived: true,
+ type: 'release',
+ project: projectId,
+ });
+
const dateMinusThirtyDays = subDays(new Date(), 30).toISOString();
const dateMinusSixtyDays = subDays(new Date(), 60).toISOString();
@@ -743,54 +748,24 @@ export default class ProjectService {
// Get all events for features that correspond to feature toggle environment ON
// Filter out events that are not a production evironment
- const eventsCurrentWindow = await this.eventStore.query([
- {
- op: 'forFeatures',
- parameters: {
- features: features.map((feature) => feature.name),
- environments: productionEnvironments.map((env) => env.name),
- type: FEATURE_ENVIRONMENT_ENABLED,
- projectId,
- },
- },
- {
- op: 'beforeDate',
- parameters: {
- dateAccessor: 'created_at',
- date: dateMinusThirtyDays,
- },
- },
- ]);
+ const allFeatures = [...features, ...archivedFeatures];
- const eventsPastWindow = await this.eventStore.query([
+ const eventsData = await this.eventStore.query([
{
op: 'forFeatures',
parameters: {
- features: features.map((feature) => feature.name),
+ features: allFeatures.map((feature) => feature.name),
environments: productionEnvironments.map((env) => env.name),
type: FEATURE_ENVIRONMENT_ENABLED,
projectId,
},
},
- {
- op: 'betweenDate',
- parameters: {
- dateAccessor: 'created_at',
- range: [dateMinusSixtyDays, dateMinusThirtyDays],
- },
- },
]);
const currentWindowTimeToProdReadModel = new TimeToProduction(
- features,
+ allFeatures,
productionEnvironments,
- eventsCurrentWindow,
- );
-
- const pastWindowTimeToProdReadModel = new TimeToProduction(
- features,
- productionEnvironments,
- eventsPastWindow,
+ eventsData,
);
const projectMembersAddedCurrentWindow =
@@ -804,8 +779,6 @@ export default class ProjectService {
updates: {
avgTimeToProdCurrentWindow:
currentWindowTimeToProdReadModel.calculateAverageTimeToProd(),
- avgTimeToProdPastWindow:
- pastWindowTimeToProdReadModel.calculateAverageTimeToProd(),
createdCurrentWindow: createdCurrentWindow.length,
createdPastWindow: createdPastWindow.length,
archivedCurrentWindow: archivedCurrentWindow.length,
diff --git a/src/migrations/20230316092547-remove-project-stats-column.js b/src/migrations/20230316092547-remove-project-stats-column.js
new file mode 100644
index 0000000000..1105730cf7
--- /dev/null
+++ b/src/migrations/20230316092547-remove-project-stats-column.js
@@ -0,0 +1,19 @@
+exports.up = function (db, cb) {
+ db.runSql(
+ `
+ ALTER table project_stats
+ DROP COLUMN avg_time_to_prod_past_window
+ `,
+ cb,
+ );
+};
+
+exports.down = function (db, cb) {
+ db.runSql(
+ `
+ ALTER table project_stats
+ ADD COLUMN IF NOT EXISTS avg_time_to_prod_past_window INTEGER DEFAULT 0
+ `,
+ cb,
+ );
+};
diff --git a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap
index 17c6ccb394..c415e90176 100644
--- a/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap
+++ b/src/test/e2e/api/openapi/__snapshots__/openapi.e2e.test.ts.snap
@@ -2937,11 +2937,6 @@ Stats are divided into current and previous **windows**.
"example": 10,
"type": "number",
},
- "avgTimeToProdPastWindow": {
- "description": "The average time from when a feature was created to when it was enabled in the "production" environment during the previous window",
- "example": 10,
- "type": "number",
- },
"createdCurrentWindow": {
"description": "The number of feature toggles created during the current window",
"example": 15,
@@ -2970,7 +2965,6 @@ Stats are divided into current and previous **windows**.
},
"required": [
"avgTimeToProdCurrentWindow",
- "avgTimeToProdPastWindow",
"createdCurrentWindow",
"createdPastWindow",
"archivedCurrentWindow",
diff --git a/src/test/e2e/services/project-service.e2e.test.ts b/src/test/e2e/services/project-service.e2e.test.ts
index 93ca9db6cf..c4fc70b545 100644
--- a/src/test/e2e/services/project-service.e2e.test.ts
+++ b/src/test/e2e/services/project-service.e2e.test.ts
@@ -1231,8 +1231,7 @@ test('should calculate average time to production', async () => {
});
const result = await projectService.getStatusUpdates(project.id);
- expect(result.updates.avgTimeToProdCurrentWindow).toBe(14);
- expect(result.updates.avgTimeToProdPastWindow).toBe(1);
+ expect(result.updates.avgTimeToProdCurrentWindow).toBe(11.4);
});
test('should get correct amount of features created in current and past window', async () => {