Skip to content

Commit

Permalink
feat: reimplement report graphs
Browse files Browse the repository at this point in the history
  • Loading branch information
NilsOveTen committed Nov 1, 2024
1 parent a94d8d3 commit de7d2c5
Show file tree
Hide file tree
Showing 16 changed files with 410 additions and 130 deletions.
1 change: 1 addition & 0 deletions config.template.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ window.env = {
REPORT_API_HOST: '$REPORT_API_HOST',
RESOURCE_API_HOST: '$RESOURCE_API_HOST',
SEARCH_SERVICE_HOST: '$SEARCH_SERVICE_HOST',
STATISTICS_SERVICE_HOST: '$STATISTICS_SERVICE_HOST',
USE_DEMO_LOGO: '$USE_DEMO_LOGO',
CATALOG_PORTAL_BASE_URI: '$CATALOG_PORTAL_BASE_URI',
ACCESS_REQUEST_API_HOST: '$ACCESS_REQUEST_API_HOST'
Expand Down
5 changes: 5 additions & 0 deletions deploy/demo/env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ spec:
secretKeyRef:
name: commonurl-demo
key: FDK_SEARCH_SERVICE_BASE_URI
- name: STATISTICS_SERVICE_HOST
valueFrom:
secretKeyRef:
name: commonurl-demo
key: FDK_STATISTICS_SERVICE_BASE_URI
- name: CMS_API_HOST
valueFrom:
secretKeyRef:
Expand Down
5 changes: 5 additions & 0 deletions deploy/prod/env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ spec:
secretKeyRef:
name: commonurl-prod
key: FDK_SEARCH_SERVICE_BASE_URI
- name: STATISTICS_SERVICE_HOST
valueFrom:
secretKeyRef:
name: commonurl-prod
key: FDK_STATISTICS_SERVICE_BASE_URI
- name: CMS_API_HOST
valueFrom:
secretKeyRef:
Expand Down
5 changes: 5 additions & 0 deletions deploy/staging/env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ spec:
secretKeyRef:
name: commonurl-staging
key: FDK_SEARCH_SERVICE_BASE_URI
- name: STATISTICS_SERVICE_HOST
valueFrom:
secretKeyRef:
name: commonurl-staging
key: FDK_STATISTICS_SERVICE_BASE_URI
- name: CMS_API_HOST
valueFrom:
secretKeyRef:
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"@redux-devtools/extension": "^3.3.0",
"@reduxjs/toolkit": "^1.9.7",
"@types/react-document-meta": "^3.0.5",
"apexcharts": "^3.49.1",
"apexcharts": "^3.54.0",
"axios": "^1.7.3",
"bootstrap": "^5.3.3",
"buffer": "^6.0.3",
Expand Down
24 changes: 24 additions & 0 deletions src/api/statistics-api/host.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import axios from 'axios';
import cleanDeep from 'clean-deep';
import { getConfig } from '../../config';
import type { TimeSeriesRequest } from '../../types';

interface Props {
path: string;
method: any;
data?: any;
params?: URLSearchParams;
}

export const statisticsApi = ({ path, method, data, params }: Props) =>
axios({
url: `${getConfig().statisticsApi.host}/${path}`,
method,
data,
params
})
.then(response => cleanDeep(response.data))
.catch(() => null);

export const statisticsApiPost = (path: string, body: TimeSeriesRequest) =>
statisticsApi({ path, method: 'POST', data: body });
76 changes: 76 additions & 0 deletions src/api/statistics-api/time-series.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { statisticsApiPost } from './host';
import type { TimeSeriesPoint, TimeSeriesRequest } from '../../types';
import { getConfig } from '../../config';

const timeSeriesBody = (
resourceType: string,
orgPath: string | undefined
): TimeSeriesRequest => {
let start = '2023-02-01';
if (resourceType === 'DATASET') {
start = '2022-11-01';
}
if (resourceType === 'INFORMATION_MODEL') {
start = '2024-01-01';
}
const now = new Date();
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1, 12)
.toISOString()
.split('T')[0];
const body: TimeSeriesRequest = {
start,
end: firstDayOfMonth,
interval: 'MONTH',
filters: {
resourceType: { value: resourceType },
orgPath: null,
transport: null
}
};

if (orgPath !== undefined) {
body.filters.orgPath = { value: orgPath };
}

if (getConfig().isNapProfile) {
body.filters.transport = { value: true };
}

return body;
};

const extractLabelsAndData = (
timeSeries: Partial<TimeSeriesPoint> | null
): number[][] => {
let timeSeriesData: number[][] = [];
if (Array.isArray(timeSeries)) {
timeSeriesData = timeSeries.map(({ date, count }) => [
Date.parse(date),
count
]);
}
return timeSeriesData;
};

const timeSeriesRequest = (body: TimeSeriesRequest) =>
statisticsApiPost('time-series', body);

export const conceptTimeSeriesRequest = (orgPath: string | undefined) =>
timeSeriesRequest(timeSeriesBody('CONCEPT', orgPath)).then(
extractLabelsAndData
);

export const dataServiceTimeSeriesRequest = (orgPath: string | undefined) =>
timeSeriesRequest(timeSeriesBody('DATA_SERVICE', orgPath)).then(
extractLabelsAndData
);

export const datasetTimeSeriesRequest = (orgPath: string | undefined) =>
timeSeriesRequest(timeSeriesBody('DATASET', orgPath)).then(
extractLabelsAndData
);

export const infoModelTimeSeriesRequest = (orgPath: string | undefined) =>
timeSeriesRequest(timeSeriesBody('INFORMATION_MODEL', orgPath)).then(
extractLabelsAndData
);
3 changes: 3 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const env = window.env || {
// env.FDK_PORTAL_BASE_URI = 'https://staging.fellesdatakatalog.digdir.no';
// env.SEARCH_SERVICE_HOST =
// 'https://search.api.staging.fellesdatakatalog.digdir.no';
// env.STATISTICS_SERVICE_HOST =
// 'https://statistics.api.staging.fellesdatakatalog.digdir.no';
// env.CMS_API_HOST = 'https://cms-fellesdatakatalog.digdir.no';
// env.FDK_CMS_BASE_URI = 'https://cms.staging.fellesdatakatalog.digdir.no';
// env.ORGANIZATION_HOST =
Expand Down Expand Up @@ -50,6 +52,7 @@ const config = {
reportApi: { host: env.REPORT_API_HOST },
resourceApi: { host: env.RESOURCE_API_HOST },
searchApi: { host: env.SEARCH_SERVICE_HOST },
statisticsApi: { host: env.STATISTICS_SERVICE_HOST },
store: { useLogger: env.REDUX_LOG === 'true' },
isNapProfile: isNapProfile(env.NAP_HOST),
useDemoLogo: env.USE_DEMO_LOGO,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import NewIcon from '../../../../images/icon-new-md.svg';
import { PATHNAME_CONCEPTS } from '../../../../constants/constants';
import { patchSearchQuery } from '../../../../lib/addOrReplaceUrlParam';
import localization from '../../../../lib/localization';
import { Line } from '../../../../components/charts';
import { getTranslateText } from '../../../../lib/translateText';
import { ContainerBoxRegular, ContainerPaneContent } from '../../styled';

Expand All @@ -32,6 +33,7 @@ interface AllReferencedConceptIdentifiers {
}
interface Props extends RouteComponentProps {
conceptsReport?: Partial<ConceptsReport> & AllReferencedConceptIdentifiers;
conceptsTimeSeries: any;
}

const ConceptReport: FC<Props> = ({
Expand All @@ -41,74 +43,98 @@ const ConceptReport: FC<Props> = ({
newLastWeek = 0,
organizationCount = 0,
allReferencedConcepts = []
} = {}
}) => (
<ThemeProvider theme={theme.extendedColors[Entity.CONCEPT]}>
<main id='content'>
<ContainerPaneContent>
<ContainerBoxRegular>
<BoxRegular>
<StatisticsRegular to={`${PATHNAME_CONCEPTS}${searchParams}`}>
<IllustrationWithCount
icon={<ConceptIcon />}
count={totalObjects}
/>
<SC.StatisticsRegular.Label>
{localization.report.conceptsDescription}
</SC.StatisticsRegular.Label>
</StatisticsRegular>
</BoxRegular>
</ContainerBoxRegular>
<ContainerBoxRegular>
<BoxRegular>
<StatisticsRegular
to={`${PATHNAME_CONCEPTS}${patchSearchQuery(
Filter.LASTXDAYS,
'7'
)}`}
>
<IllustrationWithCount icon={<NewIcon />} count={newLastWeek} />
<SC.StatisticsRegular.Label>
{localization.report.newPastWeek}
</SC.StatisticsRegular.Label>
</StatisticsRegular>
</BoxRegular>
</ContainerBoxRegular>
</ContainerPaneContent>

<div className='row'>
<div className='col-12'>
<BoxRegular>
<StatisticsRegular to='' as='div'>
<IllustrationWithCount
icon={<ConceptIcon />}
count={organizationCount}
/>
<SC.StatisticsRegular.Label variant={FontVariant.LARGE}>
{localization.report.organizationsConcept}
</SC.StatisticsRegular.Label>
</StatisticsRegular>
</BoxRegular>
</div>
</div>
} = {},
conceptsTimeSeries = []
}) => {
conceptsTimeSeries.push([Date.now(), totalObjects]);
return (
<ThemeProvider theme={theme.extendedColors[Entity.CONCEPT]}>
<main id='content'>
<ContainerPaneContent>
<ContainerBoxRegular>
<BoxRegular>
<StatisticsRegular to={`${PATHNAME_CONCEPTS}${searchParams}`}>
<IllustrationWithCount
icon={<ConceptIcon />}
count={totalObjects}
/>
<SC.StatisticsRegular.Label>
{localization.report.conceptsDescription}
</SC.StatisticsRegular.Label>
</StatisticsRegular>
</BoxRegular>
</ContainerBoxRegular>
<ContainerBoxRegular>
<BoxRegular>
<StatisticsRegular
to={`${PATHNAME_CONCEPTS}${patchSearchQuery(
Filter.LASTXDAYS,
'7'
)}`}
>
<IllustrationWithCount icon={<NewIcon />} count={newLastWeek} />
<SC.StatisticsRegular.Label>
{localization.report.newPastWeek}
</SC.StatisticsRegular.Label>
</StatisticsRegular>
</BoxRegular>
</ContainerBoxRegular>
</ContainerPaneContent>

{allReferencedConcepts?.length > 0 && (
<div className='row'>
<div className='col-12'>
<BoxRegular header={localization.report.conceptReferenced}>
{allReferencedConcepts.map(
({ id, prefLabel }: Partial<Concept>) => (
<ConceptReportSC.ConceptLink key={id} to={`/concepts/${id}`}>
{getTranslateText(prefLabel)}
</ConceptReportSC.ConceptLink>
)
)}
<BoxRegular>
<StatisticsRegular to='' as='div'>
<IllustrationWithCount
icon={<ConceptIcon />}
count={organizationCount}
/>
<SC.StatisticsRegular.Label variant={FontVariant.LARGE}>
{localization.report.organizationsConcept}
</SC.StatisticsRegular.Label>
</StatisticsRegular>
</BoxRegular>
</div>
</div>
)}
</main>
</ThemeProvider>
);

{conceptsTimeSeries?.length > 0 && conceptsTimeSeries?.length > 0 && (
<div className='row'>
<div className='col-12'>
<BoxRegular
header={localization.report.growth}
subHeader={localization.report.conceptGrowthFromFirstPublish}
>
<Line
name={localization.conceptLabel}
data={conceptsTimeSeries}
lineColor={theme.extendedColors[Entity.CONCEPT].dark}
/>
</BoxRegular>
</div>
</div>
)}

{allReferencedConcepts?.length > 0 && (
<div className='row'>
<div className='col-12'>
<BoxRegular header={localization.report.conceptReferenced}>
{allReferencedConcepts.map(
({ id, prefLabel }: Partial<Concept>) => (
<ConceptReportSC.ConceptLink
key={id}
to={`/concepts/${id}`}
>
{getTranslateText(prefLabel)}
</ConceptReportSC.ConceptLink>
)
)}
</BoxRegular>
</div>
</div>
)}
</main>
</ThemeProvider>
);
};

export default withRouter(memo(ConceptReport));
Loading

0 comments on commit de7d2c5

Please sign in to comment.