Skip to content

Commit

Permalink
Merge commit '79f9c693853b697d37ec8b5e87453063a8625dbe' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
ahonestla committed Jan 28, 2025
2 parents 22a43fb + 79f9c69 commit 31790ec
Show file tree
Hide file tree
Showing 27 changed files with 507 additions and 439 deletions.
11 changes: 5 additions & 6 deletions client/src/api/trends/_utils/variation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
export default function variation(count, max_year) {
const startValue = count?.[max_year - 1] || 0
const endValue = count?.[max_year] || 0
export default function variation(count, sum, minYear, maxYear) {
const currentVolume = count?.[maxYear] || 0
const averageVolume = (sum - currentVolume) / (maxYear - minYear - 1)

if (!startValue && !endValue) return 0
if (!startValue) return Infinity
const variation = currentVolume >= averageVolume ? currentVolume / averageVolume : -averageVolume / currentVolume

return (endValue - startValue) / startValue
return variation
}
34 changes: 27 additions & 7 deletions client/src/api/trends/publications.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { postHeaders, publicationsIndex } from "../../config/api"
import { ElasticAggregation, ElasticBucket, ElasticBuckets } from "../../types/commons"
import { TrendsArgs } from "../../types/trends"
import { TrendsArgs, TrendsRanking } from "../../types/trends"
import { FIELDS } from "../publications/_utils/constants"
import { CONFIG } from "./config"
import { citationsTrends, publicationsTrends } from "./trends"

type TrendsAggregation = Array<ElasticBucket & { model: ElasticAggregation }>

export async function getPublicationsTrends({ cursor, model, query, years, filters, normalized }: TrendsArgs) {
export async function getPublicationsTrends({
page,
model,
query,
years,
filters,
normalized,
includes,
}: TrendsArgs): Promise<TrendsRanking> {
const body: any = {
size: 0,
query: {
Expand All @@ -30,6 +38,7 @@ export async function getPublicationsTrends({ cursor, model, query, years, filte
model: { terms: { field: CONFIG[model].field, size: 60000 / years.length } },
},
},
count: { value_count: { field: "id.keyword" } },
},
}

Expand All @@ -47,18 +56,27 @@ export async function getPublicationsTrends({ cursor, model, query, years, filte
}

const json = await res.json()
const count: number = json?.aggregations?.count?.value || 0
const aggregation: TrendsAggregation = json?.aggregations?.["years"]?.buckets

if (!aggregation?.length) {
console.error(`Elasticsearch error: no aggregation found for years ${years[0]}-${years[years.length - 1]}`)
return null
}

const trends = publicationsTrends(aggregation, cursor, years, normalized)
return trends
const trends = publicationsTrends(aggregation, page, years, normalized, includes)
return { ...trends, sourceCount: count }
}

export async function getCitationsTrends({ cursor, model, query, years, filters, normalized }: TrendsArgs) {
export async function getCitationsTrends({
page,
model,
query,
years,
filters,
normalized,
includes,
}: TrendsArgs): Promise<TrendsRanking> {
const body: any = {
size: 0,
query: {
Expand All @@ -84,6 +102,7 @@ export async function getCitationsTrends({ cursor, model, query, years, filters,
),
},
},
count: { value_count: { field: "id.keyword" } },
},
}

Expand All @@ -101,13 +120,14 @@ export async function getCitationsTrends({ cursor, model, query, years, filters,
}

const json = await res.json()
const count: number = json?.aggregations?.count?.value || 0
const aggregation: ElasticBuckets = json?.aggregations?.model?.buckets

if (!aggregation?.length) {
console.error(`Elasticsearch error: no aggregation found for years ${years[0]}-${years[years.length - 1]}`)
return null
}

const trends = citationsTrends(aggregation, cursor, years, normalized)
return trends
const trends = citationsTrends(aggregation, page, years, normalized, includes)
return { ...trends, sourceCount: count }
}
54 changes: 28 additions & 26 deletions client/src/api/trends/trends.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { linearRegressionSlope } from "./_utils/regression"
import variation from "./_utils/variation"

const EXCLUDE_WORDS = [""]
const PAGE_ITEMS = 10
const ITEMS_PER_PAGE = 25

type TrendsAggregation = Array<ElasticBucket & { [x: string]: ElasticAggregation }>

function computeTrends(data: Array<any>, cursor: number, years: Array<number>, normalized: boolean) {
function computeTrends(data: Array<any>, page: number, years: Array<number>, normalized: boolean, includes: string) {
const maxYear = years[years.length - 1]
const minItems = (cursor || 0) * PAGE_ITEMS
const maxItems = ((cursor || 0) + 1) * PAGE_ITEMS
const minYear = years[0]
const minItems = (page - 1) * ITEMS_PER_PAGE
const maxItems = page * ITEMS_PER_PAGE

// Filter items
const items = data.filter(({ label }) => !EXCLUDE_WORDS.includes(label))
Expand All @@ -22,42 +23,36 @@ function computeTrends(data: Array<any>, cursor: number, years: Array<number>, n
item.norm_slope = slope / item.sum
item.intercept = intercept
item.r2 = r2
item.diff = variation(item.count, maxYear)
item.variation = variation(item.count, item.sum, minYear, maxYear)
})

// Sort items by volume max year
const sortedItems = items.sort((a, b) => (b?.count?.[maxYear] || 0) - (a?.count?.[maxYear] || 0))

// Filter labels
const filteredItems = sortedItems.filter(({ label }: { label: string }) => label.toLowerCase().includes(includes))

// Compute top items
const topCount = sortedItems.slice(minItems, maxItems)
// const topDiff = sortedItems
// .slice()
// .sort((a, b) => b.diff - a.diff)
// .slice(0, MAX_ITEMS)
// const botDiff = sortedItems
// .slice()
// .sort((a, b) => (b?.count?.[min_year - 1] || 0) - (a?.count?.[maxYear - 1] || 0))
// .sort((a, b) => a.diff - b.diff)
// .slice(0, MAX_ITEMS)
const topSlope = sortedItems
const topCount = filteredItems.slice(minItems, maxItems)
const topSlope = filteredItems
.slice()
.sort((a, b) => (normalized ? b.norm_slope - a.norm_slope : b.slope - a.slope))
.slice(minItems, maxItems)
const botSlope = sortedItems
const botSlope = filteredItems
.slice()
.sort((a, b) => (normalized ? a.norm_slope - b.norm_slope : a.slope - b.slope))
.slice(minItems, maxItems)

const trends = {
views: {
ranking: {
"count-top": topCount,
// "diff-top": topDiff,
// "diff-bot": botDiff,
"trend-top": topSlope,
"trend-bot": botSlope,
},
nextCursor: maxItems < sortedItems.length ? cursor + 1 : undefined,
total: sortedItems.length,
searchTotal: sortedItems.length,
searchPages: Math.ceil(sortedItems.length / ITEMS_PER_PAGE),
filteredTotal: filteredItems.length,
filteredPages: Math.ceil(filteredItems.length / ITEMS_PER_PAGE),
}

return trends
Expand All @@ -67,7 +62,8 @@ export function publicationsTrends(
aggregation: TrendsAggregation,
cursor: number,
years: Array<number>,
normalized: boolean
normalized: boolean,
includes: string
) {
// Items count by year
const _items: Record<string, Record<string, any>> = aggregation.reduce((acc, bucket) => {
Expand All @@ -86,11 +82,17 @@ export function publicationsTrends(
}, {})
const items = Object.values(_items)

const trends = computeTrends(items, cursor, years, normalized)
const trends = computeTrends(items, cursor, years, normalized, includes)
return trends
}

export function citationsTrends(aggregation: ElasticBuckets, cursor: number, years: Array<number>, normalized: boolean) {
export function citationsTrends(
aggregation: ElasticBuckets,
cursor: number,
years: Array<number>,
normalized: boolean,
includes: string
) {
// Items citations count by year
const _items: Record<string, Record<string, any>> = aggregation.reduce((acc, item) => {
years.forEach((year) => {
Expand All @@ -109,6 +111,6 @@ export function citationsTrends(aggregation: ElasticBuckets, cursor: number, yea
}, {})
const items = Object.values(_items)

const trends = computeTrends(items, cursor, years, normalized)
const trends = computeTrends(items, cursor, years, normalized, includes)
return trends
}
19 changes: 19 additions & 0 deletions client/src/pages/trends/components/info/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Container, Text } from "@dataesr/dsfr-plus"
import useTrends from "../../hooks/useTrends"
import { useIntl } from "react-intl"

export default function TrendsViewInfo() {
const intl = useIntl()
const { trends } = useTrends()

const topicsCount = trends?.searchTotal || 0
const publicationsCount = trends?.sourceCount || 0

return (
<Container>
<Text className="fr-mb-1w">
{intl.formatMessage({ id: "trends.ranking.info.text" }, { topics: topicsCount, publications: publicationsCount })}
</Text>
</Container>
)
}
29 changes: 0 additions & 29 deletions client/src/pages/trends/components/panel/button/index.tsx

This file was deleted.

101 changes: 0 additions & 101 deletions client/src/pages/trends/components/panel/header/index.tsx

This file was deleted.

Loading

0 comments on commit 31790ec

Please sign in to comment.