Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/staging'
Browse files Browse the repository at this point in the history
  • Loading branch information
folland87 committed Mar 27, 2024
2 parents 197405f + 6b10863 commit 98de075
Show file tree
Hide file tree
Showing 75 changed files with 1,914 additions and 953 deletions.
8 changes: 5 additions & 3 deletions client/locales.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
| /pages/bugs | OK | Mihoub | FR,EN,ES,DE |
| /pages/home | OK | Mihoub | FR,EN,ES,DE |
| /pages/organization | OK | Mihoub | FR,EN,ES,DE |
| /pages/projects | TODO | Mihoub | FR,EN,ES,DE |
| /pages/publications | TODO | Mihoub | FR,EN,ES,DE |
| /pages/projects | OK | FRED | FR,EN,ES,DE |
| /pages/publications | OK | FRED | FR,EN,ES,DE |
| /components/api-deprecation-banner | OK | FRED | FR,EN |
| /components/contact-form | OK | FRED | FR,EN |
| /components/copy | OK | FRED | FR,EN |
Expand All @@ -25,4 +25,6 @@
| /components/truncate | OK | FRED | FR,EN,ES,DE |
| /components/websites | OK | FRED | FR,EN |
| /components/wiki | OK | FRED | FR,EN |
| /components/share | TODO | FRED | FR,EN |
| /components/share | OK | FRED | FR,EN |
| /components/analytics-graph | OK | FRED | FR,EN |
| /layout/* | OK | FRED | FR,EN |
40 changes: 17 additions & 23 deletions client/package-lock.json

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

32 changes: 17 additions & 15 deletions client/src/api/networks/network/communities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ import Graph from "graphology-types"
import louvain from "graphology-communities-louvain"
import { arrayPush, labelClean } from "../_utils/functions"
import { networkSearchHits } from "../search/search"
import { ElasticHits } from "../../../types/network"
import { ElasticHits, NetworkCommunities, NetworkFilters } from "../../../types/network"
import { openAiLabeledClusters } from "./openai"
import { vosColors } from "../_utils/constants"
import { GetColorName } from "hex-color-to-color-name"

const communityGetAttribute = (graph: Graph, community: number, name: string): Array<any> =>
const communityGetAttribute = (graph: Graph, community: number, name: string): Array<string> | Array<number> =>
graph.reduceNodes(
(acc, _, attr) => (attr.community === community && attr?.[name] ? (acc = arrayPush(acc, attr[name])) : acc),
[]
)

const communityGetLinks = (graph: Graph, community: number): Array<string> => [
...new Set(communityGetAttribute(graph, community, "links").flat(1)),
...new Set(communityGetAttribute(graph, community, "links").flat(1).map(String)),
]

const communityGetIds = (graph: Graph, community: number): Array<string> =>
Expand All @@ -24,18 +24,18 @@ const communityGetSize = (graph: Graph, community: number): number =>
graph.filterNodes((_, attr) => attr?.community === community).length

const communityGetMaxYear = (graph: Graph, community: number): number =>
Math.max(...communityGetAttribute(graph, community, "maxYear"))
Math.max(...communityGetAttribute(graph, community, "maxYear").map(Number))

const communityGetMaxWeightNodes = (graph: Graph, community: number): Array<string> => {
const maxWeight = Math.max(...communityGetAttribute(graph, community, "weight"))
const maxWeight = Math.max(...communityGetAttribute(graph, community, "weight").map(Number))
const labels = graph.reduceNodes(
(acc, _, attr) => (acc = attr?.community === community && attr?.weight === maxWeight ? [...acc, attr.label] : acc),
[]
)
return labels
}

const communityGetYears = (hits: ElasticHits) =>
const communityGetYears = (hits: ElasticHits): Record<string, number> =>
hits.reduce((acc, hit) => {
const year = hit.year
acc[year] = acc[year] ? acc[year] + 1 : 1
Expand All @@ -44,7 +44,7 @@ const communityGetYears = (hits: ElasticHits) =>

// const communityGetPublications = (hits: ElasticHits): Array<string> => hits.map((hit) => hit.title.default)

const communityGetDomains = (hits: ElasticHits): any =>
const communityGetDomains = (hits: ElasticHits): Record<string, number> =>
hits.reduce((acc, hit) => {
if (hit?.domains) {
hit.domains.forEach(({ label, count }) => {
Expand All @@ -58,9 +58,10 @@ const communityGetDomains = (hits: ElasticHits): any =>
const communityGetOaPercent = (hits: ElasticHits): number =>
(hits.map((hit) => hit.isOa).filter(Boolean).length / hits.length) * 100

export default async function communitiesCreate(graph: Graph, computeClusters: boolean): Promise<any> {
const query = graph.getAttribute("query")
const model = graph.getAttribute("model")
export default async function communitiesCreate(graph: Graph, computeClusters: boolean): Promise<NetworkCommunities> {
const query: string = graph.getAttribute("query")
const model: string = graph.getAttribute("model")
const filters: NetworkFilters = graph.getAttribute("filters")

// Assign communities
louvain.assign(graph)
Expand All @@ -74,21 +75,22 @@ export default async function communitiesCreate(graph: Graph, computeClusters: b
// Create communities array
const communities = Promise.all(
Array.from({ length: count }, async (_, index) => {
const hits = await networkSearchHits(query, model, communityGetLinks(graph, index))
// Get elastic publications
const hits = await networkSearchHits({ model, query, filters, links: communityGetLinks(graph, index) })

const community = {
index: index,
cluster: index,
label: vosColors?.[index] ? GetColorName(vosColors[index]) : `Unnamed ${index + 1}`,
color: vosColors?.[index] ?? "#e2e2e2",
ids: communityGetIds(graph, index),
size: communityGetSize(graph, index),
ids: communityGetIds(graph, index),
maxYear: communityGetMaxYear(graph, index),
maxWeightNodes: communityGetMaxWeightNodes(graph, index),
...(hits && {
domains: communityGetDomains(hits),
oaPercent: communityGetOaPercent(hits),
hits: hits.length,
years: communityGetYears(hits),
domains: communityGetDomains(hits),
oaPercent: communityGetOaPercent(hits),
}),
}
return community
Expand Down
7 changes: 4 additions & 3 deletions client/src/api/networks/network/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Attributes } from "graphology-types"
import { NetworkConfig } from "../../../types/network"

const CONFIG = {
Expand Down Expand Up @@ -41,7 +42,7 @@ const CONFIG = {
},
},
domains: {
url: (_: string, attr: any) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`,
url: (_: string, attr: Attributes) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`,
terminology: {
item: "domain",
items: "domains",
Expand All @@ -54,7 +55,7 @@ const CONFIG = {
},
},
software: {
url: (_: string, attr: any) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`,
url: (_: string, attr: Attributes) => `/search/publications?q="${attr.label.replace(/ /g, "+")}"`,
terminology: {
item: "software",
items: "software",
Expand All @@ -73,7 +74,7 @@ const configGetItemDescription = () =>
const configGetLinkDescription = (model: string) =>
`<div class='description_heading'>Co-${model} link</div><div class='description_label'>`

export function configGetItemUrl(model: string, key: string, attr: any): string {
export function configGetItemUrl(model: string, key: string, attr: Attributes): string {
const targetUrl = CONFIG?.[model]?.url(key, attr) ?? ""
const baseUrl = window?.location?.href?.split("/networks")[0] ?? ""
return baseUrl + targetUrl
Expand Down
16 changes: 7 additions & 9 deletions client/src/api/networks/network/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import subgraph from "graphology-operators/subgraph"
import { connectedComponents } from "graphology-components"
import random from "graphology-layout/random"
import forceAtlas2 from "graphology-layout-forceatlas2"
import { NetworkData } from "../../../types/network"
import { ElasticBuckets, NetworkFilters, NetworkData } from "../../../types/network"
import communitiesCreate from "./communities"
import { configGetItemUrl } from "./config"

Expand All @@ -15,13 +15,15 @@ const nodeConcatMaxYear = (nodeMaxYear: number, maxYear: number) => (nodeMaxYear
export default async function networkCreate(
query: string,
model: string,
aggregation: Array<any>,
filters: NetworkFilters,
aggregation: ElasticBuckets,
computeClusters: boolean
): Promise<NetworkData> {
// Create Graph object
let graph = new UndirectedGraph()
graph.setAttribute("query", query)
graph.setAttribute("model", model)
graph.setAttribute("filters", filters)

aggregation.forEach((item) => {
const { key, doc_count: count } = item
Expand Down Expand Up @@ -88,7 +90,7 @@ export default async function networkCreate(
console.log("Graph nodes", Array.from(graph.nodeEntries()))

// Create network
const network = {
const network: NetworkData = {
items: graph.mapNodes((key, attr) => ({
id: key,
x: attr.x,
Expand All @@ -102,15 +104,11 @@ export default async function networkCreate(
links: graph.mapEdges((_, attr, source, target) => ({
source_id: source,
target_id: target,
strength: attr?.weight,
})),
clusters: communities.map((community) => ({
...community,
cluster: community.index + 1,
strength: attr.weight,
})),
clusters: communities,
}

console.log("network", network)

return network
}
7 changes: 4 additions & 3 deletions client/src/api/networks/network/openai.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import MistralClient, { ResponseFormats } from "@mistralai/mistralai"
import { NetworkCommunities } from "../../../types/network"

const ENABLED = false

async function mistralLabelsFromDomains(domains: any): Promise<string> {
async function mistralLabelsFromDomains(domains: string): Promise<string> {
const { VITE_MISTRAL_API_KEY } = import.meta.env

if (!VITE_MISTRAL_API_KEY) {
Expand Down Expand Up @@ -35,7 +36,7 @@ async function mistralLabelsFromDomains(domains: any): Promise<string> {
return answer
}

export async function openAiLabeledClusters(clusters: Array<any>) {
export async function openAiLabeledClusters(clusters: NetworkCommunities): Promise<NetworkCommunities> {
if (!ENABLED) return clusters

const prefix = "list"
Expand All @@ -50,7 +51,7 @@ export async function openAiLabeledClusters(clusters: Array<any>) {
acc = acc + `${prefix}${index + 1} = [${topDomains}], `
}
return acc
}, "")
}, "") as string
console.log("domains", domains)

if (!domains) return clusters
Expand Down
15 changes: 6 additions & 9 deletions client/src/api/networks/search/search.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { publicationsIndex, postHeaders } from "../../../config/api"
import { Network, NetworkSearchBody, NetworkSearchArgs, ElasticHits } from "../../../types/network"
import { Network, NetworkSearchBody, NetworkSearchArgs, ElasticHits, NetworkSearchHitsArgs } from "../../../types/network"
import networkCreate from "../network/network"
import configCreate from "../network/config"
import infoCreate from "../network/info"
Expand Down Expand Up @@ -43,7 +43,7 @@ export async function networkSearch({ model, query, options, filters }: NetworkS
headers: postHeaders,
})
if (res.status !== 200) {
throw new Error(`Elasticsearch error: ${res.status}`);
throw new Error(`Elasticsearch error: ${res.status}`)
}
const json = await res.json()
console.log("endOfSearch", json)
Expand All @@ -54,7 +54,7 @@ export async function networkSearch({ model, query, options, filters }: NetworkS
}

const computeClusters = options?.computeClusters ?? false
const network = await networkCreate(query, model, aggregation, computeClusters)
const network = await networkCreate(query, model, filters, aggregation, computeClusters)
const config = configCreate(model)
const info = infoCreate(query, model)

Expand All @@ -72,7 +72,8 @@ export async function networkSearch({ model, query, options, filters }: NetworkS
return data
}

export async function networkSearchHits(query: string, model: string, links: Array<string>): Promise<ElasticHits> {
export async function networkSearchHits({ model, query, filters, links }: NetworkSearchHitsArgs): Promise<ElasticHits> {
const linksFilter = { terms: { [`co_${model}.keyword`]: links } }
const body = {
size: DEFAULT_SIZE,
_source: HIT_FIELDS,
Expand All @@ -86,11 +87,7 @@ export async function networkSearchHits(query: string, model: string, links: Arr
},
},
],
filter: {
terms: {
[`co_${model}.keyword`]: links,
},
},
filter: filters.concat(linksFilter),
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/api/publications/[id]/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export async function getPublicationById(id: string): Promise<Publication> {
_source: [
"title", "summary", "authors.fullName", "authors.person", "authors.role", "authors.affiliations",
"domains", "affiliations", "source", "isOa", 'type', 'id', "year", "oaEvidence", "projects", "externalIds",
"pdfUrl", "landingPage"
"pdfUrl", "landingPage", "softwares",
],
query: {
bool: {
Expand Down
2 changes: 1 addition & 1 deletion client/src/api/publications/more-like-this/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export async function getMorePublicationsLikeThis(id: string) {
size: 3,
query: {
more_like_this: {
fields: ["title.default"],
fields: ["title.default", "domains.label.*"],
like: [{ _id: id }],
min_term_freq: 1,
max_query_terms: 12,
Expand Down
Loading

0 comments on commit 98de075

Please sign in to comment.