Skip to content

Commit

Permalink
feat(client): rework
Browse files Browse the repository at this point in the history
  • Loading branch information
ahonestla committed Sep 9, 2024
1 parent 7c88ff1 commit 0c40b9d
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 150 deletions.
37 changes: 37 additions & 0 deletions project/client/src/components/results/debug/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Container, Badge, BadgeGroup, Accordion } from "@dataesr/dsfr-plus"
import { MatchDebug } from "../../../types"

type ResultsDebugArgs = {
resultsDebug: MatchDebug
}
export default function ResultsDebug({ resultsDebug }: ResultsDebugArgs) {
console.log("resultsDebug", resultsDebug)

if (!resultsDebug) return null

const criterionMatches = (criterion: string) => resultsDebug.criterion?.[criterion] ?? 0

return (
<Accordion className="fr-container fr-mt-3w" title="See more">
{resultsDebug.strategies.map((strategy, index) => (
<Container key={index} className="debug-item">
{strategy.equivalent_strategies.map((equivalent) => (
<BadgeGroup>
{equivalent.map((criterion) => {
const matches: number = criterionMatches(criterion)
return (
<Badge color={matches ? "yellow-moutarde" : null}>{`${criterion}: ${matches} match${
matches == 1 ? "" : "es"
}`}</Badge>
)
})}
</BadgeGroup>
))}
<Badge color={strategy.matches ? "success" : "error"}>{`${strategy.matches} ${
strategy.matches == 1 ? "possibility" : "possibilities"
}`}</Badge>
</Container>
))}
</Accordion>
)
}
81 changes: 28 additions & 53 deletions project/client/src/components/results/highlights/index.tsx
Original file line number Diff line number Diff line change
@@ -1,65 +1,40 @@
import { IntlMessageFormat } from "intl-messageformat"
import { Container, Badge, Text, Row } from "@dataesr/dsfr-plus"
import { CriterionHighlightsArgs, ResultHighlightsArgs, StrategyHighlightsArgs } from "../../../types/functions"
import { getHighlightedText, getHighlightedQuery, strategyCriteria } from "../utils/highlights"
import { Container, Badge, BadgeGroup } from "@dataesr/dsfr-plus"
import { getHighlightedQuery } from "../utils/highlights"
import useUrl from "../../../hooks/useUrl"
import { MatchHighlight } from "../../../types"

function CriterionHighlights({ criterion, criterionHighlights, setTitle }: CriterionHighlightsArgs) {
const { currentQuery } = useUrl()
export type ResultHighlightsArgs = {
resultHighlights: MatchHighlight
setTitle: Function
}

const highlightedData = criterionHighlights.map((criterionHighlight) => {
const highlightedText = getHighlightedText(criterionHighlight[0])
return {
highlightedCriterion: highlightedText.join(" "),
highlightedQuery: getHighlightedQuery(highlightedText, currentQuery),
}
})
export default function ResultHighlights({ resultHighlights, setTitle }: ResultHighlightsArgs) {
const { currentQuery } = useUrl()

const onEnter = (highlightedQuery: string) =>
setTitle(new IntlMessageFormat(highlightedQuery).format({ b: (chunks) => <strong>{chunks}</strong> }))
setTitle(
new IntlMessageFormat(highlightedQuery).format({
b: (chunks) => <strong key={JSON.stringify(chunks)}>{chunks}</strong>,
})
)
const onLeave = () => setTitle(currentQuery)

return (
<Row>
<Text>{`${criterion} (${highlightedData.length} match${highlightedData.length > 1 ? "es" : ""}):`}</Text>
{highlightedData.map((data, index) => (
<Text
key={index}
className="fr-ml-1w fr-mr-1w"
onMouseEnter={() => onEnter(data.highlightedQuery)}
onMouseLeave={() => onLeave()}
>
<strong>{data.highlightedCriterion}</strong>
</Text>
))}
</Row>
)
}

function StrategyHighlights({ strategy, strategyHighlights, setTitle }: StrategyHighlightsArgs) {
const criteria = strategyCriteria(strategy)
const color = criteria.length === Object.keys(strategyHighlights).length ? "success" : "error"

return (
<Container>
<Badge color={color}>{`Strategy: ${criteria.join(", ")}`}</Badge>
{Object.entries(strategyHighlights).map(([criterion, criterionHighlights], index) => (
<CriterionHighlights
key={index}
criterion={criterion}
criterionHighlights={criterionHighlights}
setTitle={setTitle}
/>
))}
</Container>
)
}

export default function ResultHighlights({ resultHighlights, setTitle }: ResultHighlightsArgs) {
return (
<Container fluid className="fr-mt-4w">
{Object.entries(resultHighlights).map(([strategy, criteriaHighlights], index) => (
<StrategyHighlights key={index} strategy={strategy} strategyHighlights={criteriaHighlights} setTitle={setTitle} />
<Container fluid className="fr-mt-2w">
{Object.entries(resultHighlights.criterion).map(([criterion, highlights], groupIndex) => (
<BadgeGroup key={groupIndex}>
<Badge color="success">{criterion}</Badge>
{highlights.map((highlight, badgeIndex) => (
<Badge
key={badgeIndex}
onMouseEnter={() => onEnter(getHighlightedQuery(highlight, currentQuery))}
onMouseLeave={() => onLeave()}
>
{highlight?.join(" ")}
</Badge>
))}
</BadgeGroup>
))}
</Container>
)
Expand Down
21 changes: 15 additions & 6 deletions project/client/src/components/results/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import useUrl from "../../hooks/useUrl"
import Error from "../error"
import Result from "./result"
import Fetching from "../fetching"
import { MatchIds } from "../../types/data"
import { MatchIds } from "../../types"
import ResultsDebug from "./debug"

export default function Results() {
const { currentQuery, currentMatcher, currentYear } = useUrl()
Expand All @@ -27,22 +28,30 @@ export default function Results() {
const matchIds = data.results as MatchIds
if (!matchIds.length)
return (
<Container>
<Text size="lead">{currentTitle}</Text>
<Badge color="error">{`${currentMatcher} : no results`}</Badge>
</Container>
<>
<Container className="sticky card">
<Text size="lead">{currentTitle}</Text>
</Container>
<Container className="fr-mt-3w">
<Badge color="error">{`${currentMatcher} : 0 match`}</Badge>
</Container>
</>
)

return (
<Container fluid>
<Container className="sticky card">
<Text size="lead">{currentTitle}</Text>
</Container>
<Container fluid className="fr-mt-5w">
<Container className="fr-mt-3w">
<Text size="md">{`${matchIds.length} match${matchIds.length > 1 ? "es" : ""}`}</Text>
</Container>
<Container fluid className="fr-mt-3w">
{matchIds.map((id, index) => {
return <Result key={index} resultData={data} resultId={id} setTitle={setTitle} />
})}
</Container>
<ResultsDebug resultsDebug={data?.debug} />
</Container>
)
}
11 changes: 4 additions & 7 deletions project/client/src/components/results/result/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Container, Badge, Row, BadgeGroup, Accordion } from "@dataesr/dsfr-plus"
import { MatchId, MatchResults } from "../../../types/data"
import { Container, Badge, Row, BadgeGroup } from "@dataesr/dsfr-plus"
import { MatchId, MatchResults } from "../../../types"
import useUrl from "../../../hooks/useUrl"
import { getResultHighlights } from "../utils/highlights"
import { getResultUrl } from "../utils/url"
import ResultHighlights from "../highlights"

Expand All @@ -19,7 +18,7 @@ export default function Result({
const { results: resultsIds, enriched_results: resultsEnriched, highlights: resultsHighlights } = resultData
const resultIndex = resultsIds.findIndex((element) => element === resultId)
const resultEnriched = resultsEnriched[resultIndex]
const resultHighlights = getResultHighlights(resultsHighlights, resultId)
const resultHighlights = resultsHighlights?.[resultId]
const resultUrl = getResultUrl(resultId, currentMatcher)

return (
Expand All @@ -42,9 +41,7 @@ export default function Result({
{resultEnriched?.country?.length && <Badge color="pink-macaron">{resultEnriched.country[0]}</Badge>}
</BadgeGroup>
</Row>
<Accordion title="Highlights">
<ResultHighlights resultHighlights={resultHighlights} setTitle={setTitle} />
</Accordion>
<ResultHighlights resultHighlights={resultHighlights} setTitle={setTitle} />
</Container>
)
}
38 changes: 1 addition & 37 deletions project/client/src/components/results/utils/highlights.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,4 @@
import { MatchHighlights, MatchId, ResultHighlights, TextHighlight } from "../../../types/data"

export const getResultHighlights = (resultsHighlights: MatchHighlights, id: MatchId) =>
Object.entries(resultsHighlights).reduce((acc: ResultHighlights, [strategy, strategyHighlights]) => {
Object.entries(strategyHighlights[id]).forEach(([criterion, criterionHiglights]) => {
if (strategy in acc) acc[strategy][criterion] = criterionHiglights
else acc[strategy] = { [criterion]: criterionHiglights }
})
return acc
}, {})

export const strategyCriteria = (strategy: string) => strategy.split(";")

const stringFindText = (str: string, text: string): Array<number> =>
[...str.matchAll(new RegExp(text, "gi"))].map((match) => match.index)

export const getHighlightedText = (highlight: string): TextHighlight => {
const startTag = "<em>"
const endTag = "</em>"
const startTags = stringFindText(highlight, startTag)
const endTags = stringFindText(highlight, endTag)

let highlightedArray = []
let cursor = 0

for (let i = 0; i < startTags.length; i++) {
const startIndex = startTags[i]
const endIndex = endTags[i]

const highlighted = highlight.slice(startIndex + startTag.length, endIndex)
highlightedArray.push(highlighted)

cursor = endIndex + endTag.length
}

return highlightedArray
}
import { TextHighlight } from "../../../types"

export function getHighlightedQuery(highlightedArray: TextHighlight, query: string) {
let highlightedQuery = query
Expand Down
2 changes: 1 addition & 1 deletion project/client/src/components/results/utils/url.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MatchId } from "../../../types/data"
import { MatchId } from "../../../types"

export function getResultUrl(resultId: MatchId, currentMatcher: string) {
if (currentMatcher === "ror") return `https://ror.org/${resultId}`
Expand Down
9 changes: 9 additions & 0 deletions project/client/src/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,12 @@
padding-top: 15px;
padding-bottom: 1px;
}

.debug-item {
padding-bottom: 1rem !important
}

.debug-item:not(:first-child) {
border-top: 1px solid var(--border-default-grey);
padding-top: 1rem !important;
}
30 changes: 0 additions & 30 deletions project/client/src/types/data.ts

This file was deleted.

16 changes: 0 additions & 16 deletions project/client/src/types/functions.ts

This file was deleted.

43 changes: 43 additions & 0 deletions project/client/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export type MatchId = string
export type MatchIds = Array<MatchId>

export type MatchEnrichedResult = {
id: MatchId
name: Array<string>
acronym?: Array<string>
city?: Array<string>
country?: Array<string>
}
export type MatchEnrichedResults = Array<MatchEnrichedResult>

export type CriteriaHighlight = Array<Array<string>>
export type CriterionHighlight = Record<string, CriteriaHighlight>
export type StrategyHighlight = Array<string>
export type StrategiesHighlight = Array<StrategyHighlight>
export type MatchHighlight = {
criterion: CriterionHighlight
strategies: StrategiesHighlight
}
export type MatchHighlights = Record<MatchId, MatchHighlight>

export type CriterionDebug = Record<string, number>
export type StrategiesDebug = {
equivalent_strategies: Array<Array<string>>
matches: number
}
export type MatchDebug = {
criterion: CriterionDebug
strategies: Array<StrategiesDebug>
}

export type MatchResults = {
version: string
index_date: string
results: MatchIds
other_ids: MatchIds
enriched_results: MatchEnrichedResults
highlights?: MatchHighlights
debug?: MatchDebug
}

export type TextHighlight = Array<any>

0 comments on commit 0c40b9d

Please sign in to comment.