Skip to content

Commit

Permalink
feat(patents): add graph for cpc classification on a organization
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihoub2 committed Nov 4, 2024
1 parent a6f7d2d commit 08c978a
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 157 deletions.
3 changes: 2 additions & 1 deletion client/.env.production
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
VITE_API_URL="/api"
VITE_MISTRAL_URL="/mistral"
VITE_APP_MATOMO_BASE_URL="https://piwik.enseignementsup-recherche.pro"
VITE_APP_MATOMO_SITE_ID="36"
VITE_APP_MATOMO_SITE_ID="36"
VITE_APP_ENV="production"
3 changes: 2 additions & 1 deletion client/.env.staging
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
VITE_API_URL="/api"
VITE_MISTRAL_URL="/mistral"
VITE_APP_MATOMO_BASE_URL="https://matomo.staging.dataesr.ovh"
VITE_APP_MATOMO_SITE_ID="4"
VITE_APP_MATOMO_SITE_ID="4"
VITE_APP_ENV="staging"
30 changes: 23 additions & 7 deletions client/src/api/patents/[id]/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export async function getPatentById(id: string): Promise<Patent> {
if (!patent) throw new Error("404");
return { ...patent, _id: data?.hits?.hits?.[0]._id };
}

export async function getCpcAggregation(value: string): Promise<Patent> {
const body: any = {
size: 10000,
Expand All @@ -49,9 +50,17 @@ export async function getCpcAggregation(value: string): Promise<Patent> {
aggs: {
byCpc: {
terms: {
field: "cpc.ss_classe.code.keyword",
field: "cpc.classe.code.keyword",
size: 10000,
},
aggs: {
bySectionLabel: {
terms: {
field: "cpc.section.label.keyword",
size: 1,
},
},
},
},
},
};
Expand All @@ -68,7 +77,7 @@ export async function getCpcAggregation(value: string): Promise<Patent> {
const hits = data?.hits?.hits;

const labelsByCode = hits.reduce((acc: any, hit: any) => {
const cpcGroups = hit._source.cpc?.ss_classe ?? [];
const cpcGroups = hit._source.cpc?.classe ?? [];
cpcGroups.forEach((cpc: any) => {
if (!acc[cpc.code]) {
acc[cpc.code] = cpc.label;
Expand All @@ -77,11 +86,18 @@ export async function getCpcAggregation(value: string): Promise<Patent> {
return acc;
}, {});

const patent = buckets.map((bucket: any) => ({
code: bucket.key,
doc_count: bucket.doc_count,
label: labelsByCode[bucket.key] || "Label non trouvé",
}));
const patent = buckets.map((bucket: any) => {
console.log(bucket);
const sectionLabel =
bucket.bySectionLabel?.buckets?.[0]?.key || "Label de section non trouvé";

return {
code: bucket.key,
doc_count: bucket.doc_count,
label: labelsByCode[bucket.key] || "Label non trouvé",
sectionLabel,
};
});

return patent;
}
131 changes: 94 additions & 37 deletions client/src/components/patent-chart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,131 @@ import React from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import HighchartsMore from "highcharts/highcharts-more";
import { useIntl } from "react-intl";

HighchartsMore(Highcharts);

type CpcChartProps = {
data: {
label: any;
name: string;
label: string;
doc_count: number;
code: string;
}[];
};

const sectionLabels: Record<string, string> = {
A: "organizations.sectionLabels.humanNecessities",
B: "organizations.sectionLabels.performingOperations",
C: "organizations.sectionLabels.chemistryMetallurgy",
D: "organizations.sectionLabels.textilesPaper",
E: "organizations.sectionLabels.fixedConstructions",
F: "organizations.sectionLabels.mechanicalEngineering",
G: "organizations.sectionLabels.physics",
H: "organizations.sectionLabels.electricity",
Y: "organizations.sectionLabels.other",
};

const CpcChart: React.FC<CpcChartProps> = ({ data }) => {
const chartData = data.map((item) => ({
name: item.label,
value: item.doc_count,
code: item.code,
}));
const intl = useIntl();
const colorPalette = [
"#7AB1E8",
"#21AB8E",
"#f6e157",
"#CE70CC",
"#FF9575",
"#FFCA00",
"#FF732C",
"#E6BE92",
"#AEA397",
];

const groupedData = data.reduce((acc, item) => {
const firstLetter = item.code.charAt(0).toUpperCase();
if (!acc[firstLetter]) acc[firstLetter] = [];
acc[firstLetter].push({
name: item.code,
value: item.doc_count,
label: item.label,
});
return acc;
}, {} as Record<string, { name: string; value: number; label: string }[]>);

const seriesData = Object.entries(groupedData).map(
([letter, items], index) => ({
name:
intl.formatMessage({ id: sectionLabels[letter] }) ||
`Section ${letter}`,
color: colorPalette[index % colorPalette.length],
data: items.map((item) => ({
name: item.name,
value: item.value,
label: item.label,
})),
})
);

const values = seriesData.flatMap((series) =>
series.data.map((point) => point.value)
);
const zMin = Math.min(...values);
const zMax = Math.max(...values);

const options = {
chart: {
type: "packedbubble",
layoutAlgorithm: {
splitSeries: false,
},
height: "100%",
backgroundColor: "#f4f4f4",
height: "100%",
},
title: {
text: intl.formatMessage({ id: "organizations.patents.chart.title" }),
},
tooltip: {
pointFormat: "<b>{point.name}</b> (Code: {point.code}): {point.value}",
formatter: function () {
return `<b>${this.point.name}</b> (Code: ${this.point.code}): ${this.point.value}`;
const familiesText = intl.formatMessage(
{
id: "organizations.patents.chart.families",
defaultMessage: "{value} famille{plural}",
},
{
value: this.point.value,
plural: this.point.value > 1 ? "s" : "",
}
);
return `<b>${this.point.name}</b> - <b>${this.point.label}</b>: ${familiesText}`;
},
},
series: [
{
minSize: 20,
maxSize: 100,
data: chartData.map((item) => ({
name: item.name,
value: item.value,
code: item.code,
})),
},
],

plotOptions: {
packedbubble: {
minSize: 10,
maxSize: 100,
zMin: 0,
zMax: 100,
minSize: "45%",
maxSize: "120%",
zMin: zMin,
zMax: zMax,
layoutAlgorithm: {
gravitationalConstant: 0.05,
splitSeries: true,
seriesInteraction: false,
parentNodeLimit: true,
},
dataLabels: {
enabled: true,
format: "{point.value}",
},
cursor: "pointer",
point: {
events: {
click: function () {
window.location.href = `/search/patents?q=${this.code}`;
},
format: "{point.name}",
style: {
color: "black",
textOutline: "none",
fontWeight: "normal",
},
},
},
},
series: seriesData,
};

return <HighchartsReact highcharts={Highcharts} options={options} />;
return (
<>
<HighchartsReact highcharts={Highcharts} options={options} />
</>
);
};

export default CpcChart;
59 changes: 0 additions & 59 deletions client/src/components/patent-chart/indexA.tsx

This file was deleted.

Loading

0 comments on commit 08c978a

Please sign in to comment.