From d25d1f3e718c40cdb034d3a1876c628360379ac1 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Wed, 25 Oct 2023 09:46:47 +0000 Subject: [PATCH 01/32] refactor(datapage): extract component-specific css --- .../src/IndicatorBrief/IndicatorBrief.scss | 60 ++++++++++ .../src/IndicatorBrief/IndicatorBrief.tsx | 16 +-- .../IndicatorProcessing.scss | 50 +++++++++ .../IndicatorProcessing.tsx | 60 +++++----- .../IndicatorSources/IndicatorSources.scss | 30 +++++ .../components/src/styles}/mixins.scss | 0 site/DataPageContent.scss | 106 ------------------ site/DataPageV2Content.tsx | 63 +++++++---- site/owid.scss | 10 +- 9 files changed, 223 insertions(+), 172 deletions(-) create mode 100644 packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss create mode 100644 packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss create mode 100644 packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss rename {site/css => packages/@ourworldindata/components/src/styles}/mixins.scss (100%) diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss new file mode 100644 index 00000000000..fdd57e141c5 --- /dev/null +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss @@ -0,0 +1,60 @@ +.key-info__curated { + margin-bottom: 32px; +} + +.key-info__title { + @include h2-bold; + margin: 0 0 16px; + @include sm-up { + margin: 0 0 24px; + } +} + +.key-info__content { + margin-bottom: 24px; + + li { + @include body-2-regular; + } +} + +.key-info__learn-more { + @include expandable-paragraph__expand-button--full; + svg { + font-size: 0.75em; + margin-left: 12px; + } +} + +.key-info__right { + @include sm-only { + margin-top: 32px; + } + @include sm-up { + padding-left: 24px; + border-left: 1px solid $blue-20; + } + row-gap: 24px; +} + +.key-data { + @include body-3-medium; + a { + @include owid-link-90; + color: inherit; + } +} + +.key-data--hide-overflow div:last-child { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.key-data__title { + color: $blue-50; +} + +.key-data__title--dark { + color: $blue-90; +} diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx index d5cec9e9474..f5739a22a56 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx @@ -39,8 +39,8 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => { ) return ( -
-
+ <> +
{(props.descriptionShort || props.descriptionKey) && (
{props.descriptionShort ? ( @@ -94,8 +94,8 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => { /> )}
-
-
+
+
Source
{props.attribution} – with{" "} @@ -107,16 +107,16 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => { by Our World In Data
-
+
Date range
{props.dateRange}
-
+
Last updated
{lastUpdated.format("MMMM D, YYYY")}
{props.nextUpdate && ( -
+
Next expected update
@@ -124,6 +124,6 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => {
)}
-
+ ) } diff --git a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss new file mode 100644 index 00000000000..8bc518ca6c5 --- /dev/null +++ b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss @@ -0,0 +1,50 @@ +.variable-processing-info .article-block__text a { + @include owid-link-60; + color: inherit; +} + +.data-sources-processing__title { + @include datapage-section-title; +} + +.data-processing__content { + margin-bottom: 24px; +} + +.data-processing__paragraph { + @include body-3-medium; + margin: 0 0 16px; +} + +.data-processing__link { + @include expandable-paragraph__expand-button--full; +} + +.variable-processing-info { + display: flex; + flex-direction: column; + background-color: $white; + margin: 32px -24px 0; + padding: 24px; +} + +.variable-processing-info__header { + @include overline-black-caps; + text-transform: uppercase; + margin: 0 0 8px; +} + +.variable-processing-info__description { + color: $blue-60; + + .article-block__text, + .article-block__list, + .article-block__html, + .article-block__numbered-list { + @include body-3-medium; + } + + > *:last-child { + margin-bottom: 0; + } +} diff --git a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx index 86486af8016..bb0e611fa03 100644 --- a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx +++ b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx @@ -8,43 +8,33 @@ export interface IndicatorProcessingProps { export const IndicatorProcessing = (props: IndicatorProcessingProps) => { return ( <> -
-

- How we process data at Our World in Data -

-
-
-

- All data and visualizations on Our World in Data - rely on data sourced from one or several original - data providers. Preparing this original data - involves several processing steps. Depending on the - data, this can include standardizing country names - and world region definitions, converting units, - calculating derived indicators such as per capita - measures, as well as adding or adapting metadata - such as the name or the description given to an - indicator. -

-

- At the link below you can find a detailed - description of the structure of our data pipeline, - including links to all the code used to prepare data - across Our World in Data. -

-
- - Read about our data pipeline - -
+
+

+ All data and visualizations on Our World in Data rely on + data sourced from one or several original data providers. + Preparing this original data involves several processing + steps. Depending on the data, this can include standardizing + country names and world region definitions, converting + units, calculating derived indicators such as per capita + measures, as well as adding or adapting metadata such as the + name or the description given to an indicator. +

+

+ At the link below you can find a detailed description of the + structure of our data pipeline, including links to all the + code used to prepare data across Our World in Data. +

+ + Read about our data pipeline + {props.descriptionProcessing && ( -
+
Notes on our processing step for this indicator
diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss new file mode 100644 index 00000000000..9d407c9ebb0 --- /dev/null +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss @@ -0,0 +1,30 @@ +.source__key-data { + row-gap: 32px; + + .wp-code-snippet { + margin-top: 8px; + margin-bottom: 0; + } +} + +.key-data { + @include body-3-medium; + a { + @include owid-link-90; + color: inherit; + } +} + +.key-data--hide-overflow div:last-child { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.key-data__title { + color: $blue-50; +} + +.key-data__title--dark { + color: $blue-90; +} diff --git a/site/css/mixins.scss b/packages/@ourworldindata/components/src/styles/mixins.scss similarity index 100% rename from site/css/mixins.scss rename to packages/@ourworldindata/components/src/styles/mixins.scss diff --git a/site/DataPageContent.scss b/site/DataPageContent.scss index e8a5199a823..1772009d0d8 100644 --- a/site/DataPageContent.scss +++ b/site/DataPageContent.scss @@ -139,68 +139,6 @@ } } - .key-info__content { - li { - @include body-2-regular; - } - } - - .key-info__curated { - margin-bottom: 32px; - } - - .key-info__content { - margin-bottom: 24px; - } - .key-info__title { - @include h2-bold; - margin: 0 0 16px; - @include sm-up { - margin: 0 0 24px; - } - } - - .key-info__learn-more { - @include expandable-paragraph__expand-button--full; - svg { - font-size: 0.75em; - margin-left: 12px; - } - } - - .key-info__right { - @include sm-only { - margin-top: 32px; - } - @include sm-up { - padding-left: 24px; - border-left: 1px solid $blue-20; - } - row-gap: 24px; - } - - .key-data { - @include body-3-medium; - a { - @include owid-link-90; - color: inherit; - } - } - - .key-data--hide-overflow div:last-child { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - } - - .key-data__title { - color: $blue-50; - } - - .key-data__title--dark { - color: $blue-90; - } - .bg-gray-10 { background-color: $gray-10; } @@ -370,11 +308,6 @@ margin: 24px 0 16px; } } - - .data-sources-processing__title { - @include datapage-section-title; - } - .data-sources { .article-block__text, .article-block__list, @@ -391,20 +324,10 @@ margin: 0 0 24px; } - .source__key-data { - row-gap: 32px; - - .wp-code-snippet { - margin-top: 8px; - margin-bottom: 0; - } - } - .data-processing { margin-top: 32px; } - .data-processing__content, .reuse__content { margin-bottom: 24px; } @@ -413,47 +336,18 @@ margin-left: 16px; } - .data-processing__paragraph, .reuse__list-item, .citation__paragraph { @include body-3-medium; margin: 0 0 16px; } - .data-processing__link { - @include expandable-paragraph__expand-button--full; - } - - .variable-processing-info { - display: flex; - flex-direction: column; - background-color: $white; - margin: 32px -24px 0; - padding: 24px; - } - - .variable-processing-info__header, .citation__how-to-header { @include overline-black-caps; text-transform: uppercase; margin: 0 0 8px; } - .variable-processing-info__description { - color: $blue-60; - - .article-block__text, - .article-block__list, - .article-block__html, - .article-block__numbered-list { - @include body-3-medium; - } - - > *:last-child { - margin-bottom: 0; - } - } - .reuse__title { @include datapage-section-title; } diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx index 82bd3971649..a6d4232a24d 100644 --- a/site/DataPageV2Content.tsx +++ b/site/DataPageV2Content.tsx @@ -282,20 +282,28 @@ export const DataPageV2Content = ({ className="wrapper" id="explore-the-data" /> - +
+
+ +
+
{relatedResearch && relatedResearch.length > 0 && ( @@ -492,12 +500,27 @@ export const DataPageV2Content = ({ > Sources and processing - - +
+

+ This data is based on the following + sources +

+
+ +
+
+
+

+ How we process data at Our World in Data +

+
+ +
+

Date: Wed, 25 Oct 2023 12:43:27 +0000 Subject: [PATCH 02/32] feat(datapage): adapt design of the About this data section --- datapage/Datapage.ts | 1 + .../src/IndicatorBrief/IndicatorBrief.scss | 94 ++++++---- .../src/IndicatorBrief/IndicatorBrief.tsx | 167 ++++++++++-------- .../components/src/styles/typography.scss | 13 ++ .../@ourworldindata/utils/src/owidTypes.ts | 1 + site/DataPageV2Content.tsx | 7 +- 6 files changed, 173 insertions(+), 110 deletions(-) diff --git a/datapage/Datapage.ts b/datapage/Datapage.ts index f67fb4b9fb8..426e643fae5 100644 --- a/datapage/Datapage.ts +++ b/datapage/Datapage.ts @@ -62,6 +62,7 @@ export const getDatapageDataV2 = async ( source: variableMetadata.source, origins: variableMetadata.origins ?? [], chartConfig: partialGrapherConfig as Record, + unit: variableMetadata.display?.unit ?? variableMetadata.unit, } return datapageJson } diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss index fdd57e141c5..2b5428e6930 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss @@ -1,60 +1,80 @@ -.key-info__curated { +.about-this-data { margin-bottom: 32px; -} -.key-info__title { - @include h2-bold; - margin: 0 0 16px; - @include sm-up { - margin: 0 0 24px; + &__heading { + @include h2-bold; + margin: 0 0 16px; } -} -.key-info__content { - margin-bottom: 24px; + &__indicator-title { + @include h5-black-caps; + color: $blue-50; + margin: 0 0 8px; + } - li { + &__indicator-description { @include body-2-regular; + margin: 0 0 16px; } } -.key-info__learn-more { - @include expandable-paragraph__expand-button--full; - svg { - font-size: 0.75em; - margin-left: 12px; - } -} +.key-data { + @include body-3-medium; + border-bottom: 1px solid $blue-20; + + display: grid; + grid-template-columns: repeat(4, 1fr); -.key-info__right { @include sm-only { - margin-top: 32px; + grid-template-columns: max-content 1fr; } - @include sm-up { - padding-left: 24px; - border-left: 1px solid $blue-20; + + &__title, + &__content { + padding: 16px 0; + border-top: 1px solid $blue-20; + } + + &__title { + color: $blue-50; + padding-right: 24px; + } + + &__content-source { + grid-column: 2 / -1; } - row-gap: 24px; -} -.key-data { - @include body-3-medium; a { @include owid-link-90; color: inherit; } } -.key-data--hide-overflow div:last-child { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} +.key-info { + background-color: $gray-10; + border-left: 4px solid $blue-10; + padding: 40px; + margin: 0 -40px 32px -40px; -.key-data__title { - color: $blue-50; -} + &__title { + @include h5-black-caps; + color: $blue-50; + margin-top: 0; + margin-bottom: 16px; + } -.key-data__title--dark { - color: $blue-90; + &__content { + @include body-2-regular; + li { + @include body-2-regular; + } + } + + &__learn-more { + @include expandable-paragraph__expand-button--full; + svg { + font-size: 0.75em; + margin-left: 12px; + } + } } diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx index f5739a22a56..ccdb88817af 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx @@ -7,65 +7,109 @@ import { dayjs } from "@ourworldindata/utils" import { DATAPAGE_SOURCES_AND_PROCESSING_SECTION_ID } from "../SharedDataPageConstants.js" interface IndicatorBriefProps { - descriptionShort: string | undefined - descriptionKey: string[] | undefined + title: string + descriptionShort?: string + descriptionKey?: string[] hasFaqEntries: boolean - descriptionFromProducer: string | undefined - attributionShort: string | undefined + descriptionFromProducer?: string + attributionShort?: string attribution: string processedAdapted: string - dateRange: string | undefined + dateRange?: string lastUpdated: string - nextUpdate: string | undefined + nextUpdate?: string + additionalInfo?: string + unit?: string } export const IndicatorBrief = (props: IndicatorBriefProps) => { - let descriptionKeyBulletPointsOrText: JSX.Element | null = null const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) - if (props.descriptionKey) - if (props.descriptionKey.length === 1) - descriptionKeyBulletPointsOrText = ( - - ) - else - descriptionKeyBulletPointsOrText = ( -
    - {props.descriptionKey.map((item, i) => ( -
  • - -
  • - ))} -
- ) - + const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) return ( <> -
- {(props.descriptionShort || props.descriptionKey) && ( -
- {props.descriptionShort ? ( +
+
+

+ About this data +

+ {props.descriptionShort && ( + <> +
+ {props.title} +
+

+ +

+ + )} +
+
Source
+
+ {props.attribution} – with{" "} + + {props.processedAdapted} + {" "} + by Our World In Data +
+
Last updated
+
+ {lastUpdated.format("MMMM D, YYYY")} +
+ {props.nextUpdate && ( <> -

- About this data -

-
- +
+ Next expected update +
+
+ {props.nextUpdate}
- ) : null} - {props.descriptionKey ? ( + )} +
Date range
+
+ {props.dateRange} +
+ {props.unit && ( <> -

- What you should know about this indicator -

-
- {descriptionKeyBulletPointsOrText} +
Unit
+
+ {props.unit}
- ) : null} - + )} + {/* needed for its top-border */} + {keyDataCount % 2 === 0 && ( + <> +
+
+ + )} +
+
+ {props.descriptionKey && ( +
+

+ What you should know about this indicator +

+
+ {props.descriptionKey.length === 1 ? ( + + ) : ( +
    + {props.descriptionKey.map((item, i) => ( +
  • + +
  • + ))} +
+ )} +
{props.hasFaqEntries && ( Learn more in the FAQs @@ -91,37 +135,16 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => { isExpandedDefault={ !(props.descriptionShort || props.descriptionKey) } + isStacked={!!props.additionalInfo} /> )} -
-
- -
-
Date range
-
{props.dateRange}
-
-
-
Last updated
-
{lastUpdated.format("MMMM D, YYYY")}
-
- {props.nextUpdate && ( -
-
- Next expected update -
-
{props.nextUpdate}
-
+ {props.additionalInfo && ( + + } + /> )}
diff --git a/packages/@ourworldindata/components/src/styles/typography.scss b/packages/@ourworldindata/components/src/styles/typography.scss index 945532f5f8d..d952410e7dd 100644 --- a/packages/@ourworldindata/components/src/styles/typography.scss +++ b/packages/@ourworldindata/components/src/styles/typography.scss @@ -176,6 +176,19 @@ body { @include h4-semibold; } +@mixin h5-black-caps { + font-family: $sans-serif-font-stack; + font-size: 0.75rem; + font-weight: 900; + line-height: 1.33; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.h5-black-caps { + @include h5-black-caps; +} + @mixin subtitle-1 { font-family: $sans-serif-font-stack; font-size: 1.5rem; diff --git a/packages/@ourworldindata/utils/src/owidTypes.ts b/packages/@ourworldindata/utils/src/owidTypes.ts index 99a6205a4c4..ff9afaceae3 100644 --- a/packages/@ourworldindata/utils/src/owidTypes.ts +++ b/packages/@ourworldindata/utils/src/owidTypes.ts @@ -1599,6 +1599,7 @@ export interface DataPageDataV2 { source: OwidSource | undefined origins: OwidOrigin[] chartConfig: Record + unit?: string } export interface DataPageRelatedResearch { diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx index a6d4232a24d..34a0724d9dc 100644 --- a/site/DataPageV2Content.tsx +++ b/site/DataPageV2Content.tsx @@ -283,8 +283,9 @@ export const DataPageV2Content = ({ id="explore-the-data" />
-
+
From 0255ab335ca839ef3647ed4b97ce717628bd37d8 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Wed, 25 Oct 2023 12:48:36 +0000 Subject: [PATCH 03/32] fix(datapage): prevent style leak --- .../components/src/IndicatorBrief/IndicatorBrief.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss index 2b5428e6930..26b48dc2645 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss @@ -18,7 +18,7 @@ } } -.key-data { +.about-this-data .key-data { @include body-3-medium; border-bottom: 1px solid $blue-20; From 4c20d49a553c8dd918284339ed49b458a52a08c6 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Thu, 26 Oct 2023 08:05:57 +0000 Subject: [PATCH 04/32] fix(datapage): hide empty table cells --- .../components/src/IndicatorBrief/IndicatorBrief.scss | 6 ++++++ .../components/src/IndicatorBrief/IndicatorBrief.tsx | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss index 26b48dc2645..b8e4cbc7c2d 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss @@ -33,6 +33,12 @@ &__content { padding: 16px 0; border-top: 1px solid $blue-20; + + &.empty { + @include sm-only { + display: none; + } + } } &__title { diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx index ccdb88817af..f689b3ac845 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx @@ -23,6 +23,7 @@ interface IndicatorBriefProps { } export const IndicatorBrief = (props: IndicatorBriefProps) => { + props = { ...props, unit: undefined } const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) return ( @@ -84,8 +85,8 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => { {/* needed for its top-border */} {keyDataCount % 2 === 0 && ( <> -
-
+
+
)}
From 837bbb4425101e27623e5372046168ed2ff00c13 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Thu, 26 Oct 2023 09:24:25 +0000 Subject: [PATCH 05/32] refactpr(datapage): clean up IndicatorSources component --- .../src/IndicatorBrief/IndicatorBrief.scss | 126 ++++++------- .../src/IndicatorBrief/IndicatorBrief.tsx | 2 +- .../IndicatorSources/IndicatorSources.scss | 54 +++--- .../src/IndicatorSources/IndicatorSources.tsx | 168 ++++++++---------- 4 files changed, 173 insertions(+), 177 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss index b8e4cbc7c2d..a7cbc8361d5 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss @@ -1,86 +1,88 @@ -.about-this-data { - margin-bottom: 32px; +.indicator-brief { + .about-this-data { + margin-bottom: 32px; - &__heading { - @include h2-bold; - margin: 0 0 16px; - } + &__heading { + @include h2-bold; + margin: 0 0 16px; + } - &__indicator-title { - @include h5-black-caps; - color: $blue-50; - margin: 0 0 8px; - } + &__indicator-title { + @include h5-black-caps; + color: $blue-50; + margin: 0 0 8px; + } - &__indicator-description { - @include body-2-regular; - margin: 0 0 16px; + &__indicator-description { + @include body-2-regular; + margin: 0 0 16px; + } } -} -.about-this-data .key-data { - @include body-3-medium; - border-bottom: 1px solid $blue-20; + .key-data { + @include body-3-medium; + border-bottom: 1px solid $blue-20; - display: grid; - grid-template-columns: repeat(4, 1fr); + display: grid; + grid-template-columns: repeat(4, 1fr); - @include sm-only { - grid-template-columns: max-content 1fr; - } + @include sm-only { + grid-template-columns: max-content 1fr; + } - &__title, - &__content { - padding: 16px 0; - border-top: 1px solid $blue-20; + &__title, + &__content { + padding: 16px 0; + border-top: 1px solid $blue-20; - &.empty { - @include sm-only { - display: none; + &.empty { + @include sm-only { + display: none; + } } } - } - &__title { - color: $blue-50; - padding-right: 24px; - } + &__title { + color: $blue-50; + padding-right: 24px; + } - &__content-source { - grid-column: 2 / -1; - } + &__content-source { + grid-column: 2 / -1; + } - a { - @include owid-link-90; - color: inherit; + a { + @include owid-link-90; + color: inherit; + } } -} -.key-info { - background-color: $gray-10; - border-left: 4px solid $blue-10; - padding: 40px; - margin: 0 -40px 32px -40px; + .key-info { + background-color: $gray-10; + border-left: 4px solid $blue-10; + padding: 40px; + margin: 0 -40px 32px -40px; - &__title { - @include h5-black-caps; - color: $blue-50; - margin-top: 0; - margin-bottom: 16px; - } + &__title { + @include h5-black-caps; + color: $blue-50; + margin-top: 0; + margin-bottom: 16px; + } - &__content { - @include body-2-regular; - li { + &__content { @include body-2-regular; + li { + @include body-2-regular; + } } - } - &__learn-more { - @include expandable-paragraph__expand-button--full; - svg { - font-size: 0.75em; - margin-left: 12px; + &__learn-more { + @include expandable-paragraph__expand-button--full; + svg { + font-size: 0.75em; + margin-left: 12px; + } } } } diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx index f689b3ac845..0947db7b256 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx @@ -28,7 +28,7 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => { const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) return ( <> -
+

About this data diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss index 9d407c9ebb0..6d63fd14c36 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss @@ -1,30 +1,40 @@ -.source__key-data { - row-gap: 32px; +.source-content { + .description { + @include body-3-medium; + margin: 0; + } + + .key-info { + margin-top: 16px; + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + row-gap: 8px; - .wp-code-snippet { - margin-top: 8px; - margin-bottom: 0; + .wp-code-snippet { + margin-top: 8px; + margin-bottom: 0; + } } -} -.key-data { - @include body-3-medium; - a { - @include owid-link-90; - color: inherit; + .key-data { + @include body-3-medium; + a { + @include owid-link-90; + color: inherit; + } } -} -.key-data--hide-overflow div:last-child { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} + .key-data--span-2 { + grid-column: span 2; + } -.key-data__title { - color: $blue-50; -} + .key-data__title { + color: $blue-90; + } -.key-data__title--dark { - color: $blue-90; + .key-data--hide-overflow div:last-child { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } } diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx index a67421bf115..b5aee426b58 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx @@ -20,101 +20,85 @@ export interface IndicatorSourcesProps { } export const IndicatorSources = (props: IndicatorSourcesProps) => { - const citationFullBlockFn = (source: OriginSubset) => { - source.citationFull && ( -
-
Citation
- This is the citation of the original data obtained from the - source, prior to any processing or adaptation by Our World in - Data. To cite data downloaded from this page, please use the - suggested citation given in{" "} - - Reuse This Work - {" "} - below. - -
- ) - } return ( -
-

- This data is based on the following sources -

-
- {props.origins.map((source, idx: number, sources) => { - const dateAccessed = source.dateAccessed - ? dayjs(source.dateAccessed).format("MMMM D, YYYY") - : undefined - return ( -
- - {source.description && ( - - )} - {(dateAccessed || source.urlMain) && ( -
- {dateAccessed && ( -
-
- Retrieved on -
-
- {dateAccessed} -
-
- )} - {source.urlMain && ( -
-
- Retrieved from -
- -
- )} - {citationFullBlockFn(source)} -
- )} - - } + <> + {props.origins.map((source, idx: number, sources) => { + const label = + source.producer ?? + source.descriptionSnapshot ?? + source.description ?? + "" + return ( + } + isStacked={idx !== sources.length - 1} + hasTeaser + /> + ) + })} + + ) +} + +const SourceContent = (props: { source: OriginSubset }) => { + const { source } = props + const dateAccessed = source.dateAccessed + ? dayjs(source.dateAccessed).format("MMMM D, YYYY") + : undefined + const showKeyInfo = dateAccessed || source.urlMain || source.citationFull + return ( +
+ {source.description && ( +

+ +

+ )} + {showKeyInfo && ( +
+ {dateAccessed && ( +
+
Retrieved on
+
{dateAccessed}
+
+ )} + {source.urlMain && ( +
+
+ Retrieved from +
+ +
+ )} + {source.citationFull && ( +
+
Citation
+ This is the citation of the original data obtained + from the source, prior to any processing or + adaptation by Our World in Data. To cite data + downloaded from this page, please use the suggested + citation given in{" "} + + Reuse This Work + {" "} + below. +
- ) - })} -
+ )} +
+ )}
) } From ea2fe2498715c2077a310618c541905b58eeed74 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Thu, 26 Oct 2023 12:25:46 +0000 Subject: [PATCH 06/32] refactor(datapage): clean up IndicatorProcessing component --- .../IndicatorProcessing.scss | 92 +++++++++---------- .../IndicatorProcessing.tsx | 4 +- site/DataPageContent.scss | 1 + 3 files changed, 49 insertions(+), 48 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss index 8bc518ca6c5..dbf36182a44 100644 --- a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss +++ b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss @@ -1,50 +1,50 @@ -.variable-processing-info .article-block__text a { - @include owid-link-60; - color: inherit; -} - -.data-sources-processing__title { - @include datapage-section-title; -} - -.data-processing__content { - margin-bottom: 24px; -} - -.data-processing__paragraph { - @include body-3-medium; - margin: 0 0 16px; -} - -.data-processing__link { - @include expandable-paragraph__expand-button--full; -} - -.variable-processing-info { - display: flex; - flex-direction: column; - background-color: $white; - margin: 32px -24px 0; - padding: 24px; -} - -.variable-processing-info__header { - @include overline-black-caps; - text-transform: uppercase; - margin: 0 0 8px; -} - -.variable-processing-info__description { - color: $blue-60; - - .article-block__text, - .article-block__list, - .article-block__html, - .article-block__numbered-list { - @include body-3-medium; +.indicator-processing { + .data-processing { + &__content { + margin-bottom: 24px; + } + + &__paragraph { + @include body-3-medium; + margin: 0 0 16px; + } + + &__link { + @include expandable-paragraph__expand-button--full; + } } - > *:last-child { - margin-bottom: 0; + .variable-processing-info { + display: flex; + flex-direction: column; + background-color: $white; + margin: 32px -24px 0; + padding: 24px; + + &__header { + @include overline-black-caps; + text-transform: uppercase; + margin: 0 0 8px; + } + + &__description { + color: $blue-60; + + .article-block__text, + .article-block__list, + .article-block__html, + .article-block__numbered-list { + @include body-3-medium; + } + + > *:last-child { + margin-bottom: 0; + } + } + + .article-block__text a { + @include owid-link-60; + color: inherit; + } } } diff --git a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx index bb0e611fa03..7f41699adfa 100644 --- a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx +++ b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx @@ -7,7 +7,7 @@ export interface IndicatorProcessingProps { export const IndicatorProcessing = (props: IndicatorProcessingProps) => { return ( - <> +

All data and visualizations on Our World in Data rely on @@ -45,6 +45,6 @@ export const IndicatorProcessing = (props: IndicatorProcessingProps) => {

)} - +
) } diff --git a/site/DataPageContent.scss b/site/DataPageContent.scss index 1772009d0d8..d4cedc45448 100644 --- a/site/DataPageContent.scss +++ b/site/DataPageContent.scss @@ -279,6 +279,7 @@ } } + .data-sources-processing__title, .related-charts__title { @include datapage-section-title; } From d9b745ef97fbc8c69a6d597dc356d5d62cd3af98 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Thu, 26 Oct 2023 12:52:26 +0000 Subject: [PATCH 07/32] refactor(datapage): remove article-specific css from shared components --- .../src/IndicatorBrief/IndicatorBrief.scss | 12 +++++++++++- .../src/IndicatorBrief/IndicatorBrief.tsx | 16 ++++++++++------ .../IndicatorProcessing/IndicatorProcessing.tsx | 8 +++++--- .../src/IndicatorSources/IndicatorSources.tsx | 2 +- site/DataPageContent.scss | 9 +++++++++ 5 files changed, 36 insertions(+), 11 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss index a7cbc8361d5..0d50138c958 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss @@ -72,8 +72,18 @@ &__content { @include body-2-regular; - li { + ul { @include body-2-regular; + margin-bottom: 16px; + margin-left: 16px; + + li { + margin-bottom: 1em; + + &:last-child { + margin-bottom: 0; + } + } } } diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx index 0947db7b256..b059daea7fe 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx @@ -38,7 +38,7 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => {
{props.title}
-

+

@@ -96,16 +96,16 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => {

What you should know about this indicator

-
+
{props.descriptionKey.length === 1 ? ( ) : ( -
    +
      {props.descriptionKey.map((item, i) => (
    • - + {" "}
    • ))}
    @@ -127,7 +127,7 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => { : "How does the producer of this data describe this data?" } content={ -
    +
    @@ -143,7 +143,11 @@ export const IndicatorBrief = (props: IndicatorBriefProps) => { +
    + +
    } /> )} diff --git a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx index 7f41699adfa..aa079409df7 100644 --- a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx +++ b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx @@ -39,9 +39,11 @@ export const IndicatorProcessing = (props: IndicatorProcessingProps) => { Notes on our processing step for this indicator

- +

+ +

)} diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx index b5aee426b58..13570124175 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx @@ -51,7 +51,7 @@ const SourceContent = (props: { source: OriginSubset }) => { return (
{source.description && ( -

+

)} diff --git a/site/DataPageContent.scss b/site/DataPageContent.scss index d4cedc45448..a790f80cb1f 100644 --- a/site/DataPageContent.scss +++ b/site/DataPageContent.scss @@ -387,4 +387,13 @@ .wp-code-snippet { margin-bottom: 16px; } + + .simple-markdown-text { + @include body-3-medium; + + a { + @include owid-link-60; + color: inherit; + } + } } From 91b3a7bfe810118806417153bcaaf2e9a3afd569 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Thu, 26 Oct 2023 13:04:20 +0000 Subject: [PATCH 08/32] fix: remove debug code --- .../components/src/IndicatorBrief/IndicatorBrief.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx index b059daea7fe..ab2c416a4e8 100644 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx +++ b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx @@ -23,7 +23,6 @@ interface IndicatorBriefProps { } export const IndicatorBrief = (props: IndicatorBriefProps) => { - props = { ...props, unit: undefined } const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) return ( From c651a98e6c50c172d32583e5dedfe8a39b6237f1 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Thu, 26 Oct 2023 14:17:00 +0000 Subject: [PATCH 09/32] refactor(datapage): split IndicatorBrief into two components --- .../src/IndicatorBrief/IndicatorBrief.scss | 98 ----------- .../src/IndicatorBrief/IndicatorBrief.tsx | 156 ------------------ .../IndicatorKeyData/IndicatorKeyData.scss | 37 +++++ .../src/IndicatorKeyData/IndicatorKeyData.tsx | 60 +++++++ .../IndicatorKeyDescription.scss | 40 +++++ .../IndicatorKeyDescription.tsx | 81 +++++++++ .../@ourworldindata/components/src/index.ts | 5 +- site/DataPageContent.scss | 20 +++ site/DataPageV2Content.tsx | 40 ++++- site/owid.scss | 3 +- 10 files changed, 273 insertions(+), 267 deletions(-) delete mode 100644 packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss delete mode 100644 packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx create mode 100644 packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss create mode 100644 packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx create mode 100644 packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss create mode 100644 packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss deleted file mode 100644 index 0d50138c958..00000000000 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss +++ /dev/null @@ -1,98 +0,0 @@ -.indicator-brief { - .about-this-data { - margin-bottom: 32px; - - &__heading { - @include h2-bold; - margin: 0 0 16px; - } - - &__indicator-title { - @include h5-black-caps; - color: $blue-50; - margin: 0 0 8px; - } - - &__indicator-description { - @include body-2-regular; - margin: 0 0 16px; - } - } - - .key-data { - @include body-3-medium; - border-bottom: 1px solid $blue-20; - - display: grid; - grid-template-columns: repeat(4, 1fr); - - @include sm-only { - grid-template-columns: max-content 1fr; - } - - &__title, - &__content { - padding: 16px 0; - border-top: 1px solid $blue-20; - - &.empty { - @include sm-only { - display: none; - } - } - } - - &__title { - color: $blue-50; - padding-right: 24px; - } - - &__content-source { - grid-column: 2 / -1; - } - - a { - @include owid-link-90; - color: inherit; - } - } - - .key-info { - background-color: $gray-10; - border-left: 4px solid $blue-10; - padding: 40px; - margin: 0 -40px 32px -40px; - - &__title { - @include h5-black-caps; - color: $blue-50; - margin-top: 0; - margin-bottom: 16px; - } - - &__content { - @include body-2-regular; - ul { - @include body-2-regular; - margin-bottom: 16px; - margin-left: 16px; - - li { - margin-bottom: 1em; - - &:last-child { - margin-bottom: 0; - } - } - } - } - - &__learn-more { - @include expandable-paragraph__expand-button--full; - svg { - font-size: 0.75em; - margin-left: 12px; - } - } - } -} diff --git a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx b/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx deleted file mode 100644 index ab2c416a4e8..00000000000 --- a/packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import React from "react" -import { faArrowDown } from "@fortawesome/free-solid-svg-icons/faArrowDown" -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js" -import { ExpandableToggle } from "../ExpandableToggle/ExpandableToggle.js" -import { SimpleMarkdownText } from "../SimpleMarkdownText.js" -import { dayjs } from "@ourworldindata/utils" -import { DATAPAGE_SOURCES_AND_PROCESSING_SECTION_ID } from "../SharedDataPageConstants.js" - -interface IndicatorBriefProps { - title: string - descriptionShort?: string - descriptionKey?: string[] - hasFaqEntries: boolean - descriptionFromProducer?: string - attributionShort?: string - attribution: string - processedAdapted: string - dateRange?: string - lastUpdated: string - nextUpdate?: string - additionalInfo?: string - unit?: string -} - -export const IndicatorBrief = (props: IndicatorBriefProps) => { - const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) - const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) - return ( - <> -
-
-

- About this data -

- {props.descriptionShort && ( - <> -
- {props.title} -
-

- -

- - )} -
-
Source
-
- {props.attribution} – with{" "} - - {props.processedAdapted} - {" "} - by Our World In Data -
-
Last updated
-
- {lastUpdated.format("MMMM D, YYYY")} -
- {props.nextUpdate && ( - <> -
- Next expected update -
-
- {props.nextUpdate} -
- - )} -
Date range
-
- {props.dateRange} -
- {props.unit && ( - <> -
Unit
-
- {props.unit} -
- - )} - {/* needed for its top-border */} - {keyDataCount % 2 === 0 && ( - <> -
-
- - )} -
-
- {props.descriptionKey && ( -
-

- What you should know about this indicator -

-
- {props.descriptionKey.length === 1 ? ( - - ) : ( -
    - {props.descriptionKey.map((item, i) => ( -
  • - {" "} -
  • - ))} -
- )} -
- {props.hasFaqEntries && ( - - Learn more in the FAQs - - - )} -
- )} - {props.descriptionFromProducer && ( - - -
- } - isExpandedDefault={ - !(props.descriptionShort || props.descriptionKey) - } - isStacked={!!props.additionalInfo} - /> - )} - {props.additionalInfo && ( - - -
- } - /> - )} -
- - ) -} diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss new file mode 100644 index 00000000000..ede10bbf7d1 --- /dev/null +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss @@ -0,0 +1,37 @@ +.indicator-key-data { + @include body-3-medium; + border-bottom: 1px solid $blue-20; + + display: grid; + grid-template-columns: repeat(4, 1fr); + + @include sm-only { + grid-template-columns: max-content 1fr; + } + + &__title, + &__content { + padding: 16px 0; + border-top: 1px solid $blue-20; + + &.empty { + @include sm-only { + display: none; + } + } + } + + &__title { + color: $blue-50; + padding-right: 24px; + } + + &__content-source { + grid-column: 2 / -1; + } + + a { + @include owid-link-90; + color: inherit; + } +} diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx new file mode 100644 index 00000000000..3ef9d8094f3 --- /dev/null +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx @@ -0,0 +1,60 @@ +import React from "react" +import { dayjs } from "@ourworldindata/utils" +import { DATAPAGE_SOURCES_AND_PROCESSING_SECTION_ID } from "../SharedDataPageConstants.js" + +interface IndicatorKeyDataProps { + attribution: string + processedAdapted: string + dateRange?: string + lastUpdated: string + nextUpdate?: string + unit?: string +} + +export const IndicatorKeyData = (props: IndicatorKeyDataProps) => { + const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) + const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) + return ( +
+
Source
+
+ {props.attribution} – with{" "} + + {props.processedAdapted} + {" "} + by Our World In Data +
+
Last updated
+
+ {lastUpdated.format("MMMM D, YYYY")} +
+ {props.nextUpdate && ( + <> +
+ Next expected update +
+
+ {props.nextUpdate} +
+ + )} +
Date range
+
{props.dateRange}
+ {props.unit && ( + <> +
Unit
+
+ {props.unit} +
+ + )} + {/* needed for its top-border */} + {keyDataCount % 2 === 0 && ( + <> +
+
+ + )} +
+ ) +} diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss new file mode 100644 index 00000000000..3098a57b465 --- /dev/null +++ b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss @@ -0,0 +1,40 @@ +.indicator-key-description { + .key-info { + background-color: $gray-10; + border-left: 4px solid $blue-10; + padding: 40px; + margin: 0 -40px 32px -40px; + + &__title { + @include h5-black-caps; + color: $blue-50; + margin-top: 0; + margin-bottom: 16px; + } + + &__content { + @include body-2-regular; + ul { + @include body-2-regular; + margin-bottom: 16px; + margin-left: 16px; + + li { + margin-bottom: 1em; + + &:last-child { + margin-bottom: 0; + } + } + } + } + + &__learn-more { + @include expandable-paragraph__expand-button--full; + svg { + font-size: 0.75em; + margin-left: 12px; + } + } + } +} diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx new file mode 100644 index 00000000000..3c1c6c29987 --- /dev/null +++ b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx @@ -0,0 +1,81 @@ +import React from "react" +import { faArrowDown } from "@fortawesome/free-solid-svg-icons/faArrowDown" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js" +import { ExpandableToggle } from "../ExpandableToggle/ExpandableToggle.js" +import { SimpleMarkdownText } from "../SimpleMarkdownText.js" + +interface IndicatorKeyDescriptionProps { + descriptionShort?: string + descriptionKey?: string[] + descriptionFromProducer?: string + attributionShort?: string + additionalInfo?: string + hasFaqEntries: boolean +} + +export const IndicatorKeyDescription = ( + props: IndicatorKeyDescriptionProps +) => { + return ( +
+ {props.descriptionKey && ( +
+

+ What you should know about this indicator +

+
+ {props.descriptionKey.length === 1 ? ( + + ) : ( +
    + {props.descriptionKey.map((item, i) => ( +
  • + {" "} +
  • + ))} +
+ )} +
+ {props.hasFaqEntries && ( + + Learn more in the FAQs + + + )} +
+ )} + {props.descriptionFromProducer && ( + + +
+ } + isExpandedDefault={ + !(props.descriptionShort || props.descriptionKey) + } + isStacked={!!props.additionalInfo} + /> + )} + {props.additionalInfo && ( + + +
+ } + /> + )} +
+ ) +} diff --git a/packages/@ourworldindata/components/src/index.ts b/packages/@ourworldindata/components/src/index.ts index 91c4e1491fa..f8874d58ce5 100644 --- a/packages/@ourworldindata/components/src/index.ts +++ b/packages/@ourworldindata/components/src/index.ts @@ -15,12 +15,11 @@ export { export { ExpandableToggle } from "./ExpandableToggle/ExpandableToggle.js" -export { IndicatorBrief } from "./IndicatorBrief/IndicatorBrief.js" - +export { IndicatorKeyData } from "./IndicatorKeyData/IndicatorKeyData.js" +export { IndicatorKeyDescription } from "./IndicatorKeyDescription/IndicatorKeyDescription.js" export { IndicatorProcessing } from "./IndicatorProcessing/IndicatorProcessing.js" export { Checkbox } from "./Checkbox.js" - export { IndicatorSources, type OriginSubset, diff --git a/site/DataPageContent.scss b/site/DataPageContent.scss index a790f80cb1f..a7cfef0581e 100644 --- a/site/DataPageContent.scss +++ b/site/DataPageContent.scss @@ -156,6 +156,26 @@ } } + .about-this-data { + margin-bottom: 32px; + } + + .about-this-data__heading { + @include h2-bold; + margin: 0 0 16px; + } + + .about-this-data__indicator-title { + @include h5-black-caps; + color: $blue-50; + margin: 0 0 8px; + } + + .about-this-data__indicator-description { + @include body-2-regular; + margin: 0 0 16px; + } + .related-research__title { @include datapage-section-title; @include lg-up { diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx index 34a0724d9dc..d59299a2542 100644 --- a/site/DataPageV2Content.tsx +++ b/site/DataPageV2Content.tsx @@ -1,13 +1,15 @@ import React, { useEffect } from "react" import { Grapher, GrapherInterface } from "@ourworldindata/grapher" import { - IndicatorBrief, + IndicatorKeyData, + IndicatorKeyDescription, CodeSnippet, REUSE_THIS_WORK_SECTION_ID, OriginSubset, IndicatorSources, DATAPAGE_SOURCES_AND_PROCESSING_SECTION_ID, IndicatorProcessing, + SimpleMarkdownText, } from "@ourworldindata/components" import ReactDOM from "react-dom" import { GrapherWithFallback } from "./GrapherWithFallback.js" @@ -284,8 +286,34 @@ export const DataPageV2Content = ({ />
- +

+ About this data +

+ {datapageData.descriptionShort && ( + <> +
+ {datapageData.title} +
+

+ +

+ + )} + +
+
diff --git a/site/owid.scss b/site/owid.scss index b25b3e050b0..37aa5ae644d 100644 --- a/site/owid.scss +++ b/site/owid.scss @@ -27,7 +27,8 @@ @import "../packages/@ourworldindata/components/src/CodeSnippet/code-snippet.scss"; @import "../packages/@ourworldindata/components/src/ExpandableToggle/ExpandableToggle.scss"; -@import "../packages/@ourworldindata/components/src/IndicatorBrief/IndicatorBrief.scss"; +@import "../packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss"; +@import "../packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss"; @import "../packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss"; @import "../packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss"; From 866c2fd5c3620a77d4f4f3b1d43bce9b11161b52 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Thu, 26 Oct 2023 14:34:13 +0000 Subject: [PATCH 10/32] style(datapage): fix small visual glitches --- .../src/IndicatorKeyDescription/IndicatorKeyDescription.scss | 2 +- site/DataPageContent.scss | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss index 3098a57b465..070e4d22ffa 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss +++ b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss @@ -16,7 +16,6 @@ @include body-2-regular; ul { @include body-2-regular; - margin-bottom: 16px; margin-left: 16px; li { @@ -31,6 +30,7 @@ &__learn-more { @include expandable-paragraph__expand-button--full; + margin-top: 24px; svg { font-size: 0.75em; margin-left: 12px; diff --git a/site/DataPageContent.scss b/site/DataPageContent.scss index a7cfef0581e..5797209aa91 100644 --- a/site/DataPageContent.scss +++ b/site/DataPageContent.scss @@ -411,6 +411,11 @@ .simple-markdown-text { @include body-3-medium; + br + span { + margin-top: 8px; + display: inline-block; + } + a { @include owid-link-60; color: inherit; From 3dee2e3a900bfb1f3a0ec10afcca70cf9748a131 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 27 Oct 2023 08:46:28 +0000 Subject: [PATCH 11/32] refactor(datapage): move helper functions to utils --- datapage/Datapage.ts | 23 +--- .../src/IndicatorKeyData/IndicatorKeyData.tsx | 56 +++++++++- packages/@ourworldindata/utils/src/Util.ts | 2 - packages/@ourworldindata/utils/src/index.ts | 9 +- .../utils/src/metadataHelpers.ts | 103 ++++++++++++++++++ site/DataPageContent.scss | 5 - site/DataPageV2Content.tsx | 51 +-------- 7 files changed, 171 insertions(+), 78 deletions(-) create mode 100644 packages/@ourworldindata/utils/src/metadataHelpers.ts diff --git a/datapage/Datapage.ts b/datapage/Datapage.ts index 426e643fae5..cd90b5cf320 100644 --- a/datapage/Datapage.ts +++ b/datapage/Datapage.ts @@ -5,10 +5,10 @@ import { GdocsContentSource, DataPageDataV2, OwidVariableWithSource, - dayjs, gdocIdRegex, - getETLPathComponents, getAttributionFragmentsFromVariable, + getLastUpdatedFromVariable, + getNextUpdateFromVariable, } from "@ourworldindata/utils" import { ExplorerProgram } from "../explorer/ExplorerProgram.js" import { Gdoc } from "../db/model/Gdoc/Gdoc.js" @@ -20,21 +20,8 @@ export const getDatapageDataV2 = async ( ): Promise => { { const processingLevel = variableMetadata.processingLevel ?? "minor" - const version = - getETLPathComponents(variableMetadata.catalogPath ?? "")?.version ?? - "" - let nextUpdate = undefined - if (variableMetadata.updatePeriodDays) { - const date = dayjs(version) - const nextUpdateDate = date.add( - variableMetadata.updatePeriodDays, - "day" - ) - // If the next update date is in the past, we set it to the next month - if (nextUpdateDate.isBefore(dayjs())) - nextUpdate = dayjs().add(1, "month").format("MMMM YYYY") - else nextUpdate = nextUpdateDate.format("MMMM YYYY") - } + const lastUpdated = getLastUpdatedFromVariable(variableMetadata) ?? "" + const nextUpdate = getNextUpdateFromVariable(variableMetadata) const datapageJson: DataPageDataV2 = { status: "draft", title: @@ -54,7 +41,7 @@ export const getDatapageDataV2 = async ( descriptionProcessing: variableMetadata.descriptionProcessing, owidProcessingLevel: processingLevel, dateRange: variableMetadata.timespan ?? "", - lastUpdated: version, + lastUpdated: lastUpdated, nextUpdate: nextUpdate, relatedData: [], allCharts: [], diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx index 3ef9d8094f3..d46bffa7778 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx @@ -4,14 +4,19 @@ import { DATAPAGE_SOURCES_AND_PROCESSING_SECTION_ID } from "../SharedDataPageCon interface IndicatorKeyDataProps { attribution: string - processedAdapted: string - dateRange?: string + dateRange: string lastUpdated: string nextUpdate?: string unit?: string + owidProcessingLevel?: "minor" | "major" } export const IndicatorKeyData = (props: IndicatorKeyDataProps) => { + const processedAdapted = + props.owidProcessingLevel === "minor" + ? `minor processing` + : `major adaptations` + const dateRange = getDateRange(props.dateRange) const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) return ( @@ -20,7 +25,7 @@ export const IndicatorKeyData = (props: IndicatorKeyDataProps) => {
{props.attribution} – with{" "} - {props.processedAdapted} + {processedAdapted} {" "} by Our World In Data
@@ -39,7 +44,7 @@ export const IndicatorKeyData = (props: IndicatorKeyDataProps) => { )}
Date range
-
{props.dateRange}
+
{dateRange}
{props.unit && ( <>
Unit
@@ -58,3 +63,46 @@ export const IndicatorKeyData = (props: IndicatorKeyDataProps) => {
) } + +const getDateRange = (dateRange: string): string | null => { + // This regex matches: + // Beginning of string + // Ignore whitespace + // a named group called start that matches: + // hyphen aka minus + // 1 or more digits + // Ignore whitespace + // hyphen aka minus OR en dash + // Ignore whitespace + // a named group called end that matches: + // hyphen aka minus + // 1 or more digits + // Ignore whitespace + // End of string + const dateRangeRegex = /^\s*(?(-)?\d+)\s*(-|–)\s*(?(-)?\d+)\s*$/ + const match = dateRange.match(dateRangeRegex) + if (match) { + const firstYearString = match.groups?.start + const lastYearString = match.groups?.end + if (!firstYearString || !lastYearString) return null + + const firstYear = parseInt(firstYearString, 10) + const lastYear = parseInt(lastYearString, 10) + let formattedFirstYear + + // if start year is before year 0, add BCE to the end + if (firstYear < 0) formattedFirstYear = `${Math.abs(firstYear)} BCE` + else formattedFirstYear = firstYear + + // if end year is before year 0, add BCE to the end or, if start year is after year 0, add CE to the end + let formattedLastYear + if (lastYear < 0) formattedLastYear = `${Math.abs(lastYear)} BCE` + else if (firstYear < 0) formattedLastYear = `${lastYear} CE` + else formattedLastYear = lastYear + + if (lastYear < 0 || firstYear < 0) + return `${formattedFirstYear} – ${formattedLastYear}` + else return `${formattedFirstYear}–${formattedLastYear}` + } + return null +} diff --git a/packages/@ourworldindata/utils/src/Util.ts b/packages/@ourworldindata/utils/src/Util.ts index c1cf1796c72..40592873614 100644 --- a/packages/@ourworldindata/utils/src/Util.ts +++ b/packages/@ourworldindata/utils/src/Util.ts @@ -166,11 +166,9 @@ import { UserCountryInformation, SpanLink, } from "./owidTypes.js" -import { OwidVariableWithSource } from "./OwidVariable.js" import { PointVector } from "./PointVector.js" import React from "react" import { match, P } from "ts-pattern" -import { OwidOrigin } from "./OwidOrigin.js" export type NoUndefinedValues = { [P in keyof T]: Required> diff --git a/packages/@ourworldindata/utils/src/index.ts b/packages/@ourworldindata/utils/src/index.ts index f5426be6a8e..c69165c5568 100644 --- a/packages/@ourworldindata/utils/src/index.ts +++ b/packages/@ourworldindata/utils/src/index.ts @@ -351,13 +351,18 @@ export { filterValidStringValues, traverseEnrichedSpan, mergePartialGrapherConfigs, + copyToClipboard, +} from "./Util.js" + +export { getOriginAttributionFragments, getAttributionFromVariable, getAttributionFragmentsFromVariable, - copyToClipboard, getETLPathComponents, formatAuthors, -} from "./Util.js" + getLastUpdatedFromVariable, + getNextUpdateFromVariable, +} from "./metadataHelpers.js" export { capitalize, diff --git a/packages/@ourworldindata/utils/src/metadataHelpers.ts b/packages/@ourworldindata/utils/src/metadataHelpers.ts new file mode 100644 index 00000000000..75c1ad54ceb --- /dev/null +++ b/packages/@ourworldindata/utils/src/metadataHelpers.ts @@ -0,0 +1,103 @@ +import { OwidOrigin } from "./OwidOrigin" +import { OwidVariableWithSource } from "./OwidVariable" +import { compact, uniq, last } from "./Util" +import dayjs from "./dayjs.js" + +export function getOriginAttributionFragments( + origins: OwidOrigin[] | undefined +): string[] { + return origins + ? origins.map((origin) => { + const yearPublished = origin.datePublished + ? dayjs(origin.datePublished, ["YYYY", "YYYY-MM-DD"]).year() + : undefined + const yearPublishedString = yearPublished + ? ` (${yearPublished})` + : "" + return ( + origin.attribution ?? + `${origin.producer}${yearPublishedString}` + ) + }) + : [] +} + +export function getAttributionFromVariable( + variable: OwidVariableWithSource +): string { + return getAttributionFragmentsFromVariable(variable).join("; ") +} + +export function getAttributionFragmentsFromVariable( + variable: Pick< + OwidVariableWithSource, + "presentation" | "origins" | "source" + > +): string[] { + if ( + variable.presentation?.attribution && + variable.presentation?.attribution !== "" + ) + return [variable.presentation?.attribution] + const originAttributionFragments = getOriginAttributionFragments( + variable.origins + ) + const sourceName = variable.source?.name + return uniq(compact([sourceName, ...originAttributionFragments])) +} + +interface ETLPathComponents { + channel: string + producer: string + version: string + dataset: string + table: string + indicator: string +} + +export const getETLPathComponents = (path: string): ETLPathComponents => { + const [channel, producer, version, dataset, table, indicator] = + path.split("/") + return { channel, producer, version, dataset, table, indicator } +} + +export const formatAuthors = ({ + authors, + requireMax, + forBibtex, +}: { + authors: string[] + requireMax?: boolean + forBibtex?: boolean +}): string => { + if (requireMax && !authors.includes("Max Roser")) + authors = [...authors, "Max Roser"] + + let authorsText = authors.slice(0, -1).join(forBibtex ? " and " : ", ") + if (authorsText.length === 0) authorsText = authors[0] + else authorsText += ` and ${last(authors)}` + + return authorsText +} + +export const getLastUpdatedFromVariable = ( + variable: Pick +): string | undefined => { + return getETLPathComponents(variable.catalogPath ?? "")?.version +} + +export const getNextUpdateFromVariable = ( + variable: Pick +): string | undefined => { + const lastUpdated = getLastUpdatedFromVariable(variable) + let nextUpdate = undefined + if (variable.updatePeriodDays) { + const date = dayjs(lastUpdated) + const nextUpdateDate = date.add(variable.updatePeriodDays, "day") + // If the next update date is in the past, we set it to the next month + if (nextUpdateDate.isBefore(dayjs())) + nextUpdate = dayjs().add(1, "month").format("MMMM YYYY") + else nextUpdate = nextUpdateDate.format("MMMM YYYY") + } + return nextUpdate +} diff --git a/site/DataPageContent.scss b/site/DataPageContent.scss index 5797209aa91..a7cfef0581e 100644 --- a/site/DataPageContent.scss +++ b/site/DataPageContent.scss @@ -411,11 +411,6 @@ .simple-markdown-text { @include body-3-medium; - br + span { - margin-top: 8px; - display: inline-block; - } - a { @include owid-link-60; color: inherit; diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx index d59299a2542..52ca9c3a417 100644 --- a/site/DataPageV2Content.tsx +++ b/site/DataPageV2Content.tsx @@ -37,49 +37,6 @@ declare global { } export const OWID_DATAPAGE_CONTENT_ROOT_ID = "owid-datapageJson-root" -const getDateRange = (dateRange: string): string | null => { - // This regex matches: - // Beginning of string - // Ignore whitespace - // a named group called start that matches: - // hyphen aka minus - // 1 or more digits - // Ignore whitespace - // hyphen aka minus OR en dash - // Ignore whitespace - // a named group called end that matches: - // hyphen aka minus - // 1 or more digits - // Ignore whitespace - // End of string - const dateRangeRegex = /^\s*(?(-)?\d+)\s*(-|–)\s*(?(-)?\d+)\s*$/ - const match = dateRange.match(dateRangeRegex) - if (match) { - const firstYearString = match.groups?.start - const lastYearString = match.groups?.end - if (!firstYearString || !lastYearString) return null - - const firstYear = parseInt(firstYearString, 10) - const lastYear = parseInt(lastYearString, 10) - let formattedFirstYear - - // if start year is before year 0, add BCE to the end - if (firstYear < 0) formattedFirstYear = `${Math.abs(firstYear)} BCE` - else formattedFirstYear = firstYear - - // if end year is before year 0, add BCE to the end or, if start year is after year 0, add CE to the end - let formattedLastYear - if (lastYear < 0) formattedLastYear = `${Math.abs(lastYear)} BCE` - else if (firstYear < 0) formattedLastYear = `${lastYear} CE` - else formattedLastYear = lastYear - - if (lastYear < 0 || firstYear < 0) - return `${formattedFirstYear} – ${formattedLastYear}` - else return `${formattedFirstYear}–${formattedLastYear}` - } - return null -} - export const slugify_topic = (topic: string) => { // This is a heuristic to map from free form tag texts to topic page URLs. We'll // have to switch to explicitly stored URLs or explicit links between tags and topic pages @@ -188,8 +145,6 @@ export const DataPageV2Content = ({ relatedCharts = [], } = faqEntries ?? {} - const dateRange = getDateRange(datapageData.dateRange) - const citationDatapage = datapageData.primaryTopic ? `“Data Page: ${datapageData.title}”, part of the following publication: ${datapageData.primaryTopic.citation}. Data adapted from ${producers}. Retrieved from ${canonicalUrl} [online resource]` : `“Data Page: ${datapageData.title}”. Our World in Data (${currentYear}). Data adapted from ${producers}. Retrieved from ${canonicalUrl} [online resource]` @@ -306,8 +261,10 @@ export const DataPageV2Content = ({ )} Date: Fri, 27 Oct 2023 10:43:14 +0000 Subject: [PATCH 12/32] refactor: pass canonical url for datapage links --- .../src/IndicatorKeyData/IndicatorKeyData.tsx | 6 +++++- .../IndicatorKeyDescription.tsx | 8 ++++++-- .../src/IndicatorSources/IndicatorSources.tsx | 19 +++++++++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx index d46bffa7778..4e8f1110004 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx @@ -9,9 +9,11 @@ interface IndicatorKeyDataProps { nextUpdate?: string unit?: string owidProcessingLevel?: "minor" | "major" + canonicalUrl?: string } export const IndicatorKeyData = (props: IndicatorKeyDataProps) => { + const canonicalUrl = props.canonicalUrl ?? "" const processedAdapted = props.owidProcessingLevel === "minor" ? `minor processing` @@ -24,7 +26,9 @@ export const IndicatorKeyData = (props: IndicatorKeyDataProps) => {
Source
{props.attribution} – with{" "} - + {processedAdapted} {" "} by Our World In Data diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx index 3c1c6c29987..d3b4ba4866e 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx +++ b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx @@ -10,6 +10,7 @@ interface IndicatorKeyDescriptionProps { descriptionFromProducer?: string attributionShort?: string additionalInfo?: string + canonicalUrl?: string hasFaqEntries: boolean } @@ -21,7 +22,7 @@ export const IndicatorKeyDescription = ( {props.descriptionKey && (

- What you should know about this indicator + What you should know about this data

{props.descriptionKey.length === 1 ? ( @@ -39,7 +40,10 @@ export const IndicatorKeyDescription = ( )}
{props.hasFaqEntries && ( - + Learn more in the FAQs diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx index 13570124175..6ce8ae9d063 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx @@ -17,6 +17,7 @@ export type OriginSubset = Pick< export interface IndicatorSourcesProps { origins: OriginSubset[] + canonicalUrl?: string } export const IndicatorSources = (props: IndicatorSourcesProps) => { @@ -32,7 +33,12 @@ export const IndicatorSources = (props: IndicatorSourcesProps) => { } + content={ + + } isStacked={idx !== sources.length - 1} hasTeaser /> @@ -42,8 +48,11 @@ export const IndicatorSources = (props: IndicatorSourcesProps) => { ) } -const SourceContent = (props: { source: OriginSubset }) => { - const { source } = props +const SourceContent = (props: { + source: OriginSubset + canonicalUrl?: string +}) => { + const { source, canonicalUrl = "" } = props const dateAccessed = source.dateAccessed ? dayjs(source.dateAccessed).format("MMMM D, YYYY") : undefined @@ -87,7 +96,9 @@ const SourceContent = (props: { source: OriginSubset }) => { adaptation by Our World in Data. To cite data downloaded from this page, please use the suggested citation given in{" "} - + Reuse This Work {" "} below. From 894c0f15d27d42f9dcb6c035f5b36f252b74f337 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 27 Oct 2023 10:44:36 +0000 Subject: [PATCH 13/32] style(datapage): update color of key description text --- .../src/IndicatorKeyDescription/IndicatorKeyDescription.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss index 070e4d22ffa..210e0572b08 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss +++ b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss @@ -14,6 +14,7 @@ &__content { @include body-2-regular; + color: $blue-90; ul { @include body-2-regular; margin-left: 16px; From 715b22ef89770bfe25484bf7249d26fa6e9a22fa Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 27 Oct 2023 12:59:58 +0000 Subject: [PATCH 14/32] style(datapage): improve spacing --- .../IndicatorKeyDescription/IndicatorKeyDescription.scss | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss index 210e0572b08..2d73b6aa788 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss +++ b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss @@ -3,7 +3,7 @@ background-color: $gray-10; border-left: 4px solid $blue-10; padding: 40px; - margin: 0 -40px 32px -40px; + margin: 0 -40px; &__title { @include h5-black-caps; @@ -38,4 +38,8 @@ } } } + + .expandable-info-blocks { + margin-top: 32px; + } } From 9902dead9a4d9a495702a1cb72bdfad053f6c358 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 27 Oct 2023 13:16:23 +0000 Subject: [PATCH 15/32] fix(datapage): hide key description if array is empty --- .../IndicatorKeyDescription.tsx | 66 ++++++++++--------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx index d3b4ba4866e..aec23f4727e 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx +++ b/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx @@ -19,7 +19,7 @@ export const IndicatorKeyDescription = ( ) => { return (
- {props.descriptionKey && ( + {props.descriptionKey && props.descriptionKey.length > 0 && (

What you should know about this data @@ -50,36 +50,40 @@ export const IndicatorKeyDescription = ( )}

)} - {props.descriptionFromProducer && ( - - -
- } - isExpandedDefault={ - !(props.descriptionShort || props.descriptionKey) - } - isStacked={!!props.additionalInfo} - /> - )} - {props.additionalInfo && ( - - -
- } - /> - )} +
+ {props.descriptionFromProducer && ( + + +
+ } + isExpandedDefault={ + !(props.descriptionShort || props.descriptionKey) + } + isStacked={!!props.additionalInfo} + /> + )} + {props.additionalInfo && ( + + +
+ } + /> + )} +
) } From 01dcb3f17034d3cdd87ca39efdd48faddb732a41 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 27 Oct 2023 13:17:05 +0000 Subject: [PATCH 16/32] enhance(datapage): deduplciate origins --- .../src/IndicatorSources/IndicatorSources.tsx | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx index 6ce8ae9d063..52ed442be31 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx @@ -1,6 +1,6 @@ import React from "react" import { ExpandableToggle } from "../ExpandableToggle/ExpandableToggle.js" -import { OwidOrigin, dayjs } from "@ourworldindata/utils" +import { OwidOrigin, dayjs, uniqBy } from "@ourworldindata/utils" import { SimpleMarkdownText } from "../SimpleMarkdownText.js" import { CodeSnippet } from "../CodeSnippet/CodeSnippet.js" import { REUSE_THIS_WORK_SECTION_ID } from "../SharedDataPageConstants.js" @@ -21,29 +21,35 @@ export interface IndicatorSourcesProps { } export const IndicatorSources = (props: IndicatorSourcesProps) => { + const origins = props.origins.map((origin) => ({ + ...origin, + label: + origin.producer ?? + origin.descriptionSnapshot ?? + origin.description ?? + "", + })) + const uniqueOrigins = uniqBy( + origins, + (origin) => origin.label + origin.description + ) + return ( <> - {props.origins.map((source, idx: number, sources) => { - const label = - source.producer ?? - source.descriptionSnapshot ?? - source.description ?? - "" - return ( - - } - isStacked={idx !== sources.length - 1} - hasTeaser - /> - ) - })} + {uniqueOrigins.map((source, idx: number, sources) => ( + + } + isStacked={idx !== sources.length - 1} + hasTeaser + /> + ))} ) } From 45dd5ae9521ddd3fada52e4b3882244a92dad910 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 27 Oct 2023 13:33:27 +0000 Subject: [PATCH 17/32] enhance(datapage): show title of data product for a source --- .../src/IndicatorSources/IndicatorSources.tsx | 19 ++++++++++++++----- site/DataPageV2Content.tsx | 1 + 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx index 52ed442be31..7d2e892d9e9 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx @@ -7,6 +7,7 @@ import { REUSE_THIS_WORK_SECTION_ID } from "../SharedDataPageConstants.js" export type OriginSubset = Pick< OwidOrigin, + | "title" | "producer" | "descriptionSnapshot" | "dateAccessed" @@ -23,11 +24,7 @@ export interface IndicatorSourcesProps { export const IndicatorSources = (props: IndicatorSourcesProps) => { const origins = props.origins.map((origin) => ({ ...origin, - label: - origin.producer ?? - origin.descriptionSnapshot ?? - origin.description ?? - "", + label: makeLabel(origin), })) const uniqueOrigins = uniqBy( origins, @@ -119,3 +116,15 @@ const SourceContent = (props: {
) } + +const makeLabel = (origin: OriginSubset) => { + let label = + origin.producer ?? + origin.descriptionSnapshot ?? + origin.description ?? + "" + if (origin.title && origin.title !== label) { + label += " - " + origin.title + } + return label +} diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx index 52ca9c3a417..9711e0d3411 100644 --- a/site/DataPageV2Content.tsx +++ b/site/DataPageV2Content.tsx @@ -104,6 +104,7 @@ export const DataPageV2Content = ({ const origins: OriginSubset[] = uniq( datapageData.origins.map((item) => pick(item, [ + "title", "producer", "descriptionSnapshot", "dateAccessed", From e09b7da8c778b2c079fd3f632e87736cb60d20c5 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 27 Oct 2023 14:20:37 +0000 Subject: [PATCH 18/32] refactor(datapage): rename IndicatorKeyDescription -> IndicatorDescriptions --- .../IndicatorDescriptions.scss} | 0 .../IndicatorDescriptions.tsx} | 6 +++--- packages/@ourworldindata/components/src/index.ts | 2 +- site/DataPageV2Content.tsx | 4 ++-- site/owid.scss | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename packages/@ourworldindata/components/src/{IndicatorKeyDescription/IndicatorKeyDescription.scss => IndicatorDescriptions/IndicatorDescriptions.scss} (100%) rename packages/@ourworldindata/components/src/{IndicatorKeyDescription/IndicatorKeyDescription.tsx => IndicatorDescriptions/IndicatorDescriptions.tsx} (96%) diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.scss similarity index 100% rename from packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.scss rename to packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.scss diff --git a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx similarity index 96% rename from packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx rename to packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx index aec23f4727e..3f57d00fd63 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyDescription/IndicatorKeyDescription.tsx +++ b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx @@ -4,7 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js" import { ExpandableToggle } from "../ExpandableToggle/ExpandableToggle.js" import { SimpleMarkdownText } from "../SimpleMarkdownText.js" -interface IndicatorKeyDescriptionProps { +interface IndicatorDescriptionsProps { descriptionShort?: string descriptionKey?: string[] descriptionFromProducer?: string @@ -14,8 +14,8 @@ interface IndicatorKeyDescriptionProps { hasFaqEntries: boolean } -export const IndicatorKeyDescription = ( - props: IndicatorKeyDescriptionProps +export const IndicatorDescriptions = ( + props: IndicatorDescriptionsProps ) => { return (
diff --git a/packages/@ourworldindata/components/src/index.ts b/packages/@ourworldindata/components/src/index.ts index f8874d58ce5..ed66bbc114d 100644 --- a/packages/@ourworldindata/components/src/index.ts +++ b/packages/@ourworldindata/components/src/index.ts @@ -16,7 +16,7 @@ export { export { ExpandableToggle } from "./ExpandableToggle/ExpandableToggle.js" export { IndicatorKeyData } from "./IndicatorKeyData/IndicatorKeyData.js" -export { IndicatorKeyDescription } from "./IndicatorKeyDescription/IndicatorKeyDescription.js" +export { IndicatorDescriptions } from "./IndicatorDescriptions/IndicatorDescriptions.js" export { IndicatorProcessing } from "./IndicatorProcessing/IndicatorProcessing.js" export { Checkbox } from "./Checkbox.js" diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx index 9711e0d3411..9b8cf0f4d37 100644 --- a/site/DataPageV2Content.tsx +++ b/site/DataPageV2Content.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from "react" import { Grapher, GrapherInterface } from "@ourworldindata/grapher" import { IndicatorKeyData, - IndicatorKeyDescription, + IndicatorDescriptions, CodeSnippet, REUSE_THIS_WORK_SECTION_ID, OriginSubset, @@ -271,7 +271,7 @@ export const DataPageV2Content = ({ unit={datapageData.unit} />
- Date: Fri, 27 Oct 2023 14:44:54 +0000 Subject: [PATCH 19/32] enhance(datapage): deduplicate sources on label only --- .../src/IndicatorDescriptions/IndicatorDescriptions.tsx | 4 +--- .../components/src/IndicatorSources/IndicatorSources.tsx | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx index 3f57d00fd63..b05dae48064 100644 --- a/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx +++ b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx @@ -14,9 +14,7 @@ interface IndicatorDescriptionsProps { hasFaqEntries: boolean } -export const IndicatorDescriptions = ( - props: IndicatorDescriptionsProps -) => { +export const IndicatorDescriptions = (props: IndicatorDescriptionsProps) => { return (
{props.descriptionKey && props.descriptionKey.length > 0 && ( diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx index 7d2e892d9e9..7e17243dd54 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx @@ -26,10 +26,7 @@ export const IndicatorSources = (props: IndicatorSourcesProps) => { ...origin, label: makeLabel(origin), })) - const uniqueOrigins = uniqBy( - origins, - (origin) => origin.label + origin.description - ) + const uniqueOrigins = uniqBy(origins, "label") return ( <> From 37d1d8b1a590573ac6cde1347afc1ac6c612fa8e Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Fri, 27 Oct 2023 15:09:49 +0000 Subject: [PATCH 20/32] style(datapage) add icon; fix small visual glitches --- .../IndicatorDescriptions/IndicatorDescriptions.scss | 1 - .../src/IndicatorProcessing/IndicatorProcessing.scss | 10 ++++++++++ .../src/IndicatorProcessing/IndicatorProcessing.tsx | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.scss b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.scss index 2d73b6aa788..74a3ba0141e 100644 --- a/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.scss +++ b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.scss @@ -14,7 +14,6 @@ &__content { @include body-2-regular; - color: $blue-90; ul { @include body-2-regular; margin-left: 16px; diff --git a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss index dbf36182a44..5a3cae4946f 100644 --- a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss +++ b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.scss @@ -11,6 +11,12 @@ &__link { @include expandable-paragraph__expand-button--full; + + svg { + display: none; // used in Grapher's sources modal + font-size: 0.75em; + margin-left: 12px; + } } } @@ -37,6 +43,10 @@ @include body-3-medium; } + > *:first-child { + margin-top: 0; + } + > *:last-child { margin-bottom: 0; } diff --git a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx index aa079409df7..fc96adb440d 100644 --- a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx +++ b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx @@ -1,5 +1,7 @@ import React from "react" import { SimpleMarkdownText } from "../SimpleMarkdownText.js" +import { faArrowDown } from "@fortawesome/free-solid-svg-icons/faArrowDown" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js" export interface IndicatorProcessingProps { descriptionProcessing: string | undefined @@ -32,6 +34,7 @@ export const IndicatorProcessing = (props: IndicatorProcessingProps) => { className="data-processing__link" > Read about our data pipeline + {props.descriptionProcessing && (
From 35f17a317142729aa782f4e698f808af7272fb88 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Mon, 30 Oct 2023 08:52:56 +0000 Subject: [PATCH 21/32] refactor: move phrase for procssing level into utils folder --- datapage/Datapage.ts | 4 +++- db/model/Variable.ts | 3 ++- .../src/IndicatorKeyData/IndicatorKeyData.tsx | 15 +++++++++------ .../@ourworldindata/utils/src/OwidVariable.ts | 7 ++++++- packages/@ourworldindata/utils/src/index.ts | 2 ++ .../@ourworldindata/utils/src/metadataHelpers.ts | 6 +++++- packages/@ourworldindata/utils/src/owidTypes.ts | 3 ++- site/DataPageV2Content.tsx | 8 ++++---- 8 files changed, 33 insertions(+), 15 deletions(-) diff --git a/datapage/Datapage.ts b/datapage/Datapage.ts index cd90b5cf320..929b51ae254 100644 --- a/datapage/Datapage.ts +++ b/datapage/Datapage.ts @@ -9,6 +9,7 @@ import { getAttributionFragmentsFromVariable, getLastUpdatedFromVariable, getNextUpdateFromVariable, + OwidProcessingLevel, } from "@ourworldindata/utils" import { ExplorerProgram } from "../explorer/ExplorerProgram.js" import { Gdoc } from "../db/model/Gdoc/Gdoc.js" @@ -19,7 +20,8 @@ export const getDatapageDataV2 = async ( partialGrapherConfig: GrapherInterface ): Promise => { { - const processingLevel = variableMetadata.processingLevel ?? "minor" + const processingLevel = + variableMetadata.processingLevel ?? OwidProcessingLevel.minor const lastUpdated = getLastUpdatedFromVariable(variableMetadata) ?? "" const nextUpdate = getNextUpdateFromVariable(variableMetadata) const datapageJson: DataPageDataV2 = { diff --git a/db/model/Variable.ts b/db/model/Variable.ts index f1c7e2653b6..a1754f65df7 100644 --- a/db/model/Variable.ts +++ b/db/model/Variable.ts @@ -13,6 +13,7 @@ import { OwidVariableId, retryPromise, OwidLicense, + OwidProcessingLevel, } from "@ourworldindata/utils" import { GrapherInterface, @@ -41,7 +42,7 @@ export interface VariableRow { catalogPath?: string dimensions?: Dimensions schemaVersion?: number - processingLevel?: "minor" | "major" + processingLevel?: OwidProcessingLevel titlePublic?: string titleVariant?: string attributionShort?: string diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx index 4e8f1110004..ecc11db9e6a 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx @@ -1,5 +1,9 @@ import React from "react" -import { dayjs } from "@ourworldindata/utils" +import { + dayjs, + OwidProcessingLevel, + getPhraseForProcessingLevel, +} from "@ourworldindata/utils" import { DATAPAGE_SOURCES_AND_PROCESSING_SECTION_ID } from "../SharedDataPageConstants.js" interface IndicatorKeyDataProps { @@ -8,16 +12,15 @@ interface IndicatorKeyDataProps { lastUpdated: string nextUpdate?: string unit?: string - owidProcessingLevel?: "minor" | "major" + owidProcessingLevel?: OwidProcessingLevel canonicalUrl?: string } export const IndicatorKeyData = (props: IndicatorKeyDataProps) => { const canonicalUrl = props.canonicalUrl ?? "" - const processedAdapted = - props.owidProcessingLevel === "minor" - ? `minor processing` - : `major adaptations` + const processedAdapted = getPhraseForProcessingLevel( + props.owidProcessingLevel ?? OwidProcessingLevel.minor + ) const dateRange = getDateRange(props.dateRange) const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) diff --git a/packages/@ourworldindata/utils/src/OwidVariable.ts b/packages/@ourworldindata/utils/src/OwidVariable.ts index 5d6974ee85e..45a75ba30ce 100644 --- a/packages/@ourworldindata/utils/src/OwidVariable.ts +++ b/packages/@ourworldindata/utils/src/OwidVariable.ts @@ -69,7 +69,7 @@ export interface OwidVariableWithSource { source?: OwidSource origins?: OwidOrigin[] schemaVersion?: number - processingLevel?: "minor" | "major" + processingLevel?: OwidProcessingLevel presentation?: OwidVariablePresentation shortName?: string timespan?: string @@ -100,6 +100,11 @@ export interface OwidVariablePresentation { faqs?: FaqLink[] } +export enum OwidProcessingLevel { + minor = "minor", + major = "major", +} + export interface FaqLink { gdocId: string fragmentId: string diff --git a/packages/@ourworldindata/utils/src/index.ts b/packages/@ourworldindata/utils/src/index.ts index c69165c5568..ae60f53a0ec 100644 --- a/packages/@ourworldindata/utils/src/index.ts +++ b/packages/@ourworldindata/utils/src/index.ts @@ -362,6 +362,7 @@ export { formatAuthors, getLastUpdatedFromVariable, getNextUpdateFromVariable, + getPhraseForProcessingLevel, } from "./metadataHelpers.js" export { @@ -512,6 +513,7 @@ export { type OwidVariablePresentation, type OwidEntityKey, type OwidLicense, + OwidProcessingLevel, } from "./OwidVariable.js" export { diff --git a/packages/@ourworldindata/utils/src/metadataHelpers.ts b/packages/@ourworldindata/utils/src/metadataHelpers.ts index 75c1ad54ceb..3e53e8638d2 100644 --- a/packages/@ourworldindata/utils/src/metadataHelpers.ts +++ b/packages/@ourworldindata/utils/src/metadataHelpers.ts @@ -1,5 +1,5 @@ import { OwidOrigin } from "./OwidOrigin" -import { OwidVariableWithSource } from "./OwidVariable" +import { OwidProcessingLevel, OwidVariableWithSource } from "./OwidVariable" import { compact, uniq, last } from "./Util" import dayjs from "./dayjs.js" @@ -101,3 +101,7 @@ export const getNextUpdateFromVariable = ( } return nextUpdate } + +export const getPhraseForProcessingLevel = ( + processingLevel: OwidProcessingLevel +) => (processingLevel === "major" ? "major adaptations" : "minor processing") diff --git a/packages/@ourworldindata/utils/src/owidTypes.ts b/packages/@ourworldindata/utils/src/owidTypes.ts index ff9afaceae3..230bb0d78d6 100644 --- a/packages/@ourworldindata/utils/src/owidTypes.ts +++ b/packages/@ourworldindata/utils/src/owidTypes.ts @@ -3,6 +3,7 @@ import { Static, Type } from "@sinclair/typebox" import { gdocUrlRegex } from "./GdocsConstants.js" import { OwidOrigin } from "./OwidOrigin.js" import { OwidSource } from "./OwidSource.js" +import { OwidProcessingLevel } from "./OwidVariable.js" // todo: remove when we ditch Year and YearIsDay export const EPOCH_DATE = "2020-01-21" @@ -1589,7 +1590,7 @@ export interface DataPageDataV2 { faqs: FaqLink[] // Todo: resolve these at this level to the point where we can preview them descriptionKey: string[] descriptionProcessing?: string - owidProcessingLevel: "minor" | "major" + owidProcessingLevel: OwidProcessingLevel dateRange: string lastUpdated: string nextUpdate?: string diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx index 9b8cf0f4d37..8b55e1700b4 100644 --- a/site/DataPageV2Content.tsx +++ b/site/DataPageV2Content.tsx @@ -22,6 +22,7 @@ import { pick, formatAuthors, intersection, + getPhraseForProcessingLevel, } from "@ourworldindata/utils" import { AttachmentsContext, DocumentContext } from "./gdocs/OwidGdoc.js" import StickyNav from "./blocks/StickyNav.js" @@ -122,10 +123,9 @@ export const DataPageV2Content = ({ ? `${attributionFragments[0]} and other sources` : attributionFragments.join(", ") const attributionUnshortened = attributionFragments.join(", ") - const processedAdapted = - datapageData.owidProcessingLevel === "minor" - ? `minor processing` - : `major adaptations` + const processedAdapted = getPhraseForProcessingLevel( + datapageData.owidProcessingLevel + ) const lastUpdated = dayjs(datapageData.lastUpdated, ["YYYY", "YYYY-MM-DD"]) const yearOfUpdate = lastUpdated.year() const citationShort = `${attributionPotentiallyShortened} – with ${processedAdapted} by Our World In Data (${yearOfUpdate})` From 68561d20611ba9bceacfe8462a98409be94fb1b2 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Mon, 30 Oct 2023 09:35:11 +0000 Subject: [PATCH 22/32] chore: make eslint happy --- packages/@ourworldindata/utils/src/metadataHelpers.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/@ourworldindata/utils/src/metadataHelpers.ts b/packages/@ourworldindata/utils/src/metadataHelpers.ts index 3e53e8638d2..c3c73921d93 100644 --- a/packages/@ourworldindata/utils/src/metadataHelpers.ts +++ b/packages/@ourworldindata/utils/src/metadataHelpers.ts @@ -104,4 +104,5 @@ export const getNextUpdateFromVariable = ( export const getPhraseForProcessingLevel = ( processingLevel: OwidProcessingLevel -) => (processingLevel === "major" ? "major adaptations" : "minor processing") +): string => + processingLevel === "major" ? "major adaptations" : "minor processing" From 3f2fad1ec40d5d7a4f67c32eed2f37a0f4d937b3 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Mon, 30 Oct 2023 17:10:15 +0000 Subject: [PATCH 23/32] refactor: use a type union for OwidProcessingLevel --- datapage/Datapage.ts | 2 +- .../components/src/IndicatorKeyData/IndicatorKeyData.tsx | 2 +- packages/@ourworldindata/utils/src/OwidVariable.ts | 5 +---- packages/@ourworldindata/utils/src/index.ts | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/datapage/Datapage.ts b/datapage/Datapage.ts index 929b51ae254..e61b29bb944 100644 --- a/datapage/Datapage.ts +++ b/datapage/Datapage.ts @@ -21,7 +21,7 @@ export const getDatapageDataV2 = async ( ): Promise => { { const processingLevel = - variableMetadata.processingLevel ?? OwidProcessingLevel.minor + variableMetadata.processingLevel ?? "minor" const lastUpdated = getLastUpdatedFromVariable(variableMetadata) ?? "" const nextUpdate = getNextUpdateFromVariable(variableMetadata) const datapageJson: DataPageDataV2 = { diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx index ecc11db9e6a..a882ffdef59 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx @@ -19,7 +19,7 @@ interface IndicatorKeyDataProps { export const IndicatorKeyData = (props: IndicatorKeyDataProps) => { const canonicalUrl = props.canonicalUrl ?? "" const processedAdapted = getPhraseForProcessingLevel( - props.owidProcessingLevel ?? OwidProcessingLevel.minor + props.owidProcessingLevel ?? "minor" ) const dateRange = getDateRange(props.dateRange) const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) diff --git a/packages/@ourworldindata/utils/src/OwidVariable.ts b/packages/@ourworldindata/utils/src/OwidVariable.ts index 45a75ba30ce..5b7bbf4df66 100644 --- a/packages/@ourworldindata/utils/src/OwidVariable.ts +++ b/packages/@ourworldindata/utils/src/OwidVariable.ts @@ -100,10 +100,7 @@ export interface OwidVariablePresentation { faqs?: FaqLink[] } -export enum OwidProcessingLevel { - minor = "minor", - major = "major", -} +export type OwidProcessingLevel = 'minor' | 'major' export interface FaqLink { gdocId: string diff --git a/packages/@ourworldindata/utils/src/index.ts b/packages/@ourworldindata/utils/src/index.ts index ae60f53a0ec..60ee5625f95 100644 --- a/packages/@ourworldindata/utils/src/index.ts +++ b/packages/@ourworldindata/utils/src/index.ts @@ -513,7 +513,7 @@ export { type OwidVariablePresentation, type OwidEntityKey, type OwidLicense, - OwidProcessingLevel, + type OwidProcessingLevel, } from "./OwidVariable.js" export { From 73efe5222f821daf215d0f614bd31aed1fa6351d Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Mon, 30 Oct 2023 17:29:32 +0000 Subject: [PATCH 24/32] chore: make eslint happy --- datapage/Datapage.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/datapage/Datapage.ts b/datapage/Datapage.ts index e61b29bb944..cd90b5cf320 100644 --- a/datapage/Datapage.ts +++ b/datapage/Datapage.ts @@ -9,7 +9,6 @@ import { getAttributionFragmentsFromVariable, getLastUpdatedFromVariable, getNextUpdateFromVariable, - OwidProcessingLevel, } from "@ourworldindata/utils" import { ExplorerProgram } from "../explorer/ExplorerProgram.js" import { Gdoc } from "../db/model/Gdoc/Gdoc.js" @@ -20,8 +19,7 @@ export const getDatapageDataV2 = async ( partialGrapherConfig: GrapherInterface ): Promise => { { - const processingLevel = - variableMetadata.processingLevel ?? "minor" + const processingLevel = variableMetadata.processingLevel ?? "minor" const lastUpdated = getLastUpdatedFromVariable(variableMetadata) ?? "" const nextUpdate = getNextUpdateFromVariable(variableMetadata) const datapageJson: DataPageDataV2 = { From ddf4596e4289552681061eb0cfc9eb5071230673 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Mon, 30 Oct 2023 17:31:30 +0000 Subject: [PATCH 25/32] chore: run prettier --- packages/@ourworldindata/utils/src/OwidVariable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ourworldindata/utils/src/OwidVariable.ts b/packages/@ourworldindata/utils/src/OwidVariable.ts index 5b7bbf4df66..79d51e4ef57 100644 --- a/packages/@ourworldindata/utils/src/OwidVariable.ts +++ b/packages/@ourworldindata/utils/src/OwidVariable.ts @@ -100,7 +100,7 @@ export interface OwidVariablePresentation { faqs?: FaqLink[] } -export type OwidProcessingLevel = 'minor' | 'major' +export type OwidProcessingLevel = "minor" | "major" export interface FaqLink { gdocId: string From c950652e57a1f289354b2b4505e08a63e82ad6e0 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Tue, 31 Oct 2023 12:13:55 +0000 Subject: [PATCH 26/32] enhance(data-page): improve key data on mobile --- .../IndicatorKeyData/IndicatorKeyData.scss | 40 ++++++------ .../src/IndicatorKeyData/IndicatorKeyData.tsx | 62 +++++++++++-------- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss index ede10bbf7d1..aac002f9cdb 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.scss @@ -1,33 +1,37 @@ .indicator-key-data { @include body-3-medium; + + border-top: 1px solid $blue-20; border-bottom: 1px solid $blue-20; display: grid; - grid-template-columns: repeat(4, 1fr); + grid-template-columns: repeat(2, 1fr); - @include sm-only { - grid-template-columns: max-content 1fr; - } + .indicator-key-data-item { + display: flex; + padding: 16px 24px 16px 0; + + @include sm-only { + display: block; + } + + + .indicator-key-data-item { + border-top: 1px solid $blue-20; + } - &__title, - &__content { - padding: 16px 0; - border-top: 1px solid $blue-20; + &__title { + flex: 0 0 140px; // using a fixed width here to make sure the content is aligned + margin-right: 24px; + color: $blue-50; - &.empty { @include sm-only { - display: none; + margin-right: 0; } } - } - &__title { - color: $blue-50; - padding-right: 24px; - } - - &__content-source { - grid-column: 2 / -1; + &--span { + grid-column: 1 / -1; + } } a { diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx index a882ffdef59..0acf7c03686 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx @@ -26,46 +26,56 @@ export const IndicatorKeyData = (props: IndicatorKeyDataProps) => { const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) return (
-
Source
-
- {props.attribution} – with{" "} - - {processedAdapted} - {" "} - by Our World In Data +
+
Source
+
+ {props.attribution} – with{" "} + + {processedAdapted} + {" "} + by Our World In Data +
-
Last updated
-
- {lastUpdated.format("MMMM D, YYYY")} +
+
+ Last updated +
+
+ {lastUpdated.format("MMMM D, YYYY")} +
{props.nextUpdate && ( - <> -
+
+
Next expected update
-
+
{props.nextUpdate}
- +
)} -
Date range
-
{dateRange}
+
+
Date range
+
+ {dateRange} +
+
{props.unit && ( - <> -
Unit
-
+
+
Unit
+
{props.unit}
- +
)} {/* needed for its top-border */} {keyDataCount % 2 === 0 && ( - <> -
-
- +
+
+
+
)}
) From b07193bfa3dbc8226817009a867785b9c449714a Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Tue, 31 Oct 2023 12:40:15 +0000 Subject: [PATCH 27/32] enhance(data-page): show dataPublishedBy instead of the source's name --- packages/@ourworldindata/utils/src/metadataHelpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@ourworldindata/utils/src/metadataHelpers.ts b/packages/@ourworldindata/utils/src/metadataHelpers.ts index c3c73921d93..45055696003 100644 --- a/packages/@ourworldindata/utils/src/metadataHelpers.ts +++ b/packages/@ourworldindata/utils/src/metadataHelpers.ts @@ -42,8 +42,8 @@ export function getAttributionFragmentsFromVariable( const originAttributionFragments = getOriginAttributionFragments( variable.origins ) - const sourceName = variable.source?.name - return uniq(compact([sourceName, ...originAttributionFragments])) + const dataPublishedBy = variable.source?.dataPublishedBy + return uniq(compact([dataPublishedBy, ...originAttributionFragments])) } interface ETLPathComponents { From c5d6c2ee00ace9dd7efc095bd7495b1fb23ecf98 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Tue, 31 Oct 2023 13:37:57 +0000 Subject: [PATCH 28/32] enhance(data-page): allow orphan cells in the key data block to take up all available space --- .../src/IndicatorKeyData/IndicatorKeyData.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx index 0acf7c03686..34460a12663 100644 --- a/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx +++ b/packages/@ourworldindata/components/src/IndicatorKeyData/IndicatorKeyData.tsx @@ -1,4 +1,5 @@ import React from "react" +import cx from "classnames" import { dayjs, OwidProcessingLevel, @@ -23,7 +24,6 @@ export const IndicatorKeyData = (props: IndicatorKeyDataProps) => { ) const dateRange = getDateRange(props.dateRange) const lastUpdated = dayjs(props.lastUpdated, ["YYYY", "YYYY-MM-DD"]) - const keyDataCount = 3 + (props.nextUpdate ? 1 : 0) + (props.unit ? 1 : 0) return (
@@ -56,27 +56,29 @@ export const IndicatorKeyData = (props: IndicatorKeyDataProps) => {
)} -
+
Date range
{dateRange}
{props.unit && ( -
+
Unit
{props.unit}
)} - {/* needed for its top-border */} - {keyDataCount % 2 === 0 && ( -
-
-
-
- )}
) } From e0dec5712bd6fb300e82ba8aa208e82041110b79 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Wed, 1 Nov 2023 09:14:42 +0000 Subject: [PATCH 29/32] style(data-page): remove padding of expandable toggle --- .../components/src/ExpandableToggle/ExpandableToggle.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@ourworldindata/components/src/ExpandableToggle/ExpandableToggle.scss b/packages/@ourworldindata/components/src/ExpandableToggle/ExpandableToggle.scss index c83d9ea151a..bf154683438 100644 --- a/packages/@ourworldindata/components/src/ExpandableToggle/ExpandableToggle.scss +++ b/packages/@ourworldindata/components/src/ExpandableToggle/ExpandableToggle.scss @@ -1,7 +1,6 @@ .ExpandableToggle { border-top: 1px solid #d0dae3; border-bottom: 1px solid #d0dae3; - padding: 0 8px; } .ExpandableToggle--stacked { From 0f0bb523e7e13994150b13b9975aefe8eff97982 Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Wed, 1 Nov 2023 09:22:49 +0000 Subject: [PATCH 30/32] style(data-page): remove extra space when source description is missing --- .../components/src/IndicatorSources/IndicatorSources.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss index 6d63fd14c36..5ac46e1ca12 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.scss @@ -2,10 +2,10 @@ .description { @include body-3-medium; margin: 0; + margin-bottom: 16px; } .key-info { - margin-top: 16px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); row-gap: 8px; From 368c346ae70790a34a0dcee21674979a20a385ad Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Wed, 1 Nov 2023 10:21:06 +0000 Subject: [PATCH 31/32] enhance(data-page): trim text fragments --- .../IndicatorDescriptions/IndicatorDescriptions.tsx | 12 +++++++----- .../src/IndicatorProcessing/IndicatorProcessing.tsx | 2 +- .../src/IndicatorSources/IndicatorSources.tsx | 4 ++-- site/DataPageV2Content.tsx | 4 +--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx index b05dae48064..e147c3ddbca 100644 --- a/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx +++ b/packages/@ourworldindata/components/src/IndicatorDescriptions/IndicatorDescriptions.tsx @@ -25,13 +25,15 @@ export const IndicatorDescriptions = (props: IndicatorDescriptionsProps) => {
{props.descriptionKey.length === 1 ? ( ) : (
    - {props.descriptionKey.map((item, i) => ( + {props.descriptionKey.map((text, i) => (
  • - {" "} + {" "}
  • ))}
@@ -59,7 +61,7 @@ export const IndicatorDescriptions = (props: IndicatorDescriptionsProps) => { content={
} @@ -75,7 +77,7 @@ export const IndicatorDescriptions = (props: IndicatorDescriptionsProps) => { content={
} diff --git a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx index fc96adb440d..f0d1c8b6581 100644 --- a/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx +++ b/packages/@ourworldindata/components/src/IndicatorProcessing/IndicatorProcessing.tsx @@ -44,7 +44,7 @@ export const IndicatorProcessing = (props: IndicatorProcessingProps) => {

diff --git a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx index 7e17243dd54..69a5f3ef4cb 100644 --- a/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx +++ b/packages/@ourworldindata/components/src/IndicatorSources/IndicatorSources.tsx @@ -61,7 +61,7 @@ const SourceContent = (props: {
{source.description && (

- +

)} {showKeyInfo && ( @@ -103,7 +103,7 @@ const SourceContent = (props: { {" "} below.
diff --git a/site/DataPageV2Content.tsx b/site/DataPageV2Content.tsx index 8b55e1700b4..f4fb0ef245b 100644 --- a/site/DataPageV2Content.tsx +++ b/site/DataPageV2Content.tsx @@ -253,9 +253,7 @@ export const DataPageV2Content = ({

From bc6a0b56d943429bd728ccc1ce5d220e7bead81f Mon Sep 17 00:00:00 2001 From: sophiamersmann Date: Wed, 8 Nov 2023 11:31:56 +0100 Subject: [PATCH 32/32] chore: remove duplicate functions --- packages/@ourworldindata/utils/src/Util.ts | 74 ---------------------- 1 file changed, 74 deletions(-) diff --git a/packages/@ourworldindata/utils/src/Util.ts b/packages/@ourworldindata/utils/src/Util.ts index 40592873614..92e32eff5ee 100644 --- a/packages/@ourworldindata/utils/src/Util.ts +++ b/packages/@ourworldindata/utils/src/Util.ts @@ -1739,80 +1739,6 @@ export function mergePartialGrapherConfigs>( return merge({}, ...grapherConfigs) } -export function getOriginAttributionFragments( - origins: OwidOrigin[] | undefined -): string[] { - return origins - ? origins.map((origin) => { - const yearPublished = origin.datePublished - ? dayjs(origin.datePublished, ["YYYY", "YYYY-MM-DD"]).year() - : undefined - const yearPublishedString = yearPublished - ? ` (${yearPublished})` - : "" - return ( - origin.attribution ?? - `${origin.producer}${yearPublishedString}` - ) - }) - : [] -} - -export function getAttributionFromVariable( - variable: OwidVariableWithSource -): string { - return getAttributionFragmentsFromVariable(variable).join("; ") -} - -export function getAttributionFragmentsFromVariable( - variable: OwidVariableWithSource -): string[] { - if ( - variable.presentation?.attribution && - variable.presentation?.attribution !== "" - ) - return [variable.presentation?.attribution] - const originAttributionFragments = getOriginAttributionFragments( - variable.origins - ) - const sourceName = variable.source?.name - return uniq(compact([sourceName, ...originAttributionFragments])) -} - -interface ETLPathComponents { - channel: string - producer: string - version: string - dataset: string - table: string - indicator: string -} - -export const getETLPathComponents = (path: string): ETLPathComponents => { - const [channel, producer, version, dataset, table, indicator] = - path.split("/") - return { channel, producer, version, dataset, table, indicator } -} - -export const formatAuthors = ({ - authors, - requireMax, - forBibtex, -}: { - authors: string[] - requireMax?: boolean - forBibtex?: boolean -}): string => { - if (requireMax && !authors.includes("Max Roser")) - authors = [...authors, "Max Roser"] - - let authorsText = authors.slice(0, -1).join(forBibtex ? " and " : ", ") - if (authorsText.length === 0) authorsText = authors[0] - else authorsText += ` and ${last(authors)}` - - return authorsText -} - /** Works for: * #dod:text * #dod:text-hyphenated