Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useAgnosticNavigation } from '@app-builder/contexts/AgnosticNavigationContext';
import { type AnalyticsFiltersQuery } from '@app-builder/models/analytics';
import { getRoute } from '@app-builder/utils/routes';
import { keepPreviousData, useQuery } from '@tanstack/react-query';

export function createAnalyticsQuery<TData>(queryName: string) {
return ({ scenarioId, queryString }: { scenarioId: string; queryString: string }) => {
const navigate = useAgnosticNavigation();
const endpoint = getRoute('/ressources/analytics/:scenarioId/query/:queryName', {
scenarioId,
queryName,
});
console.log('endpoint', endpoint);
const qs = queryString ? atob(queryString) : null;
const parsed: AnalyticsFiltersQuery = JSON.parse(qs || '{}');

const { range, compareRange, scenarioVersion, trigger } = parsed;

return useQuery({
queryKey: ['analytics', 'query', scenarioId, queryName, queryString],
enabled: Boolean(qs && range),
queryFn: async () => {
const response = await fetch(endpoint, {
method: 'POST',
body: JSON.stringify({
scenarioVersion,
range,
compareRange,
trigger,
}),
});

const responseData = (await response.json()) as { redirectTo: string } | { data: TData };

if ('redirectTo' in responseData) {
navigate(responseData.redirectTo);
return;
}

return responseData.data;
},
placeholderData: keepPreviousData,
});
};
}
57 changes: 0 additions & 57 deletions packages/app-builder/src/queries/analytics/get-analytics.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { DecisionOutcomesPerPeriod } from '@app-builder/models/analytics';
import { createAnalyticsQuery } from './factory/create-analytics-query';

export const useGetDecisionsOutcomesPerDay =
createAnalyticsQuery<DecisionOutcomesPerPeriod>('decision-outcomes-per-day');
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { RuleHitTableResponse } from '@app-builder/models/analytics/rule-hit';
import { createAnalyticsQuery } from './factory/create-analytics-query';

export const useGetRuleHitTable = createAnalyticsQuery<RuleHitTableResponse[]>('rule-hit-table');
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { RuleVsDecisionOutcome } from '@app-builder/models/analytics';
import { createAnalyticsQuery } from './factory/create-analytics-query';

export const useGetRuleVsDecisionOutcome = createAnalyticsQuery<RuleVsDecisionOutcome[]>('rule-vs-decision-outcome');
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { ScreeningHitTableResponse } from '@app-builder/models/analytics';
import { createAnalyticsQuery } from './factory/create-analytics-query';

export const useGetScreeningHitsTable = createAnalyticsQuery<ScreeningHitTableResponse[]>('screening-hits-table');
5 changes: 5 additions & 0 deletions packages/app-builder/src/queries/analytics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './get-available-filters';
export * from './get-decisions-outcomes-per-day';
export * from './get-rule-hit-table';
export * from './get-rule-vs-decision-outcome';
export * from './get-screening-hits-table';
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ import {
FilterSource,
} from '@app-builder/models/analytics';
import { type Scenario } from '@app-builder/models/scenario';
import { useGetAnalytics } from '@app-builder/queries/analytics/get-analytics';
import { useGetAvailableFilters } from '@app-builder/queries/analytics/get-available-filters';
import {
useGetAvailableFilters,
useGetDecisionsOutcomesPerDay,
useGetRuleHitTable,
useGetRuleVsDecisionOutcome,
useGetScreeningHitsTable,
} from '@app-builder/queries/analytics';
import { initServerServices } from '@app-builder/services/init.server';
import { formatDateTimeWithoutPresets, formatDuration } from '@app-builder/utils/format';
import { getRoute } from '@app-builder/utils/routes';
Expand Down Expand Up @@ -204,22 +209,20 @@ export default function Analytics() {
return Array.from(descriptors.values());
}, [availableFilters, seenAvailableFilters]);

const {
data: {
decisionOutcomesPerDay: decisionsData,
ruleHitTable: ruleHitTableData,
screeningHitsTable: screeningHitsTableData,
// decisionsScoreDistribution: decisionsScoreDistributionData,
ruleVsDecisionOutcome: ruleVsDecisionOutcomeData,
} = {
decisionOutcomesPerDay: null,
ruleHitTable: null,
screeningHitsTable: null,
// decisionsScoreDistribution: null,
ruleVsDecisionOutcome: null,
},
isFetching: isAnalyticsFetching,
} = useGetAnalytics({
const { data: decisionsOutcomesPerDayData, isFetching: isDecisionsOutcomesPerDayFetching } =
useGetDecisionsOutcomesPerDay({
scenarioId,
queryString: queryString ?? '',
});
const { data: ruleHitTableData, isFetching: isRuleHitTableFetching } = useGetRuleHitTable({
scenarioId,
queryString: queryString ?? '',
});
const { data: ruleVsDecisionOutcomeData, isFetching: isRuleVsDecisionOutcomeFetching } = useGetRuleVsDecisionOutcome({
scenarioId,
queryString: queryString ?? '',
});
const { data: screeningHitsTableData, isFetching: isScreeningHitsTableFetching } = useGetScreeningHitsTable({
Comment on lines +212 to +225

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The destructuring is not consistent with other uses of useQuery and also makes you alias field. It would be better to keep variables like decisionsOutcomesPerDayQuery

scenarioId,
queryString: queryString ?? '',
});
Expand Down Expand Up @@ -375,19 +378,22 @@ export default function Analytics() {
<div className="flex flex-row gap-v2-md w-full items-stretch">
<div className="basis-full min-w-0">
<Decisions
data={decisionsData as DecisionOutcomesPerPeriod}
data={decisionsOutcomesPerDayData as DecisionOutcomesPerPeriod}
scenarioVersions={scenarioVersions}
isLoading={isAnalyticsFetching}
isLoading={isDecisionsOutcomesPerDayFetching}
/>
</div>
{/* <div className="basis-1/4 min-w-0">
<DecisionsScoreDistribution data={decisionsScoreDistributionData ?? []} />
</div> */}
</div>

<RulesHit data={ruleHitTableData ?? []} isLoading={isAnalyticsFetching} />
<RuleVsDecisionOutcomes data={ruleVsDecisionOutcomeData ?? null} isLoading={isAnalyticsFetching} />
<ScreeningHits data={screeningHitsTableData ?? []} isLoading={isAnalyticsFetching} />
<RulesHit data={ruleHitTableData ?? []} isLoading={isRuleHitTableFetching} />
<RuleVsDecisionOutcomes
data={ruleVsDecisionOutcomeData ?? null}
isLoading={isRuleVsDecisionOutcomeFetching}
/>
<ScreeningHits data={screeningHitsTableData ?? []} isLoading={isScreeningHitsTableFetching} />
</div>
</div>
</I18nProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { createServerFn } from '@app-builder/core/requests';
import { authMiddleware } from '@app-builder/middlewares/auth-middleware';
import { handleRedirectMiddleware } from '@app-builder/middlewares/handle-redirect-middleware';
import { analyticsQuery } from '@app-builder/models/analytics';
import invariant from 'tiny-invariant';
import { z } from 'zod';

const urlParamsSchema = z.object({
scenarioId: z.uuidv4(),
queryName: z.string(),
});

export const action = createServerFn(
[handleRedirectMiddleware, authMiddleware],
async function createAnalyticsQueryAction({ params, request, context }) {
try {
const urlParams = urlParamsSchema.parse(params);
invariant(urlParams.queryName, 'queryName is required');
console.log('urlParams', urlParams);

const body = await request.json();

const queryParams = analyticsQuery.parse({
...body,
scenarioId: urlParams.scenarioId,
});

switch (urlParams.queryName) {
case 'decision-outcomes-per-day': {
const data = await context.authInfo.analytics.getDecisionOutcomesPerDay({
...queryParams,
scenarioId: urlParams.scenarioId,
});
return {
success: true,
data,
};
}

case 'rule-hit-table': {
const data = await context.authInfo.analytics.getRuleHitTable({
...queryParams,
scenarioId: urlParams.scenarioId,
});
return {
success: true,
data,
};
}

case 'rule-vs-decision-outcome': {
const data = await context.authInfo.analytics.getRuleVsDecisionOutcome({
...queryParams,
scenarioId: urlParams.scenarioId,
});
return {
success: true,
data,
};
}

case 'screening-hits-table': {
const data = await context.authInfo.analytics.getScreeningHitsTable({
...queryParams,
scenarioId: urlParams.scenarioId,
});
return {
success: true,
data,
};
}

default: {
return {
success: false,
errors: 'Invalid query name',
};
}
}
} catch (error) {
console.error('error in analytics query', error);
return { success: false, errors: 'Internal server error' };
}
},
);

This file was deleted.

6 changes: 3 additions & 3 deletions packages/app-builder/src/utils/routes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,9 @@ export const routes = [
"file": "routes/ressources+/analytics+/$scenarioId+/available_filters.ts"
},
{
"id": "routes/ressources+/analytics+/$scenarioId+/query",
"path": "ressources/analytics/:scenarioId/query",
"file": "routes/ressources+/analytics+/$scenarioId+/query.ts"
"id": "routes/ressources+/analytics+/$scenarioId+/query.$queryName",
"path": "ressources/analytics/:scenarioId/query/:queryName",
"file": "routes/ressources+/analytics+/$scenarioId+/query.$queryName.ts"
},
{
"id": "routes/ressources+/annotations+/download-file.$annotationId.$fileId",
Expand Down
4 changes: 2 additions & 2 deletions packages/app-builder/src/utils/routes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export type RoutePath =
| '/oidc/auth'
| '/oidc/callback'
| '/ressources/analytics/:scenarioId/available_filters'
| '/ressources/analytics/:scenarioId/query'
| '/ressources/analytics/:scenarioId/query/:queryName'
| '/ressources/annotations/download-file/:annotationId/:fileId'
| '/ressources/app-config'
| '/ressources/auth/logout'
Expand Down Expand Up @@ -245,7 +245,7 @@ export type RouteID =
| 'routes/oidc+/auth'
| 'routes/oidc+/callback'
| 'routes/ressources+/analytics+/$scenarioId+/available_filters'
| 'routes/ressources+/analytics+/$scenarioId+/query'
| 'routes/ressources+/analytics+/$scenarioId+/query.$queryName'
| 'routes/ressources+/annotations+/download-file.$annotationId.$fileId'
| 'routes/ressources+/app-config'
| 'routes/ressources+/auth+/logout'
Expand Down