From 25c81172fbbb55dd2956d19f8cda1f774522494d Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Thu, 12 Feb 2026 11:02:26 -0500 Subject: [PATCH 1/4] feat: add customization on homepage and footer --- CHANGELOG.md | 1 + cypress.config.ts | 10 ++++ public/config.js | 14 +++++- public/locales/en/footer.json | 2 +- public/locales/en/homepage.json | 4 +- public/locales/es/footer.json | 2 +- public/locales/es/homepage.json | 4 +- src/config.ts | 18 ++++++- src/sections/homepage/usage/Usage.tsx | 49 ++++++++++--------- src/sections/layout/footer/Footer.tsx | 20 +++++--- .../sections/layout/footer/Footer.spec.tsx | 23 ++++++++- tests/support/bootstrapAppConfig.ts | 16 +++++- 12 files changed, 123 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f90edbeb..054458cde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel - Edit Terms Integration. - With the addition of the new runtime configuration approach, we now support dynamic configuration for languages. If more than one language is configured, the Language Switcher will be shown in the header to allow users to change the language. - Added Notifications tab in Account Page +- Added runtime configuration options for homepage branding and support link. ### Changed diff --git a/cypress.config.ts b/cypress.config.ts index f5efec081..b9f6c55e6 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -46,6 +46,16 @@ export default defineConfig({ { code: 'es', name: 'Español' } ], defaultLanguage: 'en', + branding: { + dataverseName: 'Dataverse' + }, + homepage: { + supportUrl: 'https://support.dataverse.harvard.edu/' + }, + footer: { + copyrightHolder: 'The President & Fellows of Harvard College', + privacyPolicyUrl: 'https://support.dataverse.harvard.edu/harvard-dataverse-privacy-policy' + }, codeCoverage: { exclude: ['tests/**/*.*', '**/ErrorPage.tsx'] } diff --git a/public/config.js b/public/config.js index fc815f483..bd63f3f93 100644 --- a/public/config.js +++ b/public/config.js @@ -20,5 +20,17 @@ window.__APP_CONFIG__ = { { code: 'es', name: 'Español' } ], // Default language code from the list above - defaultLanguage: 'en' + defaultLanguage: 'en', + // Optional branding values for homepage/footer text + branding: { + // Used in homepage strings such as "{{dataverseName}} is a repository..." + dataverseName: 'Harvard Dataverse' + }, + homepage: { + supportUrl: 'https://support.dataverse.harvard.edu/' + }, + footer: { + copyrightHolder: 'The President & Fellows of Harvard College', + privacyPolicyUrl: 'https://support.dataverse.harvard.edu/harvard-dataverse-privacy-policy' + } } diff --git a/public/locales/en/footer.json b/public/locales/en/footer.json index 4532c74f3..cdf13602d 100644 --- a/public/locales/en/footer.json +++ b/public/locales/en/footer.json @@ -1,5 +1,5 @@ { - "copyright": "Copyright © {{year}}, The President & Fellows of Harvard College | ", + "copyright": "Copyright © {{year}}, {{copyrightHolder}}", "privacyPolicy": "Privacy Policy", "poweredBy": "Powered by" } diff --git a/public/locales/en/homepage.json b/public/locales/en/homepage.json index fe846e929..78f74ab25 100644 --- a/public/locales/en/homepage.json +++ b/public/locales/en/homepage.json @@ -20,7 +20,7 @@ "usage": { "datasets": { "title": "Deposit and share your data. Get academic credit.", - "content": "Harvard Dataverse is a repository for research data. Deposit data and code here.", + "content": "{{dataverseName}} is a repository for research data. Deposit data and code here.", "text_button": "Add a dataset" }, "collections": { @@ -29,7 +29,7 @@ "text_button": "Add a collection" }, "general": { - "title": "Publishing your data is easy on Harvard Dataverse!", + "title": "Publishing your data is easy on {{dataverseName}}!", "content": "Learn about getting started creating your own dataverse repository here.", "text_button": "Getting started" } diff --git a/public/locales/es/footer.json b/public/locales/es/footer.json index 062908bb9..ac3cb7e89 100644 --- a/public/locales/es/footer.json +++ b/public/locales/es/footer.json @@ -1,5 +1,5 @@ { - "copyright": "Copyright © {{year}}, El Presidente y Miembros de la Universidad de Harvard | ", + "copyright": "Copyright © {{year}}, {{copyrightHolder}}", "privacyPolicy": "Política de privacidad", "poweredBy": "Desarrollado por" } diff --git a/public/locales/es/homepage.json b/public/locales/es/homepage.json index 3a4e28f96..97dd4f80f 100644 --- a/public/locales/es/homepage.json +++ b/public/locales/es/homepage.json @@ -20,7 +20,7 @@ "usage": { "datasets": { "title": "Deposita y comparte tus datos. Obtén crédito académico.", - "content": "Harvard Dataverse es un repositorio para datos de investigación. Deposita aquí tus datos y código.", + "content": "{{dataverseName}} es un repositorio para datos de investigación. Deposita aquí tus datos y código.", "text_button": "Agregar un dataset" }, "collections": { @@ -29,7 +29,7 @@ "text_button": "Agregar una colección" }, "general": { - "title": "¡Publicar tus datos es fácil en Harvard Dataverse!", + "title": "¡Publicar tus datos es fácil en {{dataverseName}}!", "content": "Aprende cómo comenzar a crear tu propio repositorio Dataverse aquí.", "text_button": "Comenzar" } diff --git a/src/config.ts b/src/config.ts index a6989ab2c..2f6d423f2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -23,7 +23,23 @@ const AppConfigSchema = z.object({ code: z.string(), name: z.string() }) - ) + ), + branding: z + .object({ + dataverseName: z.string().optional() + }) + .optional(), + homepage: z + .object({ + supportUrl: z.url().optional() + }) + .optional(), + footer: z + .object({ + copyrightHolder: z.string().optional(), + privacyPolicyUrl: z.url().optional() + }) + .optional() }) export type AppConfig = z.infer diff --git a/src/sections/homepage/usage/Usage.tsx b/src/sections/homepage/usage/Usage.tsx index f390560ec..3ebe25d78 100644 --- a/src/sections/homepage/usage/Usage.tsx +++ b/src/sections/homepage/usage/Usage.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next' import { Card, Col, Row, Stack } from '@iqss/dataverse-design-system' import { BoxArrowUpRight, Plus } from 'react-bootstrap-icons' import { RouteWithParams } from '@/sections/Route.enum' +import { requireAppConfig } from '@/config' import styles from './Usage.module.scss' interface UsageProps { @@ -11,6 +12,9 @@ interface UsageProps { export const Usage = ({ collectionId }: UsageProps) => { const { t } = useTranslation('homepage', { keyPrefix: 'usage' }) + const appConfig = requireAppConfig() + const dataverseName = appConfig.branding?.dataverseName ?? 'Dataverse' + const supportUrl = appConfig.homepage?.supportUrl return ( @@ -18,7 +22,7 @@ export const Usage = ({ collectionId }: UsageProps) => {
{t('datasets.title')}
-

{t('datasets.content')}

+

{t('datasets.content', { dataverseName })}