From 7944e9615c9de71928136fda0389cbc501ee3af0 Mon Sep 17 00:00:00 2001 From: Bryceson Laing Date: Fri, 8 Nov 2024 07:56:07 -0600 Subject: [PATCH] refactor repository page for RSC (#415) * refactor for RSC --- src/app/repositories/[...repoid]/Content.tsx | 4 +- src/app/repositories/[...repoid]/page.tsx | 2 +- .../HorizontalStackedBarChart.tsx | 48 +---------------- .../ProductionChart/ProductionChart.tsx | 19 +++---- .../RepositoryDetail/RepositoryDetail.tsx | 6 +-- .../VerticalBarChart/VerticalBarChart.tsx | 38 ++++++-------- .../WorksDashboard/WorksDashboard.tsx | 3 +- src/utils/helpers.ts | 52 ++++++++++++++++++- 8 files changed, 85 insertions(+), 87 deletions(-) diff --git a/src/app/repositories/[...repoid]/Content.tsx b/src/app/repositories/[...repoid]/Content.tsx index b2498ff4..0147fc94 100644 --- a/src/app/repositories/[...repoid]/Content.tsx +++ b/src/app/repositories/[...repoid]/Content.tsx @@ -1,5 +1,7 @@ import React from 'react' -import { Row, Col, Container } from 'react-bootstrap'; +import Container from 'react-bootstrap/Container' +import Row from 'react-bootstrap/Row' +import Col from 'react-bootstrap/Col' import { Repository as RepositoryType } from 'src/data/types' import { fetchRepository, QueryVar } from 'src/data/queries/repositoryQuery'; diff --git a/src/app/repositories/[...repoid]/page.tsx b/src/app/repositories/[...repoid]/page.tsx index 77d6a126..7d334a07 100644 --- a/src/app/repositories/[...repoid]/page.tsx +++ b/src/app/repositories/[...repoid]/page.tsx @@ -63,7 +63,7 @@ export async function generateMetadata({ params }: Props): Promise { export default async function Page({ params }: Props) { - const repoid = params.repoid.join('/') + const repoid = decodeURIComponent(params.repoid.join('/')) // Fetch Repository metadata const { data } = await fetchRepositoryMetadata(repoid) diff --git a/src/components/HorizontalStackedBarChart/HorizontalStackedBarChart.tsx b/src/components/HorizontalStackedBarChart/HorizontalStackedBarChart.tsx index 15e23df1..5bcff274 100644 --- a/src/components/HorizontalStackedBarChart/HorizontalStackedBarChart.tsx +++ b/src/components/HorizontalStackedBarChart/HorizontalStackedBarChart.tsx @@ -1,10 +1,11 @@ +'use client' + import React, { useEffect, useRef, useState } from 'react' import { VegaLite } from 'react-vega' import EmptyChart from 'src/components/EmptyChart/EmptyChart' import HelpIcon from 'src/components/HelpIcon/HelpIcon' import styles from './HorizontalStackedBarChart.module.scss' import stackedBarChartSpec from './HorizontalStackedBarChartSpec' -import { Facet } from 'src/data/types' type Props = { @@ -21,51 +22,6 @@ export interface HorizontalBarRecord { count: number } -export function toBarRecord(data: Facet) { - return { title: data.title, count: data.count } -} - -function getTotalCount(sum: number, data: HorizontalBarRecord) { return sum + data.count } - -export function getTopFive(data: HorizontalBarRecord[]) { - if (data.length === 0) { - return { - data: [], - topCategory: "", - topPercent: -1 - } - } - - const otherData = data.filter(d => d.title === "Other") - let otherCount = otherData.reduce(getTotalCount, 0) - - const missingData = data.filter(d => d.title === "Missing") - const missingCount = missingData.reduce(getTotalCount, 0) - - data = data.filter(d => d.title !== "Other" && d.title !== "Missing") - const sorted = data.sort((a, b) => b.count - a.count) - - const topFive = sorted.slice(0, 5) - const others = sorted.slice(5) - otherCount += others.reduce(getTotalCount, 0) - - if (otherCount > 0) - topFive.push({ title: 'Other', count: otherCount }) - - if (missingCount > 0) - topFive.push({ title: 'Missing', count: missingCount }) - - - topFive.sort((a, b) => b.count - a.count)[0] - - return { - data: topFive, - topCategory: topFive[0].title, - topPercent: Math.round(topFive[0].count / topFive.reduce(getTotalCount, 0) * 100) - } -} - - const HorizontalBarChart: React.FunctionComponent = ({ chartTitle, topCategory, diff --git a/src/components/ProductionChart/ProductionChart.tsx b/src/components/ProductionChart/ProductionChart.tsx index 8408224b..8991b989 100644 --- a/src/components/ProductionChart/ProductionChart.tsx +++ b/src/components/ProductionChart/ProductionChart.tsx @@ -1,9 +1,11 @@ +'use client' + import React from 'react' import { VegaLite } from 'react-vega' import { VisualizationSpec } from 'vega-embed' -import useWindowDimensions from '../../utils/useWindowDimensions' -import EmptyChart from '../EmptyChart/EmptyChart' +import useWindowDimensions from 'src/utils/useWindowDimensions' +import EmptyChart from 'src/components/EmptyChart/EmptyChart' interface ChartRecord { title: string @@ -24,14 +26,9 @@ const actions = { editor: false } -const ProductionChart: React.FunctionComponent = ({ - title, - data, - lowerBoundYear, - color -}) => { - if (data.length==0){ - return +export default function ProductionChart({ title, data, lowerBoundYear, color }: Props) { + if (data.length == 0) { + return } // get current screen size const windowDimensions: any = useWindowDimensions() @@ -160,5 +157,3 @@ const ProductionChart: React.FunctionComponent = ({ ) } - -export default ProductionChart diff --git a/src/components/RepositoryDetail/RepositoryDetail.tsx b/src/components/RepositoryDetail/RepositoryDetail.tsx index cee07baf..fc7f93ff 100644 --- a/src/components/RepositoryDetail/RepositoryDetail.tsx +++ b/src/components/RepositoryDetail/RepositoryDetail.tsx @@ -1,5 +1,3 @@ -'use client' - import React from 'react' import Link from 'next/link' import { Button, Badge } from 'react-bootstrap'; @@ -9,12 +7,12 @@ import { faNewspaper } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faSignInAlt } from '@fortawesome/free-solid-svg-icons' -import { compactNumbers } from 'src/utils/helpers' +import { compactNumbers, getTopFive, toBarRecord } from 'src/utils/helpers' import styles from './RepositoryDetail.module.scss' import { MetricsDisplay } from 'src/components/MetricsDisplay/MetricsDisplay'; import ShareLinks from 'src/components/ShareLinks/ShareLinks'; import { resourceTypeDomain, resourceTypeRange, licenseRange, otherDomain, otherRange } from 'src/data/color_palettes'; -import HorizontalStackedBarChart, { getTopFive, toBarRecord } from 'src/components/HorizontalStackedBarChart/HorizontalStackedBarChart'; +import HorizontalStackedBarChart from 'src/components/HorizontalStackedBarChart/HorizontalStackedBarChart'; import { Repository } from 'src/data/types'; type Props = { diff --git a/src/components/VerticalBarChart/VerticalBarChart.tsx b/src/components/VerticalBarChart/VerticalBarChart.tsx index dedb3334..a9ce331b 100644 --- a/src/components/VerticalBarChart/VerticalBarChart.tsx +++ b/src/components/VerticalBarChart/VerticalBarChart.tsx @@ -1,9 +1,11 @@ +'use client' + import React from 'react' import { VegaLite } from 'react-vega' import { VisualizationSpec } from 'vega-embed' -import useWindowDimensions from '../../utils/useWindowDimensions' -import EmptyChart from '../EmptyChart/EmptyChart' +import useWindowDimensions from 'src/utils/useWindowDimensions' +import EmptyChart from 'src/components/EmptyChart/EmptyChart' interface ChartRecord { title: string @@ -24,13 +26,9 @@ const actions = { editor: false } -const VerticalBarChart: React.FunctionComponent = ({ - title, - data, - color -}) => { - if (data.length==0){ - return +export default function VerticalBarChart({ title, data, color }: Props) { + if (data.length == 0) { + return } // get current screen size const windowDimensions: any = useWindowDimensions() @@ -60,12 +58,12 @@ const VerticalBarChart: React.FunctionComponent = ({ tooltip: true }, params: [ - { - name: "highlight", - select: {type: "point", on: "pointerover"} - }, - {name: "select", select: "point"} - ], + { + name: "highlight", + select: { type: "point", on: "pointerover" } + }, + { name: "select", select: "point" } + ], // params: { // name: "highlight", // @@ -120,10 +118,10 @@ const VerticalBarChart: React.FunctionComponent = ({ const mydata = data.map(item => { - if(item.title === "missing") { - return {...item, color: "#e74c3c"} - }else{ - return {...item, color: "#1abc9c"} + if (item.title === "missing") { + return { ...item, color: "#e74c3c" } + } else { + return { ...item, color: "#1abc9c" } } }) @@ -143,5 +141,3 @@ const VerticalBarChart: React.FunctionComponent = ({ ) } - -export default VerticalBarChart diff --git a/src/components/WorksDashboard/WorksDashboard.tsx b/src/components/WorksDashboard/WorksDashboard.tsx index 4f46f7ca..0c461448 100644 --- a/src/components/WorksDashboard/WorksDashboard.tsx +++ b/src/components/WorksDashboard/WorksDashboard.tsx @@ -5,9 +5,10 @@ import { Row, Col } from 'react-bootstrap' import clone from 'lodash/clone' import { Works } from 'src/data/types' import ProductionChart from '../ProductionChart/ProductionChart' -import HorizontalStackedBarChart, { getTopFive, toBarRecord } from '../HorizontalStackedBarChart/HorizontalStackedBarChart' +import HorizontalStackedBarChart from '../HorizontalStackedBarChart/HorizontalStackedBarChart' import { resourceTypeDomain, resourceTypeRange, licenseRange, otherDomain, otherRange } from '../../data/color_palettes' import styles from './WorksDashboard.module.scss' +import { getTopFive, toBarRecord } from 'src/utils/helpers' type Props = PropsWithChildren<{ works: Works diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index e83e029e..a9e3368f 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -1,6 +1,7 @@ import '@formatjs/intl-numberformat/polyfill' import '@formatjs/intl-numberformat/locale-data/en' -import { WorkMetadata } from 'src/data/types' +import type { Facet, WorkMetadata } from 'src/data/types' +import type { HorizontalBarRecord } from 'src/components/HorizontalStackedBarChart/HorizontalStackedBarChart' export const compactNumbers = (num: number, compact: boolean = false) => { let options = {} @@ -58,3 +59,52 @@ export function isAwardGrant(work: WorkMetadata) { work.types.resourceTypeGeneral === 'Text') ) } + + +function getTotalCount(sum: number, data: HorizontalBarRecord) { return sum + data.count } + +export function getTopFive(data: HorizontalBarRecord[]) { + if (data.length === 0) { + return { + data: [], + topCategory: "", + topPercent: -1 + } + } + + const otherData = data.filter(d => d.title === "Other") + let otherCount = otherData.reduce(getTotalCount, 0) + + const missingData = data.filter(d => d.title === "Missing") + const missingCount = missingData.reduce(getTotalCount, 0) + + data = data.filter(d => d.title !== "Other" && d.title !== "Missing") + const sorted = data.sort((a, b) => b.count - a.count) + + const topFive = sorted.slice(0, 5) + const others = sorted.slice(5) + otherCount += others.reduce(getTotalCount, 0) + + if (otherCount > 0) + topFive.push({ title: 'Other', count: otherCount }) + + if (missingCount > 0) + topFive.push({ title: 'Missing', count: missingCount }) + + + topFive.sort((a, b) => b.count - a.count)[0] + + return { + data: topFive, + topCategory: topFive[0].title, + topPercent: Math.round(topFive[0].count / topFive.reduce(getTotalCount, 0) * 100) + } +} + +export function toBarRecord(data: Facet) { + return { title: data.title, count: data.count } +} + + + +