From 3f41b02174a93f2efe6f915ae25ae21863b9ed0d Mon Sep 17 00:00:00 2001 From: kccrtv Date: Tue, 7 Jan 2025 19:21:36 -0600 Subject: [PATCH 1/5] remove taviraj, update hero text size, update TOU content, rm unused news components --- .../internal_routes.ci.spec.ts | 16 +- frontend/src/pages/Landing/LandingPage.tsx | 4 +- .../methodologySections/AgeAdjustmentLink.tsx | 2 +- frontend/src/pages/News/AllPosts.tsx | 141 +++------- frontend/src/pages/News/ArticleFilters.tsx | 49 ---- frontend/src/pages/News/PinnedArticles.tsx | 31 --- .../pages/TermsOfUsePage/TermsOfUsePage.tsx | 248 +++++++----------- frontend/src/pages/ui/SignupSection.tsx | 30 --- frontend/tailwind.config.ts | 1 + 9 files changed, 156 insertions(+), 366 deletions(-) delete mode 100644 frontend/src/pages/News/ArticleFilters.tsx delete mode 100644 frontend/src/pages/News/PinnedArticles.tsx delete mode 100644 frontend/src/pages/ui/SignupSection.tsx diff --git a/frontend/playwright-tests/internal_routes.ci.spec.ts b/frontend/playwright-tests/internal_routes.ci.spec.ts index 48c10b1667..f544e0c469 100644 --- a/frontend/playwright-tests/internal_routes.ci.spec.ts +++ b/frontend/playwright-tests/internal_routes.ci.spec.ts @@ -46,11 +46,21 @@ test('About Us Page Loads', async ({ page }) => { expect(accessibilityScanResults.violations).toEqual([]) }) -test('Terms of Use Page Loads', async ({ page }) => { +test('Terms of Use Page Loads and Renders Correctly', async ({ page }) => { await page.goto('/termsofuse', { waitUntil: 'commit' }) - const mainSection = page.locator('main#main') - const mainHeading = mainSection.locator('h2#main') + const mainSection = page.locator('section#main-content') + await expect(mainSection).toBeVisible() + const mainHeading = mainSection.locator('h1#main') await expect(mainHeading).toHaveText('Terms of Use') + const termsList = mainSection.locator('ul') + await expect(termsList).toBeVisible() + const firstTerm = termsList.locator('li#tou-0') + const firstTermHeading = firstTerm.locator('h3') + await expect(firstTermHeading).toHaveText('Privacy Policy') + const firstTermParagraph = firstTerm.locator('p') + await expect(firstTermParagraph).toContainText( + 'The Health Equity Tracker (HET)', + ) const accessibilityScanResults = await new AxeBuilder({ page }).analyze() expect(accessibilityScanResults.violations).toEqual([]) }) diff --git a/frontend/src/pages/Landing/LandingPage.tsx b/frontend/src/pages/Landing/LandingPage.tsx index 6268ca44ad..51bea1d99e 100644 --- a/frontend/src/pages/Landing/LandingPage.tsx +++ b/frontend/src/pages/Landing/LandingPage.tsx @@ -116,8 +116,8 @@ function LandingPage() { alt='various charts from the health equity tracker' className='absolute top-0 right-0 bottom-0 z-0 float-right mx-24 max-w-4xl opacity-35 xs:opacity-15 sm:opacity-15 md:opacity-15' > -
-

+
+

Where will the
Health Equity Tracker
take you? diff --git a/frontend/src/pages/Methodology/methodologySections/AgeAdjustmentLink.tsx b/frontend/src/pages/Methodology/methodologySections/AgeAdjustmentLink.tsx index e2b0453835..6b31d6e4d3 100644 --- a/frontend/src/pages/Methodology/methodologySections/AgeAdjustmentLink.tsx +++ b/frontend/src/pages/Methodology/methodologySections/AgeAdjustmentLink.tsx @@ -280,7 +280,7 @@ const AgeAdjustmentLink = () => {

Age-Adjustment Example: HIV Deaths

diff --git a/frontend/src/pages/News/AllPosts.tsx b/frontend/src/pages/News/AllPosts.tsx index 209089505c..dba6f55c40 100644 --- a/frontend/src/pages/News/AllPosts.tsx +++ b/frontend/src/pages/News/AllPosts.tsx @@ -1,24 +1,15 @@ import { useEffect, useState } from 'react' import { Helmet } from 'react-helmet-async' import { useQuery } from 'react-query' -import { Link } from 'react-router-dom' import HetPostsLoading from '../../styles/HetComponents/HetPostsLoading' import { ARTICLES_KEY, REACT_QUERY_OPTIONS, fetchNewsData, } from '../../utils/blogUtils' -import { - NEWS_PAGE_LINK, - SHARE_YOUR_STORY_TAB_LINK, -} from '../../utils/internalRoutes' -import { LinkWithStickyParams, useUrlSearchParams } from '../../utils/urlutils' -import SignupSection from '../ui/SignupSection' -import ArticleFilters from './ArticleFilters' +import { useUrlSearchParams } from '../../utils/urlutils' import type { Article } from './ArticleTypes' import NewsAndStoriesPreviewCardOutlined from './NewsAndStoriesPreviewCardOutlined' -import NewsPreviewCard from './NewsPreviewCard' -import PinnedArticles from './PinnedArticles' export const ARTICLES_TERM = 'Articles' @@ -123,108 +114,60 @@ function AllPosts() { setCategories(Array.from(allCategoriesSet) as string[]) }, [data?.data]) - - // featured "sticky" articles - const pinnedArticles = data?.data?.filter((post: Article) => post?.sticky) - return (
News - Health Equity Tracker -
-
- - -
-
-
-
- {/* show featured card with "sticky" articles marked PIN TO TOP if any */} - {selectedAuthor?.length === 0 && - selectedCategory?.length === 0 && ( - - )} - - {/* if there is a filter in place, show breadcrumbs type menu */} - {(selectedAuthor || selectedCategory) && ( - <> - - {ARTICLES_TERM} - - - › - - - )} - - {selectedAuthor?.length > 0 && `Author: ${selectedAuthor}`} - {selectedCategory?.length > 0 && - `Category: ${selectedCategory}`} - -
- - {/* all posts matching client applied filters */} -
- {filteredArticles?.slice(5, -1).map((post: any) => { - return ( -
-
- -
-
- ) - })} -
- -
- {isLoading && ( - <> - -
- Updating articles... -
- - )} - {error && !isLoading && ( -
-
- Problem updating articles. +
+
+
+ + {selectedAuthor?.length > 0 && `Author: ${selectedAuthor}`} + {selectedCategory?.length > 0 && `Category: ${selectedCategory}`} + +
+ + {/* all posts matching client applied filters */} +
+ {filteredArticles?.slice(5, -1).map((post: any) => { + return ( +
+
+
-
- )} -
+ ) + })}
-
-
-
-
-
-
- -
-
- +
+ {isLoading && ( + <> + +
+ Updating articles... +
+ + )} + {error && !isLoading && ( +
+
+ Problem updating articles. +
+ +
+ )}
- -
) } diff --git a/frontend/src/pages/News/ArticleFilters.tsx b/frontend/src/pages/News/ArticleFilters.tsx deleted file mode 100644 index bc36facc8a..0000000000 --- a/frontend/src/pages/News/ArticleFilters.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Link } from 'react-router-dom' -import { NEWS_PAGE_LINK } from '../../utils/internalRoutes' - -type FilterType = 'author' | 'category' - -// pretty string for filter box heading -const filterHeaderMap: Record = { - author: 'Authors', - category: 'Categories', -} - -interface ArticleFiltersProps { - filterType: FilterType - filterOptions: string[] -} - -export default function ArticleFilters(props: ArticleFiltersProps) { - return ( -
- {/* FILTER BOX HEADING */} -

- {filterHeaderMap[props.filterType]} -

- - {/* LIST OF LINKED FILTERS (IF ANY) */} -
    - {props.filterOptions.length > 0 && - props.filterOptions.map((filter) => { - return ( -
  • - - {filter} - -
  • - ) - })} - {/* ALWAYS DISPLAY ALL POSTS LINK */} -
  • - - All Posts - -
  • -
-
- ) -} diff --git a/frontend/src/pages/News/PinnedArticles.tsx b/frontend/src/pages/News/PinnedArticles.tsx deleted file mode 100644 index 7ad05eeebc..0000000000 --- a/frontend/src/pages/News/PinnedArticles.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import type { Article } from './ArticleTypes' -import NewsPreviewCard from './NewsPreviewCard' - -export const ARTICLES_TERM = 'Articles' - -interface PinnedArticlesProps { - articles: Article[] -} - -export default function PinnedArticles(props: PinnedArticlesProps) { - const { articles } = props - - return articles?.length > 0 ? ( -
-
- Featured: -
-
- {articles.map((post: any) => { - return ( -
- -
- ) - })} -
-
- ) : ( - <> - ) -} diff --git a/frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx b/frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx index 1ae0c33e3f..ddb869002b 100644 --- a/frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx +++ b/frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx @@ -1,163 +1,109 @@ import { Helmet } from 'react-helmet-async' -function TermsOfUsePage() { +interface TermsContent { + title: string + paragraphs: React.ReactNode | string +} + +const termsOfUseContent: TermsContent[] = [ + { + title: 'Privacy Policy', + paragraphs: [ + `The Health Equity Tracker (HET), a project of the Satcher Health Leadership Institute (SHLI) at Morehouse School of Medicine (MSM), is committed to protecting your online privacy. The only information HET obtains about individual visitors to this web application is information supplied voluntarily by visitors. This policy outlines HET's practices regarding the collection and use of your personal information during your visit to our web application.`, + ], + }, + { + title: 'Personally Provided Information', + paragraphs: [ + `In general, you can visit the Health Equity Tracker without revealing any personal information. If you choose to provide us with personal information by sending an email or submitting a news article for us to review and potentially publish, we use that information to respond to your message and help provide you with requested information or material. HET does not give, share, sell, or transfer any personal information to third parties unless required by law.`, + ], + }, + { + title: 'Email and Phone Communications', + paragraphs: [ + `Email communications sent to us via contact forms on our site or through phone calls may be shared with a customer service representative, employee, HET partner, or subject matter expert best qualified to address your inquiry. We make every effort to respond in a timely fashion once communications are received.`, + ], + }, + { + title: 'Collection of Technical Information', + paragraphs: [ + `The Health Equity Tracker uses IP addresses (the Internet address of your computer) to help diagnose problems with our servers and administer our site. We run statistical software to identify heavily used parts of our site and analyze our audience composition. However, we do not link IP addresses to anything personally identifiable.`, + `Like many other web applications, the Health Equity Tracker uses cookies. This is typically done to recognize you and your access privileges on the site. These cookies are stored on your computer, never contain personal data, and cannot be accessed remotely by anybody other than certain HET staffers.`, + `While aggregate statistical reports may be generated based on site usage, no personally identifiable information will ever be disseminated to any unaffiliated third party.`, + ], + }, + { + title: 'Security', + paragraphs: [ + `While no computing environment can be 100% secure, HET is committed to maintaining as secure a technical environment as feasible given current technological capabilities. As a SHLI project within MSM, HET complies with all state and federal statutes requiring additional safeguards for certain types of information, including personally identifiable information and protected health information.`, + ], + }, + { + title: 'Links to Other Sites', + paragraphs: [ + `Please note that some pages within the Health Equity Tracker may contain links to external websites not managed by HET, SHLI, or MSM. These links are provided for user convenience. HET does not review, control, or take responsibility for the content of these websites. Once you visit a link to another site, you are subject to the privacy policy of that new website.`, + ], + }, + { + title: 'Changes to our Privacy Policy', + paragraphs: [ + `We may change the terms and conditions of our Privacy Policy at any time by posting revisions on the Health Equity Tracker website. By accessing or using the HET website, you agree to be bound by all the terms and conditions of our Privacy Policy as posted at the time of your access or use. If you do not agree to the terms of this Privacy Policy or any revised statement, please exit the site immediately.`, + ], + }, + { + title: 'Complaint Process', + paragraphs: ( + <> + If you have a complaint or problem with the Health Equity Tracker + website, or if you believe your privacy rights have been violated, + please email us at{' '} + + info@healthequitytracker.org + + . Please indicate the reason for contacting us. The core HET team will + review your complaint for response or resolution. + + ), + }, + { + title: 'Disclaimer', + paragraphs: [ + `No data protection method or combination of methods can be guaranteed as completely secure. The Health Equity Tracker is not responsible for and will not be held liable for disclosures of your personal information due to transmission errors or unauthorized acts of third parties. HET does not guarantee the privacy of confidential information transmitted to its website should you choose not to use the appropriate secure online forms provided. By using this website, you agree to the terms and conditions outlined in this Terms of Use statement.`, + ], + }, +] + +export default function TermsOfUsePage() { return ( <> Terms of Use - Health Equity Tracker -
-
-

- Terms of Use -

-
-
    -
  • -

    - Privacy Policy -

    -

    - Morehouse School of Medicine’s (MSM) Health Equity Tracker (HET) - is committed to protecting your online privacy. The only - information MSM’s HET obtains about individual visitors to this - web site is information supplied voluntarily by the visitor. This - policy outlines the practices of MSM regarding the collection and - use of your personal information from your visit to our web site. -

    -
  • -
  • -

    - Personally Provided Information -

    -

    - In general, you can visit official MSM web sites, such as the - Health Equity Tracker, without revealing any personal information. - If you choose to provide us with any personal information by - sending an email or by filling out a form with your personal - information and submitting it through a MSM web site, we use that - information to respond to your message and to help us provide you - with information or material that you request. We do not give, - share, sell or transfer any personal information to a third party - unless required by law. -

    -
  • -
  • -

    - Email and Phone Communications -

    -

    - Email communication that you send to us via contact forms on our - sites or through phone calls may be shared with a customer service - representative, employee, HET partners or medical expert that is - most able to address your inquiry. We make every effort to respond - in a timely fashion once communications are received. -

    -
  • -
  • -

    - Collection of Technical Information -

    -

    - MSM and the HET use IP addresses (the Internet address of your - computer) to help diagnose problems with our servers and to - administer our site. For instance, we run statistical software to - identify those parts of our site that are more heavily used and - which portion of our audience comes from within the MSM network. - But, we do not link IP addresses to anything personally - identifiable. -

    -

    - Like many other web sites, portions of MSM’s HET web site might - use cookies. This is typically done to recognize you and your - access privileges on the MSM web site. For instance, using cookies - prevents the user from needing to constantly reenter a password on - every site of MSM. These cookies get stored on your computer and - never contain personal data and cannot be accessed remotely by - anybody other than MSM. -

    -

    - While aggregate statistical reports may be generated based on site - usage, no personally identifiable information will ever be - disseminated to any unaffiliated third party. -

    -
  • -
  • -

    Security

    -

    - While no computing environment can be 100% secure, it is MSM’s - goal to maintain as secure a technical environment as feasible - given the current state of capabilities and technologies. MSM will - comply with all state and federal statutes requiring additional - safeguards for certain types of information, such as students’ - personally identifiable information and patients’ protected health - information. -

    -
  • -
  • -

    - Links to Other Sites -

    -

    - Please note that some pages within MSM web site, for the - convenience of users, are linked to web sites not managed by the - institution or HET. MSM does not review, control or take - responsibility for the content of these web sites. Once you link - to another site, you are subject to the privacy policy of the new - web site. -

    -
  • -
  • -

    - Changes to our Privacy Policy -

    -

    - We may change the terms and conditions of our Privacy Policy at - any time by posting revisions on the MSM and HET web site. By - accessing or using the MSM and HET web site, you agree to be bound - by all the terms and conditions of our Privacy Policy as posted on - the MSM and HET web site at the time of your access or use. If you - do not agree to the terms of this Privacy Policy or any revised - statement, please exit the site immediately. -

    -
  • -
  • -

    - Complaint Process -

    -

    - If you have a complaint or problem with the HET website, or if you - believe your privacy rights have been violated from the HET - website, you may email us at HET@msm.edu. Please indicate the - reason for contacting us. The HET Communications and Dissemination - Core will review your complaint for response or resolution. -

    -
  • -
  • -

    - Disclaimer -

    -

    - No data protection method or combination of methods can be - guaranteed as completely secure. MSM nor HET are responsible for - and will not be held liable for disclosures of your personal - information due to errors in transmissions or unauthorized acts of - third parties. MSM nor HET guarantee the privacy of your - confidential information transmitted to its web site should you - choose not to use the appropriate secure on-line forms provided in - the relevant pages of the web site. By using this web site you - agree to the terms and conditions outlined in this Privacy Policy - statement. -

    -
  • +
    +

    + Terms of Use +

    +

    Terms of Use

    +
      + {termsOfUseContent.map((tou, index) => ( +
    • +

      + {tou.title} +

      +

      + {tou.paragraphs} +

      +
    • + ))}
    -
    ) } - -export default TermsOfUsePage diff --git a/frontend/src/pages/ui/SignupSection.tsx b/frontend/src/pages/ui/SignupSection.tsx deleted file mode 100644 index 37d706978d..0000000000 --- a/frontend/src/pages/ui/SignupSection.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { - ABOUT_US_PAGE_LINK, - SHARE_YOUR_STORY_TAB_LINK, -} from '../../utils/internalRoutes' -import { LinkWithStickyParams } from '../../utils/urlutils' - -import HetEmailSignup from '../../styles/HetComponents/HetEmailSignup' - -export default function SignupSection() { - return ( -
    -

    - Please{' '} - - contact us - {' '} - with any questions or concerns, and{' '} - - consider sharing your own story - - . -

    -

    - For more information about health equity, please sign up for our Satcher - Health Leadership Institute newsletter. -

    - -
    - ) -} diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts index 8d2b8cabe5..a9aca6c650 100644 --- a/frontend/tailwind.config.ts +++ b/frontend/tailwind.config.ts @@ -62,6 +62,7 @@ export default { bigHeader: '3rem', biggerHeader: '3.125rem', biggestHeader: '4rem', + heroHeader: '4.5rem' }, // TODO: improve this hack that convinces TS that Tailwind can use z index numbers (not only strings) zIndex: ThemeZIndexValues as Record as Record< From 4e10de0e103a98a81ff15a6532c65862f7b1f00b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Hammond=20=F0=9F=8E=9B=EF=B8=8F?= Date: Thu, 9 Jan 2025 10:14:15 -0700 Subject: [PATCH 2/5] Frontend: small second cleanup PR for d3 stacked refactor (#3907) --- biome.json | 2 +- frontend/playwright-tests/cawp.ci.spec.ts | 6 ------ frontend/playwright.config.ts | 4 ++-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/biome.json b/biome.json index 15ee5cf568..2ad0e650a7 100644 --- a/biome.json +++ b/biome.json @@ -31,7 +31,7 @@ "useSortedClasses": "info" }, "a11y": { - "useSemanticElements": "info", + "useSemanticElements": "off", "noSvgWithoutTitle": "off" }, "suspicious": { diff --git a/frontend/playwright-tests/cawp.ci.spec.ts b/frontend/playwright-tests/cawp.ci.spec.ts index 0c51f0ad21..3ae12f0d8a 100644 --- a/frontend/playwright-tests/cawp.ci.spec.ts +++ b/frontend/playwright-tests/cawp.ci.spec.ts @@ -49,12 +49,6 @@ test('CAWP: Congress', async ({ page }) => { ) .getByText('7.1% of women members', { exact: true }) .click() - await page - .getByLabel( - 'Comparison bar chart showing Population vs. distribution of total women in US congress in the United States', - ) - .getByText('20.0% of women members', { exact: true }) - .click() await page.getByRole('button', { name: 'US Congress', exact: true }).click() await page.getByRole('menuitem', { name: 'State legislatures' }).click() diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index 05532193ad..7b216fadd2 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -12,10 +12,10 @@ const config: PlaywrightTestConfig = { }, testDir: './playwright-tests', /* Maximum time one test can run for, default was 30s. */ - timeout: process.env.CI ? 150 * 1000 : 90 * 1000, + timeout: process.env.CI ? 150 * 1000 : 60 * 1000, /* Maximum time one "expect" can run for, default was 5 seconds and was too quick */ expect: { - timeout: 90 * 1000, + timeout: process.env.CI ? 90 * 1000 : 10 * 1000, }, /* run all tests, even those within a shared file, in parallel */ fullyParallel: true, From bbd0ceb987cd4255ec4b1cb91b1ee2758ba5e5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Hammond=20=F0=9F=8E=9B=EF=B8=8F?= Date: Thu, 9 Jan 2025 10:43:37 -0700 Subject: [PATCH 3/5] Frontend/Frontend Server: Replace `console.log`s with specific methods (#3908) By switching the codebase's `console.log` statements into more specific ones like `.info()` `.error()` `.warn()`, we provide better developer feedback, and we also make it easier to find and remove any temporary console.log statements that have been added and overlooked during the local dev process --- biome.json | 13 +- .../playwright-tests/externalUrls.spec.ts | 24 ++-- .../playwright-tests/landing_page.ci.spec.ts | 2 +- frontend/src/ErrorBoundaryDropParams.jsx | 2 +- frontend/src/charts/rateBarChart/Index.tsx | 1 - frontend/src/data/config/MetadataMap.test.ts | 2 +- frontend/src/data/query/MetricQuery.ts | 1 + frontend/src/utils/globals.ts | 2 +- frontend_server/server.js | 125 +++++++++--------- 9 files changed, 94 insertions(+), 78 deletions(-) diff --git a/biome.json b/biome.json index 2ad0e650a7..e4524cb9eb 100644 --- a/biome.json +++ b/biome.json @@ -39,7 +39,18 @@ "noImplicitAnyLet": "off", "noArrayIndexKey": "off", "noAssignInExpressions": "off", - "noGlobalIsNan": "off" + "noGlobalIsNan": "off", + "noConsole": { + "level": "info", + "options": { + "allow": [ + "assert", + "error", + "info", + "warn" + ] + } + } }, "correctness": { "useExhaustiveDependencies": "off" diff --git a/frontend/playwright-tests/externalUrls.spec.ts b/frontend/playwright-tests/externalUrls.spec.ts index 6a044b093b..bb3b1fdcc3 100644 --- a/frontend/playwright-tests/externalUrls.spec.ts +++ b/frontend/playwright-tests/externalUrls.spec.ts @@ -40,7 +40,7 @@ test(`Fetch First 100 Blog Posts`, async ({ page }) => { 'https://hetblog.dreamhosters.com/wp-json/wp/v2/posts?_embed&per_page=100' const response = await page.goto(url, { waitUntil: 'domcontentloaded' }) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) for (const url of Object.values(urlMap)) { @@ -48,7 +48,7 @@ for (const url of Object.values(urlMap)) { test(`${url}`, async ({ page }) => { const response = await page.goto(url, { waitUntil: 'domcontentloaded' }) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } @@ -59,7 +59,7 @@ for (const url of RESOURCES.resources test(`Resource Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } @@ -70,7 +70,7 @@ for (const url of PDOH_RESOURCES.resources test(`PDOH_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } @@ -81,7 +81,7 @@ for (const url of EQUITY_INDEX_RESOURCES.resources test(`EQUITY_INDEX_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } @@ -92,7 +92,7 @@ for (const url of ECONOMIC_EQUITY_RESOURCES.resources test(`ECONOMIC_EQUITY_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } @@ -103,7 +103,7 @@ for (const url of AIAN_RESOURCES.resources test(`AIAN_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } @@ -114,7 +114,7 @@ for (const url of API_RESOURCES.resources test(`API_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } @@ -125,7 +125,7 @@ for (const url of HISP_RESOURCES.resources test(`HISP_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } @@ -136,7 +136,7 @@ for (const url of MENTAL_HEALTH_RESOURCES.resources test(`MENTAL_HEALTH_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } for (const url of COVID_RESOURCES.resources @@ -146,7 +146,7 @@ for (const url of COVID_RESOURCES.resources test(`COVID_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } for (const url of COVID_VACCINATION_RESOURCES.resources @@ -156,6 +156,6 @@ for (const url of COVID_VACCINATION_RESOURCES.resources test(`COVID_VACCINATION_RESOURCES Page: ${url}`, async ({ page }) => { const response = await page.goto(url) if (response?.status() !== 200) - console.log('\n🙀', url, response?.status(), '\n') + console.error('\n🙀', url, response?.status(), '\n') }) } diff --git a/frontend/playwright-tests/landing_page.ci.spec.ts b/frontend/playwright-tests/landing_page.ci.spec.ts index 15a239a741..79ffe4b043 100644 --- a/frontend/playwright-tests/landing_page.ci.spec.ts +++ b/frontend/playwright-tests/landing_page.ci.spec.ts @@ -1,6 +1,6 @@ import { test } from '@playwright/test' test(`Site Loads`, async ({ page, baseURL }) => { - console.log(`Running tests against: ${baseURL}`) + console.info(`Running tests against: ${baseURL}`) await page.goto('/', { waitUntil: 'commit' }) }) diff --git a/frontend/src/ErrorBoundaryDropParams.jsx b/frontend/src/ErrorBoundaryDropParams.jsx index a8438d9d81..6f18713d94 100644 --- a/frontend/src/ErrorBoundaryDropParams.jsx +++ b/frontend/src/ErrorBoundaryDropParams.jsx @@ -12,7 +12,7 @@ export default class ErrorBoundary extends React.Component { } componentDidCatch(error, info) { - console.log(error, info.componentStack) + console.error(error, info.componentStack) } render() { diff --git a/frontend/src/charts/rateBarChart/Index.tsx b/frontend/src/charts/rateBarChart/Index.tsx index b02fe1d826..4abd8ea121 100644 --- a/frontend/src/charts/rateBarChart/Index.tsx +++ b/frontend/src/charts/rateBarChart/Index.tsx @@ -101,7 +101,6 @@ export function RateBarChart(props: RateBarChartProps) { className='relative' > - {/* biome-ignore lint/a11y/noSvgWithoutTitle: we use aria-label instead, so screen reader has accessible text but browser tooltips don't interfere with custom tooltip */} { test('Links all use HTTPS', () => { Object.values(dataSourceMetadataMap).forEach((metadata) => { const testUrl = metadata.data_source_link - console.log(testUrl, '--') + console.info(testUrl, '--') expect(testUrl.slice(0, 8)).toEqual('https://') }) diff --git a/frontend/src/data/query/MetricQuery.ts b/frontend/src/data/query/MetricQuery.ts index fcd3db3804..846b0bd878 100644 --- a/frontend/src/data/query/MetricQuery.ts +++ b/frontend/src/data/query/MetricQuery.ts @@ -178,6 +178,7 @@ export function resolveDatasetId( // Normal, valid demographic request const requestedDatasetId: string = `${bqDatasetName}-${tablePrefix}${requestedDemographic}_${requestedGeography}_${timeView}` + if (isValidDatasetId(requestedDatasetId)) { return { breakdowns, diff --git a/frontend/src/utils/globals.ts b/frontend/src/utils/globals.ts index c6f34848a8..c7dc9a884c 100644 --- a/frontend/src/utils/globals.ts +++ b/frontend/src/utils/globals.ts @@ -39,7 +39,7 @@ export function initGlobals( ) { if (globals.initialized && !import.meta.env.PROD) { // throw new Error('Cannot initialize globals multiple times') - console.log('Cannot initialize globals multiple times') + console.error('Cannot initialize globals multiple times') } globals.environment = environment diff --git a/frontend_server/server.js b/frontend_server/server.js index 3b9e4a3b1f..16fad55c5b 100644 --- a/frontend_server/server.js +++ b/frontend_server/server.js @@ -1,74 +1,74 @@ -'use strict'; - +import compression from 'compression' +import path, { dirname } from 'node:path' +import { fileURLToPath } from 'node:url' // TODO: change over to use ESModules with import() instead of require() ? -import express from 'express'; -import compression from 'compression'; -import basicAuth from 'express-basic-auth'; -import { createProxyMiddleware } from 'http-proxy-middleware'; -import { fileURLToPath } from 'url'; -import path, { dirname } from 'path'; +import express from 'express' +import basicAuth from 'express-basic-auth' +import { createProxyMiddleware } from 'http-proxy-middleware' -const buildDir = process.env['BUILD_DIR'] || 'build'; -console.log(`Build directory: ${buildDir}`); +const buildDir = process.env['BUILD_DIR'] || 'build' +console.info(`Build directory: ${buildDir}`) export function assertEnvVar(name) { - const value = process.env[name]; - console.log(`Environment variable ${name}: ${value}`); - if (value === "NULL") return "" + const value = process.env[name] + console.info(`Environment variable ${name}: ${value}`) + if (value === 'NULL') return '' if (!value) { throw new Error( - `Invalid environment variable. Name: ${name}, value: ${value}`); + `Invalid environment variable. Name: ${name}, value: ${value}`, + ) } - return value; + return value } export function getBooleanEnvVar(name) { - const value = process.env[name]; - console.log(`Environment variable ${name}: ${value}`); - if (value && value !== "true" && value !== "false") { + const value = process.env[name] + console.info(`Environment variable ${name}: ${value}`) + if (value && value !== 'true' && value !== 'false') { throw new Error( - `Invalid boolean environment variable. Name: ${name}, value: ${value}`); + `Invalid boolean environment variable. Name: ${name}, value: ${value}`, + ) } - return value === "true"; + return value === 'true' } // TODO it would be nice to extract PORT and HOST to environment variables // because it's good practice not to hard-code this kind of configuration. -const PORT = 8080; -const HOST = '0.0.0.0'; -const app = express(); +const PORT = 8080 +const HOST = '0.0.0.0' +const app = express() app.use(compression()) // Add Authorization header for all requests that are proxied to the data server. // TODO: The token can be cached and only refreshed when needed app.use('/api', (req, res, next) => { - if (assertEnvVar("NODE_ENV") === 'production') { + if (assertEnvVar('NODE_ENV') === 'production') { // Set up metadata server request // See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature - const metadataServerTokenURL = assertEnvVar("METADATA_SERVER_TOKEN_URL"); - const targetUrl = assertEnvVar("DATA_SERVER_URL"); - const fetchUrl = metadataServerTokenURL + targetUrl; + const metadataServerTokenURL = assertEnvVar('METADATA_SERVER_TOKEN_URL') + const targetUrl = assertEnvVar('DATA_SERVER_URL') + const fetchUrl = metadataServerTokenURL + targetUrl const options = { headers: { - 'Metadata-Flavor': 'Google' - } - }; + 'Metadata-Flavor': 'Google', + }, + } fetch(fetchUrl, options) - .then(res => res.text()) - .then(token => { + .then((res) => res.text()) + .then((token) => { // Set the bearer token temporarily to Authorization_DataServer header. If BasicAuth is enabled, // it will overwrite the Authorization header after the token is fetched. Right before the proxy // request is sent, overwrite the Authorization header with the bearer token from the service // account and delete the Authorization_DataServer header. - req.headers["Authorization_DataServer"] = `bearer ${token}`; - next(); + req.headers['Authorization_DataServer'] = `bearer ${token}` + next() }) - .catch(next); + .catch(next) } else { - next(); + next() } -}); +}) // TODO should this go before or after basic auth? // TODO check if these are all the right proxy options. For example, there's a @@ -76,44 +76,49 @@ app.use('/api', (req, res, next) => { // it but I can't find good documentation. // TODO add logging if there's an error in the request. const apiProxyOptions = { - target: assertEnvVar("DATA_SERVER_URL"), + target: assertEnvVar('DATA_SERVER_URL'), changeOrigin: true, // needed for virtual hosted sites pathRewrite: { '^/api': '' }, onProxyReq: (proxyReq, req, res) => { // Replace the basic auth header with the service account token. - proxyReq.setHeader('Authorization', proxyReq.getHeader('Authorization_DataServer')); - proxyReq.removeHeader('Authorization_DataServer'); - } -}; -const apiProxy = createProxyMiddleware(apiProxyOptions); -app.use('/api', apiProxy); + proxyReq.setHeader( + 'Authorization', + proxyReq.getHeader('Authorization_DataServer'), + ) + proxyReq.removeHeader('Authorization_DataServer') + }, +} +const apiProxy = createProxyMiddleware(apiProxyOptions) +app.use('/api', apiProxy) // auth middleware must be installed before setting up routes so it applies // to the whole site. -if (!getBooleanEnvVar("DISABLE_BASIC_AUTH")) { - const username = assertEnvVar("BASIC_AUTH_USERNAME"); - const password = assertEnvVar("BASIC_AUTH_PASSWORD"); - app.use(basicAuth({ - // Temporary values until we can use Github Secrets. Also needs to be set up - // so that it's disabled for production but enabled for the test site. - users: { [username]: password }, - challenge: true, - realm: 'Health Equity Tracker', - })); +if (!getBooleanEnvVar('DISABLE_BASIC_AUTH')) { + const username = assertEnvVar('BASIC_AUTH_USERNAME') + const password = assertEnvVar('BASIC_AUTH_PASSWORD') + app.use( + basicAuth({ + // Temporary values until we can use Github Secrets. Also needs to be set up + // so that it's disabled for production but enabled for the test site. + users: { [username]: password }, + challenge: true, + realm: 'Health Equity Tracker', + }), + ) } app.use(compression()) // Serve static files from the build directory. -const __dirname = dirname(fileURLToPath(import.meta.url)); -app.use(express.static(path.join(__dirname, buildDir))); +const __dirname = dirname(fileURLToPath(import.meta.url)) +app.use(express.static(path.join(__dirname, buildDir))) // Route all other paths to index.html. The "*" must be used otherwise // client-side routing wil fail due to missing exact matches. For more info, see // https://create-react-app.dev/docs/deployment/#serving-apps-with-client-side-routing app.get('/*', (req, res) => { - res.sendFile(path.join(__dirname, buildDir, 'index.html')); -}); + res.sendFile(path.join(__dirname, buildDir, 'index.html')) +}) -app.listen(PORT, HOST); -console.log(`Running on http://${HOST}:${PORT}`); +app.listen(PORT, HOST) +console.info(`Running on http://${HOST}:${PORT}`) From 1506e92d0235b2acca21fa13982a94f393f96b8c Mon Sep 17 00:00:00 2001 From: kccrtv Date: Wed, 8 Jan 2025 10:22:46 -0600 Subject: [PATCH 4/5] spacing --- frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx b/frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx index ddb869002b..6c3e8c539b 100644 --- a/frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx +++ b/frontend/src/pages/TermsOfUsePage/TermsOfUsePage.tsx @@ -91,10 +91,10 @@ export default function TermsOfUsePage() { Terms of Use

Terms of Use

-