From a72809e96b90622a945d0d4e482cc62f230f09dc Mon Sep 17 00:00:00 2001 From: Carina Date: Mon, 17 Feb 2025 14:08:48 +0100 Subject: [PATCH 01/24] MIM-2198:Timeline part from design sprint --- .../resources/assets/styles/_timeline.scss | 133 +++++++++++++ src/main/resources/assets/styles/main.scss | 1 + src/main/resources/index.d.ts | 1 + .../resources/lib/types/partTypes/timeline.ts | 18 ++ .../resources/site/parts/timeline/timeline.ts | 56 ++++++ .../site/parts/timeline/timeline.tsx | 176 ++++++++++++++++++ .../site/parts/timeline/timeline.xml | 61 ++++++ 7 files changed, 446 insertions(+) create mode 100644 src/main/resources/assets/styles/_timeline.scss create mode 100644 src/main/resources/lib/types/partTypes/timeline.ts create mode 100644 src/main/resources/site/parts/timeline/timeline.ts create mode 100644 src/main/resources/site/parts/timeline/timeline.tsx create mode 100644 src/main/resources/site/parts/timeline/timeline.xml diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss new file mode 100644 index 0000000000..ad9978f9fd --- /dev/null +++ b/src/main/resources/assets/styles/_timeline.scss @@ -0,0 +1,133 @@ +.ssb-timeline { + .filter { + display: flex; + flex-wrap: wrap; + gap: 0.75rem; + margin-top: 1.5rem; + margin-bottom: 8rem; + + .ssb-tag { + &.active { + background: $ssb-dark-5; + border: 2px solid $ssb-dark-5; + color: $ssb-white; + } + } + } + .timeline { + position: relative; + margin-right: 40px; + padding-left: 200px; + + .circle { + width: 16px; + height: 16px; + background-color: #274247; + border-radius: 50%; + position: absolute; + top: -10px; + transform: translateX(-40%); + } + + &:before { + content: ''; + width: 4px; + height: 100%; + background: #274247; + position: absolute; + top: 0; + } + + &:after { + content: ''; + display: block; + width: 100%; + clear: both; + } + + .timeline-elements { + padding-top: 25px; + padding-bottom: 50px; + } + + .timeline-content { + left: -20px; + position: relative; + margin-bottom: 30px; + max-width: 740px; + + .year { + width: 180px; + height: 80px; + background: #274247; + border-radius: 4px; + position: absolute; + align-content: center; + + span { + @include roboto-condenced; + color: #fff; + padding: 20px 40px; + font-size: 28px; + } + } + + .triangle { + position: absolute; + width: 0; + height: 0; + border-top: 40px solid transparent; + border-bottom: 40px solid transparent; + border-right: 20px solid #f0f8f9; + border-radius: 4px; + left: 160px; + } + + .events { + padding-top: 90px; + width: 100%; + min-width: 400px; + position: relative; + + .event { + margin-bottom: 20px; + + &:first-child { + margin-top: 20px; + } + + &:last-child { + margin-bottom: 80px; + } + + .ssb-card { + max-width: 400px; + } + } + } + + .event-box { + background: #fff; + border: 1px solid #274247; + border-radius: 8px; + display: grid; + padding: 20px 40px; + width: 100%; + .title { + @include roboto-condenced; + font-size: 20px; + margin-bottom: 10px; + } + } + } + + @include media-breakpoint-down(lg) { + padding-left: 20px; + margin-right: 0; + + .timeline-content { + width: 100%; + } + } + } +} diff --git a/src/main/resources/assets/styles/main.scss b/src/main/resources/assets/styles/main.scss index 5c32c8db83..91908b4a8a 100644 --- a/src/main/resources/assets/styles/main.scss +++ b/src/main/resources/assets/styles/main.scss @@ -91,6 +91,7 @@ $container-max-widths: ( @import './statisticContact'; @import './popup'; @import './print'; +@import './timeline'; body { -moz-osx-font-smoothing: grayscale; diff --git a/src/main/resources/index.d.ts b/src/main/resources/index.d.ts index 8a0d2dbac5..9f3ccbdd8a 100644 --- a/src/main/resources/index.d.ts +++ b/src/main/resources/index.d.ts @@ -71,6 +71,7 @@ declare global { export type StatisticDescription = _PartComponent<'mimir:statisticDescription'> export type SubjectArticleList = _PartComponent<'mimir:subjectArticleList'> export type Table = _PartComponent<'mimir:table'> + export type Timeline = _PartComponent<'mimir:timeline'> export type UpcomingReleases = _PartComponent<'mimir:upcomingReleases'> export type Variables = _PartComponent<'mimir:variables'> export type VideoEmbed = _PartComponent<'mimir:videoEmbed'> diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts new file mode 100644 index 0000000000..5a476d6356 --- /dev/null +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -0,0 +1,18 @@ +export interface TimelineProps { + timelineElements: TimelineElement[] +} + +export interface TimelineElement { + year: string + event?: TimelineEvent | TimelineEvent[] +} + +export interface TimelineEvent { + title: string + ingress?: string + eventText?: string + directorImage?: string + directorImageAltText?: string + category?: string + article?: string +} diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts new file mode 100644 index 0000000000..21fa9c2f52 --- /dev/null +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -0,0 +1,56 @@ +import { getComponent } from '/lib/xp/portal' +import { render } from '/lib/enonic/react4xp' +import { renderError } from '/lib/ssb/error/error' +import { imageUrl, getImageAlt } from '/lib/ssb/utils/imageUtils' +import { type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' +import { forceArray } from '/lib/ssb/utils/arrayUtils' + +export function get(req: XP.Request): XP.Response { + try { + return renderPart(req) + } catch (e) { + return renderError(req, 'Error in part: ', e) + } +} + +function renderPart(req: XP.Request) { + const part = getComponent() + if (!part) throw new Error('No part') + + const timelineElements: TimelineElement[] = part.config.TimelineItemSet ? forceArray(part.config.TimelineItemSet) : [] + const timelineProps: TimelineElement[] = timelineElements.map((element) => { + return { + year: element.year, + event: element.event ? parseEvent(forceArray(element.event)) : [], + } + }) + + const props = { + timelineElements: timelineProps, + } + + return render('site/parts/timeline/timeline', props, req, { + body: '
', + }) +} + +function parseEvent(events: TimelineEvent[]): TimelineEvent[] { + const parsedElements = events.map((event) => { + const image = event.directorImage + ? imageUrl({ + id: event.directorImage as string, + scale: 'block(100,100)', + format: 'jpg', + }) + : undefined + + const imageAltText = event.directorImage ? getImageAlt(event.directorImage) : '' + return { + ...event, + directorImage: image, + directorImageAltText: imageAltText ?? '', + } + }) + + return parsedElements +} diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx new file mode 100644 index 0000000000..946c2fa3e5 --- /dev/null +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -0,0 +1,176 @@ +import React, { useEffect, useState } from 'react' +import { CategoryLink, Card, ExpansionBox, Link, Tag, Text } from '@statisticsnorway/ssb-component-library' +import { type TimelineProps, type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' +import { sanitize } from '/lib/ssb/utils/htmlUtils' + +function Timeline(props: TimelineProps) { + const { timelineElements } = props + const [selectedTag, setSelectedTag] = useState('all') + const [filteredElements, setFilteredElements] = useState(props.timelineElements) + const [active, setActive] = useState(false) + + useEffect(() => { + if (selectedTag !== 'all') { + setFilteredElements(filterElementsByCategory(timelineElements, selectedTag)) + } else { + setFilteredElements(props.timelineElements) + } + }, [selectedTag]) + + function setFilter(filter: string) { + setSelectedTag(filter) + setActive(true) + setTimeout(() => { + setActive(false) + }, 1000) + } + + const filterElementsByCategory = (elements: TimelineElement[], category: string) => { + if (category === 'all') { + return elements + } + return elements + .map((element) => { + if (element.event) { + const filteredEvents = Array.isArray(element.event) + ? element.event.filter((event) => event.category === category) + : element.event.category === category + ? element.event + : null + + return filteredEvents ? { ...element, event: filteredEvents } : null + } + return null + }) + .filter((element) => element !== null) + } + + function addCategoryLink(event: TimelineEvent) { + return + } + + function addDirectorCard(event: TimelineEvent) { + return ( + } + profiled + > + {event.ingress} + + ) + } + + function addEventBox(event: TimelineEvent) { + return ( +
+ {event.article ? {event.title} : {event.title}} + {event.ingress && {event.ingress}} +
+ ) + } + + function addEventExpansionBox(event: TimelineEvent) { + const text = event.eventText ? ( +
+ ) : ( + '' + ) + + return + } + + function addEvents(events: TimelineEvent[]) { + return ( +
+ {events.map((event, index) => { + return ( +
+ {addEvent(event)} +
+ ) + })} +
+ ) + } + + function addEvent(event: TimelineEvent) { + if (event.directorImage) { + return addDirectorCard(event) + } + if (event.article) { + return addCategoryLink(event) + } + + if (event.eventText) { + return addEventExpansionBox(event) + } + + if (!event.eventText && !event.article) { + return addEventBox(event) + } + return addEventBox(event) + } + + function addTimelineYear(timeline: TimelineElement) { + const events = timeline.event ? (Array.isArray(timeline.event) ? timeline.event : [timeline.event]) : [] + if (events.length === 0) { + return null + } + return ( +
+
+ {timeline.year} +
+
+ {events?.length && addEvents(events)} +
+ ) + } + + function addFilter() { + return ( +
+ setFilter('all')}> + Vis alt + + setFilter('statistic')}> + Statistiske hendelser + + setFilter('eventSsb')}> + Institusjonelle hendelser + + setFilter('director')}> + Direktører + +
+ ) + } + + function addTimeLine() { + return ( +
+
+
+ {filteredElements?.map((timeline) => { + return <>{addTimelineYear(timeline)} + })} +
+
+ ) + } + + return ( +
+ {addFilter()} + {addTimeLine()} +
+ ) +} + +export default (props: TimelineProps) => diff --git a/src/main/resources/site/parts/timeline/timeline.xml b/src/main/resources/site/parts/timeline/timeline.xml new file mode 100644 index 0000000000..2635bc941b --- /dev/null +++ b/src/main/resources/site/parts/timeline/timeline.xml @@ -0,0 +1,61 @@ + + Tidslinje +
+ + + + + + + + + + + + + + + + + + + + + + + + + Bold Italic Underline Strike Subscript Superscript Cut Copy Blockquote + h2 h3 h4 h5 + + + + + + + + + + + + + + + + eventSsb + + + + + + ${site} + page + article + + + + + + +
+
From bed3e357b098048d1d992ee6f1f1338222c08b09 Mon Sep 17 00:00:00 2001 From: Carina Date: Tue, 18 Feb 2025 14:52:04 +0100 Subject: [PATCH 02/24] MIM-2198:Added optionset urlArticle --- .../resources/lib/types/partTypes/timeline.ts | 16 +++++++++ .../resources/site/parts/timeline/timeline.ts | 24 +++++++++++-- .../site/parts/timeline/timeline.tsx | 12 +++++-- .../site/parts/timeline/timeline.xml | 34 +++++++++++++++---- 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts index 5a476d6356..a85f5735c0 100644 --- a/src/main/resources/lib/types/partTypes/timeline.ts +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -15,4 +15,20 @@ export interface TimelineEvent { directorImageAltText?: string category?: string article?: string + urlArticle?: hrefManual | hrefContent + targetUrl?: string +} + +interface hrefManual { + _selected: 'optionLink' + optionLink: { + link?: string + } +} + +interface hrefContent { + _selected: 'optionXPContent' + optionXPContent: { + xpContent?: string + } } diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts index 21fa9c2f52..a7ea7f0e64 100644 --- a/src/main/resources/site/parts/timeline/timeline.ts +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -1,9 +1,10 @@ -import { getComponent } from '/lib/xp/portal' +import { getComponent, pageUrl } from '/lib/xp/portal' import { render } from '/lib/enonic/react4xp' import { renderError } from '/lib/ssb/error/error' import { imageUrl, getImageAlt } from '/lib/ssb/utils/imageUtils' import { type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' import { forceArray } from '/lib/ssb/utils/arrayUtils' +import { type Timeline as TimelinePartConfig } from '/site/parts/timeline' export function get(req: XP.Request): XP.Response { try { @@ -17,8 +18,9 @@ function renderPart(req: XP.Request) { const part = getComponent() if (!part) throw new Error('No part') - const timelineElements: TimelineElement[] = part.config.TimelineItemSet ? forceArray(part.config.TimelineItemSet) : [] - const timelineProps: TimelineElement[] = timelineElements.map((element) => { + const timelineConfig: TimelinePartConfig = part.config + const timelineItems: TimelinePartConfig['TimelineItemSet'] = forceArray(timelineConfig.TimelineItemSet) + const timelineProps: TimelineElement[] = timelineItems.map((element) => { return { year: element.year, event: element.event ? parseEvent(forceArray(element.event)) : [], @@ -49,8 +51,24 @@ function parseEvent(events: TimelineEvent[]): TimelineEvent[] { ...event, directorImage: image, directorImageAltText: imageAltText ?? '', + targetUrl: getLinkTargetUrl(event), } }) return parsedElements } + +function getLinkTargetUrl(event: TimelineEvent): string { + if (event.urlArticle?._selected == 'optionLink') { + return event.urlArticle.optionLink.link ?? '' + } + + if (event.urlArticle?._selected == 'optionXPContent') { + return event.urlArticle.optionXPContent.xpContent + ? pageUrl({ + id: event.urlArticle.optionXPContent.xpContent, + }) + : '' + } + return '' +} diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 946c2fa3e5..5e12c04ce5 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -46,14 +46,14 @@ function Timeline(props: TimelineProps) { } function addCategoryLink(event: TimelineEvent) { - return + return } function addDirectorCard(event: TimelineEvent) { return ( } profiled > @@ -65,7 +65,13 @@ function Timeline(props: TimelineProps) { function addEventBox(event: TimelineEvent) { return (
- {event.article ? {event.title} : {event.title}} + {event.targetUrl ? ( + + {event.title} + + ) : ( + {event.title} + )} {event.ingress && {event.ingress}}
) diff --git a/src/main/resources/site/parts/timeline/timeline.xml b/src/main/resources/site/parts/timeline/timeline.xml index 2635bc941b..6f34b285c7 100644 --- a/src/main/resources/site/parts/timeline/timeline.xml +++ b/src/main/resources/site/parts/timeline/timeline.xml @@ -44,15 +44,35 @@ eventSsb - + + false - - ${site} - page - article - - + Velge enten url eller innhold + + + + + From c60c217ed2212638d6a59af7b5775073cabc4edd Mon Sep 17 00:00:00 2001 From: Carina Date: Wed, 19 Feb 2025 12:46:30 +0100 Subject: [PATCH 03/24] First version Show more button --- .../resources/assets/styles/_timeline.scss | 7 +++ .../resources/lib/types/partTypes/timeline.ts | 1 + .../resources/site/parts/timeline/timeline.ts | 1 + .../site/parts/timeline/timeline.tsx | 50 ++++++++++++++++--- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index ad9978f9fd..5af58d384a 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -47,7 +47,9 @@ .timeline-elements { padding-top: 25px; + padding-left: 0; padding-bottom: 50px; + list-style: none; } .timeline-content { @@ -130,4 +132,9 @@ } } } + .button-more { + left: -20px; + top: -30px; + position: relative; + } } diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts index a85f5735c0..7042c23196 100644 --- a/src/main/resources/lib/types/partTypes/timeline.ts +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -1,5 +1,6 @@ export interface TimelineProps { timelineElements: TimelineElement[] + countYear: number } export interface TimelineElement { diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts index a7ea7f0e64..1bd7058a2d 100644 --- a/src/main/resources/site/parts/timeline/timeline.ts +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -29,6 +29,7 @@ function renderPart(req: XP.Request) { const props = { timelineElements: timelineProps, + countYear: 5, } return render('site/parts/timeline/timeline', props, req, { diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 5e12c04ce5..77e21337ee 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -1,13 +1,17 @@ -import React, { useEffect, useState } from 'react' -import { CategoryLink, Card, ExpansionBox, Link, Tag, Text } from '@statisticsnorway/ssb-component-library' +import React, { useEffect, useState, useRef } from 'react' +import { Button, CategoryLink, Card, ExpansionBox, Link, Tag, Text } from '@statisticsnorway/ssb-component-library' +import { ChevronDown } from 'react-feather' import { type TimelineProps, type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' import { sanitize } from '/lib/ssb/utils/htmlUtils' function Timeline(props: TimelineProps) { - const { timelineElements } = props + const { timelineElements, countYear } = props const [selectedTag, setSelectedTag] = useState('all') - const [filteredElements, setFilteredElements] = useState(props.timelineElements) + const [filteredElements, setFilteredElements] = useState(timelineElements) const [active, setActive] = useState(false) + const [timelineCount, setTimeLineCount] = useState(countYear) + + const firstNewItemRef = useRef(null) useEffect(() => { if (selectedTag !== 'all') { @@ -17,6 +21,22 @@ function Timeline(props: TimelineProps) { } }, [selectedTag]) + useEffect(() => { + if (timelineCount > countYear && firstNewItemRef.current) { + const firstEvent = firstNewItemRef.current.querySelector('.event') + if (firstEvent) { + const firstFocusable = firstEvent.querySelector('a, button, input, [tabindex]:not([tabindex="-1"])') + if (firstFocusable) { + ;(firstFocusable as HTMLElement).focus() + } + } + } + }, [timelineCount]) + + const fetchMoreYear = () => { + setTimeLineCount((prevCount) => prevCount + countYear) + } + function setFilter(filter: string) { setSelectedTag(filter) setActive(true) @@ -45,6 +65,15 @@ function Timeline(props: TimelineProps) { .filter((element) => element !== null) } + function renderShowMoreButton() { + return ( + + ) + } + function addCategoryLink(event: TimelineEvent) { return } @@ -123,13 +152,17 @@ function Timeline(props: TimelineProps) { return addEventBox(event) } - function addTimelineYear(timeline: TimelineElement) { + function addTimelineYear(timeline: TimelineElement, i: number) { const events = timeline.event ? (Array.isArray(timeline.event) ? timeline.event : [timeline.event]) : [] if (events.length === 0) { return null } return ( -
+
{timeline.year}
@@ -163,10 +196,11 @@ function Timeline(props: TimelineProps) {
- {filteredElements?.map((timeline) => { - return <>{addTimelineYear(timeline)} + {filteredElements?.slice(0, timelineCount).map((timeline, i) => { + return <>{addTimelineYear(timeline, i)} })}
+ {renderShowMoreButton()}
) } From 524235c972a9ed5b2b2f22c3e6d2b84349d10412 Mon Sep 17 00:00:00 2001 From: Carina Date: Wed, 19 Feb 2025 15:33:14 +0100 Subject: [PATCH 04/24] Refactoring show more years button --- .../resources/lib/types/partTypes/timeline.ts | 1 + .../resources/site/i18n/phrases.properties | 1 + .../resources/site/i18n/phrases_en.properties | 1 + .../resources/site/i18n/phrases_nn.properties | 1 + .../resources/site/parts/timeline/timeline.ts | 14 ++++++-- .../site/parts/timeline/timeline.tsx | 32 +++++++++++++++---- 6 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts index 7042c23196..94d6ee6f17 100644 --- a/src/main/resources/lib/types/partTypes/timeline.ts +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -1,5 +1,6 @@ export interface TimelineProps { timelineElements: TimelineElement[] + showMoreButtonText: string countYear: number } diff --git a/src/main/resources/site/i18n/phrases.properties b/src/main/resources/site/i18n/phrases.properties index 02dc803796..ce04877787 100644 --- a/src/main/resources/site/i18n/phrases.properties +++ b/src/main/resources/site/i18n/phrases.properties @@ -393,6 +393,7 @@ highcharts.legendLabelNoTitle = Bytt synlighet på serie, {chartTitle} button.showMore = Vis flere button.showAll = Vis alle +button.showMoreYears = Vis flere år methodsAndDocumentation = Metoder og dokumentasjon nameSearch.title = Navnesøk diff --git a/src/main/resources/site/i18n/phrases_en.properties b/src/main/resources/site/i18n/phrases_en.properties index 128d8282f1..1d957e6124 100644 --- a/src/main/resources/site/i18n/phrases_en.properties +++ b/src/main/resources/site/i18n/phrases_en.properties @@ -393,6 +393,7 @@ highcharts.legendLabelNoTitle = Toggle series visibility, {chartTitle} button.showMore = Show more button.showAll = Show all +button.showMoreYears = Show more years methodsAndDocumentation = Methods and documentation nameSearch.title = Name search diff --git a/src/main/resources/site/i18n/phrases_nn.properties b/src/main/resources/site/i18n/phrases_nn.properties index 0fb0ddfd1a..05242a8ab2 100644 --- a/src/main/resources/site/i18n/phrases_nn.properties +++ b/src/main/resources/site/i18n/phrases_nn.properties @@ -386,6 +386,7 @@ highcharts.legendLabelNoTitle = Bytt synlighet på serie, {chartTitle} button.showMore = Vis fleire button.showAll = Vis alle +button.showMoreYears = Vis fleire år methodsAndDocumentation = Metoder og dokumentasjon nameSearch.title = Namnsøk diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts index 1bd7058a2d..ad79f4e402 100644 --- a/src/main/resources/site/parts/timeline/timeline.ts +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -1,4 +1,5 @@ -import { getComponent, pageUrl } from '/lib/xp/portal' +import { getComponent, getContent, pageUrl } from '/lib/xp/portal' +import { localize } from '/lib/xp/i18n' import { render } from '/lib/enonic/react4xp' import { renderError } from '/lib/ssb/error/error' import { imageUrl, getImageAlt } from '/lib/ssb/utils/imageUtils' @@ -16,7 +17,10 @@ export function get(req: XP.Request): XP.Response { function renderPart(req: XP.Request) { const part = getComponent() - if (!part) throw new Error('No part') + const page = getContent() + if (!part || !page) throw new Error('No page or part') + + const language: string = page.language ? page.language : 'nb' const timelineConfig: TimelinePartConfig = part.config const timelineItems: TimelinePartConfig['TimelineItemSet'] = forceArray(timelineConfig.TimelineItemSet) @@ -27,8 +31,14 @@ function renderPart(req: XP.Request) { } }) + const showMoreText: string = localize({ + key: 'button.showMoreYears', + locale: language === 'nb' ? 'no' : language, + }) + const props = { timelineElements: timelineProps, + showMoreButtonText: showMoreText ?? 'Vis flere år', countYear: 5, } diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 77e21337ee..765624ff29 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -3,15 +3,17 @@ import { Button, CategoryLink, Card, ExpansionBox, Link, Tag, Text } from '@stat import { ChevronDown } from 'react-feather' import { type TimelineProps, type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' import { sanitize } from '/lib/ssb/utils/htmlUtils' +import { usePaginationKeyboardNavigation } from '/lib/ssb/utils/customHooks/paginationHooks' function Timeline(props: TimelineProps) { - const { timelineElements, countYear } = props + const { timelineElements, countYear, showMoreButtonText } = props const [selectedTag, setSelectedTag] = useState('all') const [filteredElements, setFilteredElements] = useState(timelineElements) const [active, setActive] = useState(false) const [timelineCount, setTimeLineCount] = useState(countYear) + const [keyboardNavigation, setKeyboardNavigation] = useState(false) - const firstNewItemRef = useRef(null) + const firstNewTimelineRef = useRef(null) useEffect(() => { if (selectedTag !== 'all') { @@ -22,8 +24,8 @@ function Timeline(props: TimelineProps) { }, [selectedTag]) useEffect(() => { - if (timelineCount > countYear && firstNewItemRef.current) { - const firstEvent = firstNewItemRef.current.querySelector('.event') + if (keyboardNavigation && firstNewTimelineRef.current) { + const firstEvent = firstNewTimelineRef.current.querySelector('.event') if (firstEvent) { const firstFocusable = firstEvent.querySelector('a, button, input, [tabindex]:not([tabindex="-1"])') if (firstFocusable) { @@ -65,11 +67,27 @@ function Timeline(props: TimelineProps) { .filter((element) => element !== null) } + const handleOnClick = () => { + setKeyboardNavigation(false) + fetchMoreYear() + } + + const handleKeyboardNavigation = usePaginationKeyboardNavigation(() => { + setKeyboardNavigation(true) + fetchMoreYear() + }) + function renderShowMoreButton() { return ( - ) } @@ -161,7 +179,7 @@ function Timeline(props: TimelineProps) {
{timeline.year} From 9a6047f2d77a4fb1f269cab95f109ed4d8274052 Mon Sep 17 00:00:00 2001 From: Carina Date: Mon, 24 Feb 2025 14:23:29 +0100 Subject: [PATCH 05/24] MIM-2198:Added external categoryLink --- package-lock.json | 14 +++++++------- package.json | 2 +- .../resources/site/parts/timeline/timeline.tsx | 13 ++++++++++++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 20334de870..8269dade58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,7 +65,7 @@ "@item-enonic-types/lib-thymeleaf": "~2.1.0", "@item-enonic-types/lib-time": "~1.0.4", "@reduxjs/toolkit": "~2.5.0", - "@statisticsnorway/ssb-component-library": "~2.4.7", + "@statisticsnorway/ssb-component-library": "~2.4.8", "@types/grecaptcha": "^3.0.9", "@types/ramda": "~0.30.2", "@types/react": "~18.3.12", @@ -5735,9 +5735,9 @@ "dev": true }, "node_modules/@statisticsnorway/ssb-component-library": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/@statisticsnorway/ssb-component-library/-/ssb-component-library-2.4.7.tgz", - "integrity": "sha512-CAsVBKBQ8N+jm3M42DyhEWJ6kgTDGoJKjbqDUC1vsHXuZy8v8sgAa0VRyC0EtDdR9NHbz0P82pJwCNHx8sVZuQ==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@statisticsnorway/ssb-component-library/-/ssb-component-library-2.4.8.tgz", + "integrity": "sha512-Qta56a5jD8Q8Cbz4rl/xMpQY9059XqgbeUMHLtNfvSOB5yxRUOSSfaWr34e9eN5m1zp/sOUTASI/aC+3Yi3vew==", "dev": true, "dependencies": { "prismjs": "~1.29.0", @@ -25457,9 +25457,9 @@ "dev": true }, "@statisticsnorway/ssb-component-library": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/@statisticsnorway/ssb-component-library/-/ssb-component-library-2.4.7.tgz", - "integrity": "sha512-CAsVBKBQ8N+jm3M42DyhEWJ6kgTDGoJKjbqDUC1vsHXuZy8v8sgAa0VRyC0EtDdR9NHbz0P82pJwCNHx8sVZuQ==", + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/@statisticsnorway/ssb-component-library/-/ssb-component-library-2.4.8.tgz", + "integrity": "sha512-Qta56a5jD8Q8Cbz4rl/xMpQY9059XqgbeUMHLtNfvSOB5yxRUOSSfaWr34e9eN5m1zp/sOUTASI/aC+3Yi3vew==", "dev": true, "requires": { "prismjs": "~1.29.0", diff --git a/package.json b/package.json index 4623b13e09..10197d8fe5 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "@item-enonic-types/lib-thymeleaf": "~2.1.0", "@item-enonic-types/lib-time": "~1.0.4", "@reduxjs/toolkit": "~2.5.0", - "@statisticsnorway/ssb-component-library": "~2.4.7", + "@statisticsnorway/ssb-component-library": "~2.4.8", "@types/grecaptcha": "^3.0.9", "@types/ramda": "~0.30.2", "@types/react": "~18.3.12", diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 765624ff29..dbfd10245c 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -77,6 +77,10 @@ function Timeline(props: TimelineProps) { fetchMoreYear() }) + function isExternalUrl(url?: string): boolean { + return !!url && !url.startsWith('/') && !url.includes('ssb.no') + } + function renderShowMoreButton() { return (
- {renderShowMoreButton()} + {timelineElements.length > countYear && renderShowMoreButton()}
) } diff --git a/src/main/resources/site/parts/timeline/timeline.xml b/src/main/resources/site/parts/timeline/timeline.xml index 6f34b285c7..af51be569e 100644 --- a/src/main/resources/site/parts/timeline/timeline.xml +++ b/src/main/resources/site/parts/timeline/timeline.xml @@ -37,9 +37,8 @@ - - - + + eventSsb From dec33443204d5776275952b319fe2e9ed3091416 Mon Sep 17 00:00:00 2001 From: Carina Date: Thu, 27 Feb 2025 12:24:19 +0100 Subject: [PATCH 08/24] changing catogoryes --- src/main/resources/site/parts/timeline/timeline.tsx | 6 +++--- src/main/resources/site/parts/timeline/timeline.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 2f6166a895..871734403f 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -208,10 +208,10 @@ function Timeline(props: TimelineProps) { Vis alt setFilter('statistic')}> - Statistiske hendelser + Statistikk - setFilter('eventSsb')}> - Institusjonelle hendelser + setFilter('aboutSsb')}> + Om SSB setFilter('director')}> Direktører diff --git a/src/main/resources/site/parts/timeline/timeline.xml b/src/main/resources/site/parts/timeline/timeline.xml index af51be569e..69a16e183d 100644 --- a/src/main/resources/site/parts/timeline/timeline.xml +++ b/src/main/resources/site/parts/timeline/timeline.xml @@ -37,11 +37,11 @@ - - + + - eventSsb + aboutSsb From dc963564e5333bf257434150908ac044119e6f4b Mon Sep 17 00:00:00 2001 From: Carina Date: Sat, 1 Mar 2025 19:38:13 +0100 Subject: [PATCH 09/24] Teste alternativ part --- src/main/resources/index.d.ts | 1 + .../resources/lib/types/partTypes/timeline.ts | 44 +++- .../linkUrlOrContent/linkUrlOrContent.xml | 33 +++ .../timelineCategory/timelineCategory.xml | 15 ++ .../site/parts/timelineNew/timelineNew.ts | 144 +++++++++++ .../site/parts/timelineNew/timelineNew.tsx | 240 ++++++++++++++++++ .../site/parts/timelineNew/timelineNew.xml | 74 ++++++ 7 files changed, 550 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/site/mixins/linkUrlOrContent/linkUrlOrContent.xml create mode 100644 src/main/resources/site/mixins/timelineCategory/timelineCategory.xml create mode 100644 src/main/resources/site/parts/timelineNew/timelineNew.ts create mode 100644 src/main/resources/site/parts/timelineNew/timelineNew.tsx create mode 100644 src/main/resources/site/parts/timelineNew/timelineNew.xml diff --git a/src/main/resources/index.d.ts b/src/main/resources/index.d.ts index 9f3ccbdd8a..1b32b467c0 100644 --- a/src/main/resources/index.d.ts +++ b/src/main/resources/index.d.ts @@ -72,6 +72,7 @@ declare global { export type SubjectArticleList = _PartComponent<'mimir:subjectArticleList'> export type Table = _PartComponent<'mimir:table'> export type Timeline = _PartComponent<'mimir:timeline'> + export type TimelineNew = _PartComponent<'mimir:timelineNew'> export type UpcomingReleases = _PartComponent<'mimir:upcomingReleases'> export type Variables = _PartComponent<'mimir:variables'> export type VideoEmbed = _PartComponent<'mimir:videoEmbed'> diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts index 94d6ee6f17..03415c42c9 100644 --- a/src/main/resources/lib/types/partTypes/timeline.ts +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -6,10 +6,22 @@ export interface TimelineProps { export interface TimelineElement { year: string - event?: TimelineEvent | TimelineEvent[] + event: TimelineEvent[] + //event?: TimelineEvent | TimelineEvent[] } export interface TimelineEvent { + eventType: string + title: string + text?: string + directorImage?: string + directorImageAltText?: string + timelineCategory?: string + targetUrl?: string +} + +/* export interface TimelineEventOld { + title: string ingress?: string eventText?: string @@ -19,6 +31,36 @@ export interface TimelineEvent { article?: string urlArticle?: hrefManual | hrefContent targetUrl?: string +} */ +export interface SimpleBox { + title: string + text: string + timelineCategory: string + urlContentSelector?: hrefManual | hrefContent +} + +export interface ExpansionBox { + title: string + text: string + timelineCategory: string +} + +export interface DirectorBox { + title: string + text: string + directorImage: string +} + +export interface Event { + simpleBox?: SimpleBox + expansionBox?: ExpansionBox + directorBox?: DirectorBox + _selected: 'simpleBox' | 'expansionBox' | 'directorBox' +} + +export interface TimelineItemSet { + year: string + event: Event[] } interface hrefManual { diff --git a/src/main/resources/site/mixins/linkUrlOrContent/linkUrlOrContent.xml b/src/main/resources/site/mixins/linkUrlOrContent/linkUrlOrContent.xml new file mode 100644 index 0000000000..9a8c318d03 --- /dev/null +++ b/src/main/resources/site/mixins/linkUrlOrContent/linkUrlOrContent.xml @@ -0,0 +1,33 @@ + + Lenke +
+ + + false + + + + + + +
+
diff --git a/src/main/resources/site/mixins/timelineCategory/timelineCategory.xml b/src/main/resources/site/mixins/timelineCategory/timelineCategory.xml new file mode 100644 index 0000000000..13314c47f8 --- /dev/null +++ b/src/main/resources/site/mixins/timelineCategory/timelineCategory.xml @@ -0,0 +1,15 @@ + + Hendelsestype Tidslinje +
+ + + + + + + + + aboutSsb + + +
diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.ts b/src/main/resources/site/parts/timelineNew/timelineNew.ts new file mode 100644 index 0000000000..3f64c0e14d --- /dev/null +++ b/src/main/resources/site/parts/timelineNew/timelineNew.ts @@ -0,0 +1,144 @@ +import { getComponent, getContent, pageUrl } from '/lib/xp/portal' +import { localize } from '/lib/xp/i18n' +import { render } from '/lib/enonic/react4xp' +import { renderError } from '/lib/ssb/error/error' +import { imageUrl, getImageAlt } from '/lib/ssb/utils/imageUtils' +import { + type Event, + type SimpleBox, + type ExpansionBox, + type DirectorBox, + type TimelineElement, + type TimelineEvent, +} from '/lib/types/partTypes/timeline' +import { forceArray } from '/lib/ssb/utils/arrayUtils' +import { type Timeline as TimelinePartConfig } from '/site/parts/timeline' + +export function get(req: XP.Request): XP.Response { + try { + return renderPart(req) + } catch (e) { + return renderError(req, 'Error in part: ', e) + } +} + +function renderPart(req: XP.Request) { + const part = getComponent() + const page = getContent() + if (!part || !page) throw new Error('No page or part') + + const language: string = page.language ? page.language : 'nb' + + const timelineConfig: TimelinePartConfig = part.config + const timelineItems: TimelinePartConfig['TimelineItemSet'] = forceArray(timelineConfig.TimelineItemSet) + + const timelineProps: TimelineElement[] = timelineItems.map((element) => { + const events: Event[] = element.event ? forceArray(element.event) : [] + const parsedEvents: TimelineEvent[] = parseEvents(events) + return { + year: element.year, + event: parsedEvents, + } + }) + + const showMoreText: string = localize({ + key: 'button.showMoreYears', + locale: language === 'nb' ? 'no' : language, + }) + + const props = { + timelineElements: timelineProps, + showMoreButtonText: showMoreText ?? 'Vis flere år', + countYear: 5, + } + + return render('site/parts/timeline/timeline', props, req, { + body: '
', + }) +} + +function parseEvents(events: Event[]): TimelineEvent[] { + return events.map((event: Event) => { + return parseEvent(event) + }) +} + +function parseEvent(event: Event): TimelineEvent { + if (event.simpleBox) { + return parseSimpleBox(event.simpleBox) + } + + if (event.expansionBox) { + return parseExpansionBox(event.expansionBox) + } + if (event.directorBox) { + return parseDirector(event.directorBox) + } + return { + eventType: '', + title: '', + text: '', + directorImage: undefined, + directorImageAltText: '', + timelineCategory: '', + targetUrl: '', + } +} + +function parseSimpleBox(event: SimpleBox): TimelineEvent { + const simpleBox = { + eventType: 'simpleBox', + title: event.title, + text: event.text ?? '', + directorImage: undefined, + directorImageAltText: '', + timelineCategory: event.timelineCategory, + targetUrl: event.urlContentSelector ? getLinkTargetUrl(event) : '', + } + return simpleBox +} + +function parseExpansionBox(event: ExpansionBox): TimelineEvent { + return { + eventType: 'expansionBox', + title: event.title, + text: event.text, + directorImage: undefined, + directorImageAltText: '', + timelineCategory: event.timelineCategory, + targetUrl: '', + } +} + +function parseDirector(event: DirectorBox): TimelineEvent { + return { + eventType: 'directorBox', + title: event.title, + text: event.text, + directorImage: event.directorImage + ? imageUrl({ + id: event.directorImage as string, + scale: 'block(100,100)', + format: 'jpg', + }) + : undefined, + directorImageAltText: event.directorImage ? getImageAlt(event.directorImage) : '', + timelineCategory: 'director', + targetUrl: '', + } +} + +function getLinkTargetUrl(event: SimpleBox): string { + if (event.urlContentSelector?._selected == 'optionLink') { + return event.urlContentSelector.optionLink.link ?? '' + } + + if (event.urlContentSelector?._selected == 'optionXPContent') { + return event.urlContentSelector.optionXPContent.xpContent + ? pageUrl({ + id: event.urlContentSelector.optionXPContent.xpContent, + }) + : '' + } + return '' +} diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.tsx b/src/main/resources/site/parts/timelineNew/timelineNew.tsx new file mode 100644 index 0000000000..260b6a6249 --- /dev/null +++ b/src/main/resources/site/parts/timelineNew/timelineNew.tsx @@ -0,0 +1,240 @@ +import React, { useEffect, useState, useRef } from 'react' +import { Button, CategoryLink, Card, ExpansionBox, Link, Tag, Text } from '@statisticsnorway/ssb-component-library' +import { ChevronDown } from 'react-feather' +import { type TimelineProps, type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' +import { sanitize } from '/lib/ssb/utils/htmlUtils' +import { usePaginationKeyboardNavigation } from '/lib/ssb/utils/customHooks/paginationHooks' + +function Timeline(props: TimelineProps) { + const { timelineElements, countYear, showMoreButtonText } = props + const [selectedTag, setSelectedTag] = useState('all') + const [filteredElements, setFilteredElements] = useState(timelineElements) + const [active, setActive] = useState(false) + const [timelineCount, setTimeLineCount] = useState(countYear) + const [keyboardNavigation, setKeyboardNavigation] = useState(false) + + const firstNewTimelineRef = useRef(null) + + useEffect(() => { + if (selectedTag !== 'all') { + setFilteredElements(filterElementsByCategory(timelineElements, selectedTag)) + } else { + setFilteredElements(props.timelineElements) + } + }, [selectedTag]) + + useEffect(() => { + if (keyboardNavigation && firstNewTimelineRef.current) { + const firstEvent = firstNewTimelineRef.current.querySelector('.event') + if (firstEvent) { + const firstFocusable = firstEvent.querySelector('a, button, input, [tabindex]:not([tabindex="-1"])') + if (firstFocusable) { + ;(firstFocusable as HTMLElement).focus() + } + } + } + }, [timelineCount]) + + const fetchMoreYear = () => { + setTimeLineCount((prevCount) => prevCount + countYear) + } + + function setFilter(filter: string) { + setSelectedTag(filter) + setActive(true) + setTimeout(() => { + setActive(false) + }, 1000) + } + + const filterElementsByCategory = (elements: TimelineElement[], category: string) => { + if (category === 'all') { + return elements + } + return elements + .map((element) => { + if (element.event) { + const filteredEvents = element.event.filter((event) => event.timelineCategory === category) + return filteredEvents ? { ...element, event: filteredEvents } : null + } + return null + }) + .filter((element) => element !== null) + } + + const handleOnClick = () => { + setKeyboardNavigation(false) + fetchMoreYear() + } + + const handleKeyboardNavigation = usePaginationKeyboardNavigation(() => { + setKeyboardNavigation(true) + fetchMoreYear() + }) + + function isExternalUrl(url?: string): boolean { + return !!url && !url.startsWith('/') && !url.includes('ssb.no') + } + + function renderShowMoreButton() { + return ( + + ) + } + + function addCategoryLink(event: TimelineEvent) { + return ( + + ) + } + + function addDirectorCard(event: TimelineEvent) { + return ( + } + profiled + > + {event.text} + + ) + } + + function addEventBox(event: TimelineEvent) { + return ( +
+ {event.targetUrl ? ( + + {event.title} + + ) : ( + {event.title} + )} + {event.text && {event.text}} +
+ ) + } + + function addEventExpansionBox(event: TimelineEvent) { + const text = event.text ? ( +
+ ) : ( + '' + ) + + return + } + + function addEvents(events: TimelineEvent[]) { + return ( +
+ {events.map((event, index) => { + return ( +
+ {addEvent(event)} +
+ ) + })} +
+ ) + } + + function addEvent(event: TimelineEvent) { + if (event.eventType === 'directorBox') { + return addDirectorCard(event) + } + if (event.eventType === 'simpleBox' && event.targetUrl) { + return addCategoryLink(event) + } + + if (event.eventType === 'simpleBox' && !event.targetUrl) { + return addEventBox(event) + } + + if (event.eventType === 'expansionBox') { + return addEventExpansionBox(event) + } + return addEventBox(event) + } + + function addTimelineYear(timeline: TimelineElement, i: number) { + const events = timeline.event ? (Array.isArray(timeline.event) ? timeline.event : [timeline.event]) : [] + if (events.length === 0) { + return null + } + return ( +
+
+ {timeline.year} +
+
+ {events?.length && addEvents(events)} +
+ ) + } + + function addFilter() { + return ( +
+ setFilter('all')}> + Vis alt + + setFilter('statistic')}> + Statistikk + + setFilter('aboutSsb')}> + Om SSB + + setFilter('director')}> + Direktører + +
+ ) + } + + function addTimeLine() { + return ( +
+
+
+ {filteredElements?.slice(0, timelineCount).map((timeline, i) => { + return <>{addTimelineYear(timeline, i)} + })} +
+ {timelineElements.length > countYear && renderShowMoreButton()} +
+ ) + } + + return ( +
+ {addFilter()} + {addTimeLine()} +
+ ) +} + +export default (props: TimelineProps) => diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.xml b/src/main/resources/site/parts/timelineNew/timelineNew.xml new file mode 100644 index 0000000000..f64229a480 --- /dev/null +++ b/src/main/resources/site/parts/timelineNew/timelineNew.xml @@ -0,0 +1,74 @@ + + Tidslinje Ny +
+ + + + + + + + + + + false + + Velg type hendelse + + + + + + + + +
+
From 734e65491463e7b19a1e3af2033247dd6942ddf5 Mon Sep 17 00:00:00 2001 From: Carina Date: Wed, 5 Mar 2025 07:30:30 +0100 Subject: [PATCH 10/24] Fikse liten feil i ny mal --- src/main/resources/site/parts/timelineNew/timelineNew.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.ts b/src/main/resources/site/parts/timelineNew/timelineNew.ts index 3f64c0e14d..983746d048 100644 --- a/src/main/resources/site/parts/timelineNew/timelineNew.ts +++ b/src/main/resources/site/parts/timelineNew/timelineNew.ts @@ -52,7 +52,7 @@ function renderPart(req: XP.Request) { countYear: 5, } - return render('site/parts/timeline/timeline', props, req, { + return render('site/parts/timelineNew/timelineNew', props, req, { body: '
', }) } From c8521f881377975eb44043b24b4b8f485abeab56 Mon Sep 17 00:00:00 2001 From: Carina Date: Wed, 5 Mar 2025 10:48:01 +0100 Subject: [PATCH 11/24] Added targetUrl to DirectorBox --- src/main/resources/lib/types/partTypes/timeline.ts | 1 + src/main/resources/site/parts/timelineNew/timelineNew.ts | 4 ++-- src/main/resources/site/parts/timelineNew/timelineNew.xml | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts index 03415c42c9..20f5b2499b 100644 --- a/src/main/resources/lib/types/partTypes/timeline.ts +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -49,6 +49,7 @@ export interface DirectorBox { title: string text: string directorImage: string + urlContentSelector?: hrefManual | hrefContent } export interface Event { diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.ts b/src/main/resources/site/parts/timelineNew/timelineNew.ts index 983746d048..8d398c1d6e 100644 --- a/src/main/resources/site/parts/timelineNew/timelineNew.ts +++ b/src/main/resources/site/parts/timelineNew/timelineNew.ts @@ -124,11 +124,11 @@ function parseDirector(event: DirectorBox): TimelineEvent { : undefined, directorImageAltText: event.directorImage ? getImageAlt(event.directorImage) : '', timelineCategory: 'director', - targetUrl: '', + targetUrl: event.urlContentSelector ? getLinkTargetUrl(event) : '', } } -function getLinkTargetUrl(event: SimpleBox): string { +function getLinkTargetUrl(event: SimpleBox | DirectorBox): string { if (event.urlContentSelector?._selected == 'optionLink') { return event.urlContentSelector.optionLink.link ?? '' } diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.xml b/src/main/resources/site/parts/timelineNew/timelineNew.xml index f64229a480..c90b002abb 100644 --- a/src/main/resources/site/parts/timelineNew/timelineNew.xml +++ b/src/main/resources/site/parts/timelineNew/timelineNew.xml @@ -64,6 +64,7 @@ + From e8f5eeadd480919305a7bdca73ba4bbebe206f56 Mon Sep 17 00:00:00 2001 From: Carina Date: Wed, 5 Mar 2025 11:33:36 +0100 Subject: [PATCH 12/24] Fjernet alternativ visning --- .../resources/assets/styles/_timeline.scss | 4 +- src/main/resources/index.d.ts | 1 - .../resources/site/parts/timeline/timeline.ts | 105 ++++++-- .../site/parts/timeline/timeline.tsx | 29 +-- .../site/parts/timeline/timeline.xml | 125 +++++---- .../site/parts/timelineNew/timelineNew.ts | 144 ----------- .../site/parts/timelineNew/timelineNew.tsx | 240 ------------------ .../site/parts/timelineNew/timelineNew.xml | 75 ------ 8 files changed, 157 insertions(+), 566 deletions(-) delete mode 100644 src/main/resources/site/parts/timelineNew/timelineNew.ts delete mode 100644 src/main/resources/site/parts/timelineNew/timelineNew.tsx delete mode 100644 src/main/resources/site/parts/timelineNew/timelineNew.xml diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index 5af58d384a..bbe2a5e025 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -118,7 +118,9 @@ .title { @include roboto-condenced; font-size: 20px; - margin-bottom: 10px; + } + .text { + margin-top: 10px; } } } diff --git a/src/main/resources/index.d.ts b/src/main/resources/index.d.ts index 1b32b467c0..9f3ccbdd8a 100644 --- a/src/main/resources/index.d.ts +++ b/src/main/resources/index.d.ts @@ -72,7 +72,6 @@ declare global { export type SubjectArticleList = _PartComponent<'mimir:subjectArticleList'> export type Table = _PartComponent<'mimir:table'> export type Timeline = _PartComponent<'mimir:timeline'> - export type TimelineNew = _PartComponent<'mimir:timelineNew'> export type UpcomingReleases = _PartComponent<'mimir:upcomingReleases'> export type Variables = _PartComponent<'mimir:variables'> export type VideoEmbed = _PartComponent<'mimir:videoEmbed'> diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts index ad79f4e402..9414313524 100644 --- a/src/main/resources/site/parts/timeline/timeline.ts +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -3,7 +3,14 @@ import { localize } from '/lib/xp/i18n' import { render } from '/lib/enonic/react4xp' import { renderError } from '/lib/ssb/error/error' import { imageUrl, getImageAlt } from '/lib/ssb/utils/imageUtils' -import { type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' +import { + type Event, + type SimpleBox, + type ExpansionBox, + type DirectorBox, + type TimelineElement, + type TimelineEvent, +} from '/lib/types/partTypes/timeline' import { forceArray } from '/lib/ssb/utils/arrayUtils' import { type Timeline as TimelinePartConfig } from '/site/parts/timeline' @@ -24,10 +31,13 @@ function renderPart(req: XP.Request) { const timelineConfig: TimelinePartConfig = part.config const timelineItems: TimelinePartConfig['TimelineItemSet'] = forceArray(timelineConfig.TimelineItemSet) + const timelineProps: TimelineElement[] = timelineItems.map((element) => { + const events: Event[] = element.event ? forceArray(element.event) : [] + const parsedEvents: TimelineEvent[] = parseEvents(events) return { year: element.year, - event: element.event ? parseEvent(forceArray(element.event)) : [], + event: parsedEvents, } }) @@ -47,37 +57,86 @@ function renderPart(req: XP.Request) { }) } -function parseEvent(events: TimelineEvent[]): TimelineEvent[] { - const parsedElements = events.map((event) => { - const image = event.directorImage +function parseEvents(events: Event[]): TimelineEvent[] { + return events.map((event: Event) => { + return parseEvent(event) + }) +} + +function parseEvent(event: Event): TimelineEvent { + if (event.simpleBox) { + return parseSimpleBox(event.simpleBox) + } + + if (event.expansionBox) { + return parseExpansionBox(event.expansionBox) + } + if (event.directorBox) { + return parseDirector(event.directorBox) + } + return { + eventType: '', + title: '', + text: '', + directorImage: undefined, + directorImageAltText: '', + timelineCategory: '', + targetUrl: '', + } +} + +function parseSimpleBox(event: SimpleBox): TimelineEvent { + const simpleBox = { + eventType: 'simpleBox', + title: event.title, + text: event.text ?? '', + directorImage: undefined, + directorImageAltText: '', + timelineCategory: event.timelineCategory, + targetUrl: event.urlContentSelector ? getLinkTargetUrl(event) : '', + } + return simpleBox +} + +function parseExpansionBox(event: ExpansionBox): TimelineEvent { + return { + eventType: 'expansionBox', + title: event.title, + text: event.text, + directorImage: undefined, + directorImageAltText: '', + timelineCategory: event.timelineCategory, + targetUrl: '', + } +} + +function parseDirector(event: DirectorBox): TimelineEvent { + return { + eventType: 'directorBox', + title: event.title, + text: event.text, + directorImage: event.directorImage ? imageUrl({ id: event.directorImage as string, scale: 'block(100,100)', format: 'jpg', }) - : undefined - - const imageAltText = event.directorImage ? getImageAlt(event.directorImage) : '' - return { - ...event, - directorImage: image, - directorImageAltText: imageAltText ?? '', - targetUrl: getLinkTargetUrl(event), - } - }) - - return parsedElements + : undefined, + directorImageAltText: event.directorImage ? getImageAlt(event.directorImage) : '', + timelineCategory: 'director', + targetUrl: event.urlContentSelector ? getLinkTargetUrl(event) : '', + } } -function getLinkTargetUrl(event: TimelineEvent): string { - if (event.urlArticle?._selected == 'optionLink') { - return event.urlArticle.optionLink.link ?? '' +function getLinkTargetUrl(event: SimpleBox | DirectorBox): string { + if (event.urlContentSelector?._selected == 'optionLink') { + return event.urlContentSelector.optionLink.link ?? '' } - if (event.urlArticle?._selected == 'optionXPContent') { - return event.urlArticle.optionXPContent.xpContent + if (event.urlContentSelector?._selected == 'optionXPContent') { + return event.urlContentSelector.optionXPContent.xpContent ? pageUrl({ - id: event.urlArticle.optionXPContent.xpContent, + id: event.urlContentSelector.optionXPContent.xpContent, }) : '' } diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 871734403f..badaf34f19 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -54,12 +54,7 @@ function Timeline(props: TimelineProps) { return elements .map((element) => { if (element.event) { - const filteredEvents = Array.isArray(element.event) - ? element.event.filter((event) => event.category === category) - : element.event.category === category - ? element.event - : null - + const filteredEvents = element.event.filter((event) => event.timelineCategory === category) return filteredEvents ? { ...element, event: filteredEvents } : null } return null @@ -102,7 +97,7 @@ function Timeline(props: TimelineProps) { external={isExternalUrl(event.targetUrl)} href={event.targetUrl} titleText={event.title} - subText={event.ingress} + subText={event.text} /> ) } @@ -115,7 +110,7 @@ function Timeline(props: TimelineProps) { icon={{event.directorImageAltText}} profiled > - {event.ingress} + {event.text} ) } @@ -130,16 +125,16 @@ function Timeline(props: TimelineProps) { ) : ( {event.title} )} - {event.ingress && {event.ingress}} + {event.text && {event.text}}
) } function addEventExpansionBox(event: TimelineEvent) { - const text = event.eventText ? ( + const text = event.text ? (
) : ( @@ -164,19 +159,19 @@ function Timeline(props: TimelineProps) { } function addEvent(event: TimelineEvent) { - if (event.directorImage) { + if (event.eventType === 'directorBox') { return addDirectorCard(event) } - if (event.urlArticle) { + if (event.eventType === 'simpleBox' && event.targetUrl) { return addCategoryLink(event) } - if (event.eventText) { - return addEventExpansionBox(event) + if (event.eventType === 'simpleBox' && !event.targetUrl) { + return addEventBox(event) } - if (!event.eventText && !event.article) { - return addEventBox(event) + if (event.eventType === 'expansionBox') { + return addEventExpansionBox(event) } return addEventBox(event) } diff --git a/src/main/resources/site/parts/timeline/timeline.xml b/src/main/resources/site/parts/timeline/timeline.xml index 69a16e183d..150f92cd4f 100644 --- a/src/main/resources/site/parts/timeline/timeline.xml +++ b/src/main/resources/site/parts/timeline/timeline.xml @@ -9,71 +9,66 @@ - - - - - - - - - - - - - - - - - Bold Italic Underline Strike Subscript Superscript Cut Copy Blockquote - h2 h3 h4 h5 - - - - - - - - - - - - - - - aboutSsb - - - - false - - Velge enten url eller innhold - - - - - - - + + + false + + Velg type hendelse + + + + + + diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.ts b/src/main/resources/site/parts/timelineNew/timelineNew.ts deleted file mode 100644 index 8d398c1d6e..0000000000 --- a/src/main/resources/site/parts/timelineNew/timelineNew.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { getComponent, getContent, pageUrl } from '/lib/xp/portal' -import { localize } from '/lib/xp/i18n' -import { render } from '/lib/enonic/react4xp' -import { renderError } from '/lib/ssb/error/error' -import { imageUrl, getImageAlt } from '/lib/ssb/utils/imageUtils' -import { - type Event, - type SimpleBox, - type ExpansionBox, - type DirectorBox, - type TimelineElement, - type TimelineEvent, -} from '/lib/types/partTypes/timeline' -import { forceArray } from '/lib/ssb/utils/arrayUtils' -import { type Timeline as TimelinePartConfig } from '/site/parts/timeline' - -export function get(req: XP.Request): XP.Response { - try { - return renderPart(req) - } catch (e) { - return renderError(req, 'Error in part: ', e) - } -} - -function renderPart(req: XP.Request) { - const part = getComponent() - const page = getContent() - if (!part || !page) throw new Error('No page or part') - - const language: string = page.language ? page.language : 'nb' - - const timelineConfig: TimelinePartConfig = part.config - const timelineItems: TimelinePartConfig['TimelineItemSet'] = forceArray(timelineConfig.TimelineItemSet) - - const timelineProps: TimelineElement[] = timelineItems.map((element) => { - const events: Event[] = element.event ? forceArray(element.event) : [] - const parsedEvents: TimelineEvent[] = parseEvents(events) - return { - year: element.year, - event: parsedEvents, - } - }) - - const showMoreText: string = localize({ - key: 'button.showMoreYears', - locale: language === 'nb' ? 'no' : language, - }) - - const props = { - timelineElements: timelineProps, - showMoreButtonText: showMoreText ?? 'Vis flere år', - countYear: 5, - } - - return render('site/parts/timelineNew/timelineNew', props, req, { - body: '
', - }) -} - -function parseEvents(events: Event[]): TimelineEvent[] { - return events.map((event: Event) => { - return parseEvent(event) - }) -} - -function parseEvent(event: Event): TimelineEvent { - if (event.simpleBox) { - return parseSimpleBox(event.simpleBox) - } - - if (event.expansionBox) { - return parseExpansionBox(event.expansionBox) - } - if (event.directorBox) { - return parseDirector(event.directorBox) - } - return { - eventType: '', - title: '', - text: '', - directorImage: undefined, - directorImageAltText: '', - timelineCategory: '', - targetUrl: '', - } -} - -function parseSimpleBox(event: SimpleBox): TimelineEvent { - const simpleBox = { - eventType: 'simpleBox', - title: event.title, - text: event.text ?? '', - directorImage: undefined, - directorImageAltText: '', - timelineCategory: event.timelineCategory, - targetUrl: event.urlContentSelector ? getLinkTargetUrl(event) : '', - } - return simpleBox -} - -function parseExpansionBox(event: ExpansionBox): TimelineEvent { - return { - eventType: 'expansionBox', - title: event.title, - text: event.text, - directorImage: undefined, - directorImageAltText: '', - timelineCategory: event.timelineCategory, - targetUrl: '', - } -} - -function parseDirector(event: DirectorBox): TimelineEvent { - return { - eventType: 'directorBox', - title: event.title, - text: event.text, - directorImage: event.directorImage - ? imageUrl({ - id: event.directorImage as string, - scale: 'block(100,100)', - format: 'jpg', - }) - : undefined, - directorImageAltText: event.directorImage ? getImageAlt(event.directorImage) : '', - timelineCategory: 'director', - targetUrl: event.urlContentSelector ? getLinkTargetUrl(event) : '', - } -} - -function getLinkTargetUrl(event: SimpleBox | DirectorBox): string { - if (event.urlContentSelector?._selected == 'optionLink') { - return event.urlContentSelector.optionLink.link ?? '' - } - - if (event.urlContentSelector?._selected == 'optionXPContent') { - return event.urlContentSelector.optionXPContent.xpContent - ? pageUrl({ - id: event.urlContentSelector.optionXPContent.xpContent, - }) - : '' - } - return '' -} diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.tsx b/src/main/resources/site/parts/timelineNew/timelineNew.tsx deleted file mode 100644 index 260b6a6249..0000000000 --- a/src/main/resources/site/parts/timelineNew/timelineNew.tsx +++ /dev/null @@ -1,240 +0,0 @@ -import React, { useEffect, useState, useRef } from 'react' -import { Button, CategoryLink, Card, ExpansionBox, Link, Tag, Text } from '@statisticsnorway/ssb-component-library' -import { ChevronDown } from 'react-feather' -import { type TimelineProps, type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' -import { sanitize } from '/lib/ssb/utils/htmlUtils' -import { usePaginationKeyboardNavigation } from '/lib/ssb/utils/customHooks/paginationHooks' - -function Timeline(props: TimelineProps) { - const { timelineElements, countYear, showMoreButtonText } = props - const [selectedTag, setSelectedTag] = useState('all') - const [filteredElements, setFilteredElements] = useState(timelineElements) - const [active, setActive] = useState(false) - const [timelineCount, setTimeLineCount] = useState(countYear) - const [keyboardNavigation, setKeyboardNavigation] = useState(false) - - const firstNewTimelineRef = useRef(null) - - useEffect(() => { - if (selectedTag !== 'all') { - setFilteredElements(filterElementsByCategory(timelineElements, selectedTag)) - } else { - setFilteredElements(props.timelineElements) - } - }, [selectedTag]) - - useEffect(() => { - if (keyboardNavigation && firstNewTimelineRef.current) { - const firstEvent = firstNewTimelineRef.current.querySelector('.event') - if (firstEvent) { - const firstFocusable = firstEvent.querySelector('a, button, input, [tabindex]:not([tabindex="-1"])') - if (firstFocusable) { - ;(firstFocusable as HTMLElement).focus() - } - } - } - }, [timelineCount]) - - const fetchMoreYear = () => { - setTimeLineCount((prevCount) => prevCount + countYear) - } - - function setFilter(filter: string) { - setSelectedTag(filter) - setActive(true) - setTimeout(() => { - setActive(false) - }, 1000) - } - - const filterElementsByCategory = (elements: TimelineElement[], category: string) => { - if (category === 'all') { - return elements - } - return elements - .map((element) => { - if (element.event) { - const filteredEvents = element.event.filter((event) => event.timelineCategory === category) - return filteredEvents ? { ...element, event: filteredEvents } : null - } - return null - }) - .filter((element) => element !== null) - } - - const handleOnClick = () => { - setKeyboardNavigation(false) - fetchMoreYear() - } - - const handleKeyboardNavigation = usePaginationKeyboardNavigation(() => { - setKeyboardNavigation(true) - fetchMoreYear() - }) - - function isExternalUrl(url?: string): boolean { - return !!url && !url.startsWith('/') && !url.includes('ssb.no') - } - - function renderShowMoreButton() { - return ( - - ) - } - - function addCategoryLink(event: TimelineEvent) { - return ( - - ) - } - - function addDirectorCard(event: TimelineEvent) { - return ( - } - profiled - > - {event.text} - - ) - } - - function addEventBox(event: TimelineEvent) { - return ( -
- {event.targetUrl ? ( - - {event.title} - - ) : ( - {event.title} - )} - {event.text && {event.text}} -
- ) - } - - function addEventExpansionBox(event: TimelineEvent) { - const text = event.text ? ( -
- ) : ( - '' - ) - - return - } - - function addEvents(events: TimelineEvent[]) { - return ( -
- {events.map((event, index) => { - return ( -
- {addEvent(event)} -
- ) - })} -
- ) - } - - function addEvent(event: TimelineEvent) { - if (event.eventType === 'directorBox') { - return addDirectorCard(event) - } - if (event.eventType === 'simpleBox' && event.targetUrl) { - return addCategoryLink(event) - } - - if (event.eventType === 'simpleBox' && !event.targetUrl) { - return addEventBox(event) - } - - if (event.eventType === 'expansionBox') { - return addEventExpansionBox(event) - } - return addEventBox(event) - } - - function addTimelineYear(timeline: TimelineElement, i: number) { - const events = timeline.event ? (Array.isArray(timeline.event) ? timeline.event : [timeline.event]) : [] - if (events.length === 0) { - return null - } - return ( -
-
- {timeline.year} -
-
- {events?.length && addEvents(events)} -
- ) - } - - function addFilter() { - return ( -
- setFilter('all')}> - Vis alt - - setFilter('statistic')}> - Statistikk - - setFilter('aboutSsb')}> - Om SSB - - setFilter('director')}> - Direktører - -
- ) - } - - function addTimeLine() { - return ( -
-
-
- {filteredElements?.slice(0, timelineCount).map((timeline, i) => { - return <>{addTimelineYear(timeline, i)} - })} -
- {timelineElements.length > countYear && renderShowMoreButton()} -
- ) - } - - return ( -
- {addFilter()} - {addTimeLine()} -
- ) -} - -export default (props: TimelineProps) => diff --git a/src/main/resources/site/parts/timelineNew/timelineNew.xml b/src/main/resources/site/parts/timelineNew/timelineNew.xml deleted file mode 100644 index c90b002abb..0000000000 --- a/src/main/resources/site/parts/timelineNew/timelineNew.xml +++ /dev/null @@ -1,75 +0,0 @@ - - Tidslinje Ny -
- - - - - - - - - - - false - - Velg type hendelse - - - - - - - - -
-
From 79fdc95455d7f04a2634ded895fb3086b0d16eed Mon Sep 17 00:00:00 2001 From: Carina Date: Wed, 5 Mar 2025 13:06:20 +0100 Subject: [PATCH 13/24] Lagt til property for visning antall aar og fikset Vis flere knappen --- src/main/resources/site/parts/timeline/timeline.ts | 2 +- src/main/resources/site/parts/timeline/timeline.tsx | 11 +++-------- src/main/resources/site/parts/timeline/timeline.xml | 6 ++++++ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts index 9414313524..544dfa3a6f 100644 --- a/src/main/resources/site/parts/timeline/timeline.ts +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -49,7 +49,7 @@ function renderPart(req: XP.Request) { const props = { timelineElements: timelineProps, showMoreButtonText: showMoreText ?? 'Vis flere år', - countYear: 5, + countYear: timelineConfig.numberOfYear ?? 10, } return render('site/parts/timeline/timeline', props, req, { diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index badaf34f19..e2f01e2432 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -9,7 +9,6 @@ function Timeline(props: TimelineProps) { const { timelineElements, countYear, showMoreButtonText } = props const [selectedTag, setSelectedTag] = useState('all') const [filteredElements, setFilteredElements] = useState(timelineElements) - const [active, setActive] = useState(false) const [timelineCount, setTimeLineCount] = useState(countYear) const [keyboardNavigation, setKeyboardNavigation] = useState(false) @@ -36,15 +35,11 @@ function Timeline(props: TimelineProps) { }, [timelineCount]) const fetchMoreYear = () => { - setTimeLineCount((prevCount) => prevCount + countYear) + setTimeLineCount((prevCount) => Number(prevCount) + Number(countYear)) } function setFilter(filter: string) { setSelectedTag(filter) - setActive(true) - setTimeout(() => { - setActive(false) - }, 1000) } const filterElementsByCategory = (elements: TimelineElement[], category: string) => { @@ -217,14 +212,14 @@ function Timeline(props: TimelineProps) { function addTimeLine() { return ( -
+
{filteredElements?.slice(0, timelineCount).map((timeline, i) => { return <>{addTimelineYear(timeline, i)} })}
- {timelineElements.length > countYear && renderShowMoreButton()} + {timelineElements.length > countYear && timelineElements.length > timelineCount && renderShowMoreButton()}
) } diff --git a/src/main/resources/site/parts/timeline/timeline.xml b/src/main/resources/site/parts/timeline/timeline.xml index 150f92cd4f..7f32a6605d 100644 --- a/src/main/resources/site/parts/timeline/timeline.xml +++ b/src/main/resources/site/parts/timeline/timeline.xml @@ -71,5 +71,11 @@ + + + Hvor mange år skal vises før man må trykke Vis flere år + 10 + + From 6a0b345fa348c0ec734cbece1cea971ab066ee0d Mon Sep 17 00:00:00 2001 From: Carina Date: Wed, 5 Mar 2025 16:53:24 +0100 Subject: [PATCH 14/24] Midtstilt innhold hvis fullbredde --- .../resources/assets/styles/_timeline.scss | 40 ++++++++++++++----- .../site/parts/timeline/timeline.tsx | 16 ++++---- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index bbe2a5e025..ee22542f9d 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -1,4 +1,9 @@ .ssb-timeline { + .timeline-container { + display: flex; + justify-content: center; + } + .filter { display: flex; flex-wrap: wrap; @@ -14,10 +19,11 @@ } } } + .timeline { position: relative; - margin-right: 40px; - padding-left: 200px; + padding-left: 20px; + width: 740px; .circle { width: 16px; @@ -46,9 +52,7 @@ } .timeline-elements { - padding-top: 25px; - padding-left: 0; - padding-bottom: 50px; + padding: 25px 0; list-style: none; } @@ -124,19 +128,33 @@ } } } + } + + .button-more { + left: -20px; + top: -30px; + position: relative; + } - @include media-breakpoint-down(lg) { + @include media-breakpoint-down(lg) { + .timeline-container { + justify-content: start; + } + + .timeline { padding-left: 20px; margin-right: 0; + width: 100%; .timeline-content { width: 100%; + left: -10px; + + .events { + width: 100%; + min-width: 0; + } } } } - .button-more { - left: -20px; - top: -30px; - position: relative; - } } diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index e2f01e2432..916ff377d6 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -212,14 +212,16 @@ function Timeline(props: TimelineProps) { function addTimeLine() { return ( -
-
-
- {filteredElements?.slice(0, timelineCount).map((timeline, i) => { - return <>{addTimelineYear(timeline, i)} - })} +
+
+
+
+ {filteredElements?.slice(0, timelineCount).map((timeline, i) => { + return <>{addTimelineYear(timeline, i)} + })} +
+ {timelineElements.length > countYear && timelineElements.length > timelineCount && renderShowMoreButton()}
- {timelineElements.length > countYear && timelineElements.length > timelineCount && renderShowMoreButton()}
) } From 4c02b78b9e44cc72282626a7d437e83d795caa6b Mon Sep 17 00:00:00 2001 From: Carina Date: Wed, 5 Mar 2025 17:46:29 +0100 Subject: [PATCH 15/24] Lagt til tittel og ingress --- .../resources/assets/styles/_timeline.scss | 13 ++++++++- .../resources/lib/types/partTypes/timeline.ts | 2 ++ .../resources/site/parts/timeline/timeline.ts | 2 ++ .../site/parts/timeline/timeline.tsx | 23 ++++++++++++++-- .../site/parts/timeline/timeline.xml | 27 ++++++++++++++----- 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index ee22542f9d..f18c6488e0 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -1,4 +1,11 @@ .ssb-timeline { + .title-ingress-wrapper { + margin-bottom: 30px; + .ingress { + font-size: 1.25rem; + } + } + .timeline-container { display: flex; justify-content: center; @@ -9,7 +16,7 @@ flex-wrap: wrap; gap: 0.75rem; margin-top: 1.5rem; - margin-bottom: 8rem; + margin-bottom: 6rem; .ssb-tag { &.active { @@ -137,6 +144,10 @@ } @include media-breakpoint-down(lg) { + .filter { + margin-bottom: 4rem; + } + .timeline-container { justify-content: start; } diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts index 20f5b2499b..7fcc8878a3 100644 --- a/src/main/resources/lib/types/partTypes/timeline.ts +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -1,4 +1,6 @@ export interface TimelineProps { + title: string + ingress: string timelineElements: TimelineElement[] showMoreButtonText: string countYear: number diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts index 544dfa3a6f..c20ba9de07 100644 --- a/src/main/resources/site/parts/timeline/timeline.ts +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -47,6 +47,8 @@ function renderPart(req: XP.Request) { }) const props = { + title: timelineConfig.title, + ingress: timelineConfig.ingress, timelineElements: timelineProps, showMoreButtonText: showMoreText ?? 'Vis flere år', countYear: timelineConfig.numberOfYear ?? 10, diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 916ff377d6..e226f685d8 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -1,12 +1,21 @@ import React, { useEffect, useState, useRef } from 'react' -import { Button, CategoryLink, Card, ExpansionBox, Link, Tag, Text } from '@statisticsnorway/ssb-component-library' +import { + Button, + CategoryLink, + Card, + ExpansionBox, + Link, + Tag, + Text, + Title, +} from '@statisticsnorway/ssb-component-library' import { ChevronDown } from 'react-feather' import { type TimelineProps, type TimelineElement, type TimelineEvent } from '/lib/types/partTypes/timeline' import { sanitize } from '/lib/ssb/utils/htmlUtils' import { usePaginationKeyboardNavigation } from '/lib/ssb/utils/customHooks/paginationHooks' function Timeline(props: TimelineProps) { - const { timelineElements, countYear, showMoreButtonText } = props + const { timelineElements, countYear, showMoreButtonText, title, ingress } = props const [selectedTag, setSelectedTag] = useState('all') const [filteredElements, setFilteredElements] = useState(timelineElements) const [timelineCount, setTimeLineCount] = useState(countYear) @@ -210,6 +219,15 @@ function Timeline(props: TimelineProps) { ) } + function addTitle() { + return ( +
+ {title} +

{ingress}

+
+ ) + } + function addTimeLine() { return (
@@ -228,6 +246,7 @@ function Timeline(props: TimelineProps) { return (
+ {title && addTitle()} {addFilter()} {addTimeLine()}
diff --git a/src/main/resources/site/parts/timeline/timeline.xml b/src/main/resources/site/parts/timeline/timeline.xml index 7f32a6605d..5aef52f75e 100644 --- a/src/main/resources/site/parts/timeline/timeline.xml +++ b/src/main/resources/site/parts/timeline/timeline.xml @@ -1,8 +1,27 @@ Tidslinje
+ + + + + + + + + + + + + + Hvor mange år skal vises før man må trykke Vis flere år + 10 + + + + - + @@ -71,11 +90,5 @@ - - - Hvor mange år skal vises før man må trykke Vis flere år - 10 - -
From 5178998773db01898f79f633e907a4abe4fe7002 Mon Sep 17 00:00:00 2001 From: Carina Date: Thu, 6 Mar 2025 09:39:53 +0100 Subject: [PATCH 16/24] designendringer tittel og chip --- .../resources/assets/styles/_timeline.scss | 30 ++++++++++++++----- .../timelineCategory/timelineCategory.xml | 1 - .../site/parts/timeline/timeline.tsx | 12 +++++--- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index f18c6488e0..597a3fb5bc 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -1,22 +1,31 @@ .ssb-timeline { + .title-filter-container { + display: grid; + grid-template-columns: repeat(12, 1fr); + margin-top: 4rem; + } + .title-ingress-wrapper { - margin-bottom: 30px; + grid-column: 2 / span 10; + + .title { + display: block; + margin: 0 auto; + } .ingress { + display: block; + margin: 0 auto; font-size: 1.25rem; } } - .timeline-container { - display: flex; - justify-content: center; - } - .filter { display: flex; + grid-column: 3 / span 8; flex-wrap: wrap; gap: 0.75rem; - margin-top: 1.5rem; - margin-bottom: 6rem; + margin-top: 5rem; + margin-bottom: 4rem; .ssb-tag { &.active { @@ -27,6 +36,11 @@ } } + .timeline-container { + display: flex; + justify-content: center; + } + .timeline { position: relative; padding-left: 20px; diff --git a/src/main/resources/site/mixins/timelineCategory/timelineCategory.xml b/src/main/resources/site/mixins/timelineCategory/timelineCategory.xml index 13314c47f8..9f0136a2f8 100644 --- a/src/main/resources/site/mixins/timelineCategory/timelineCategory.xml +++ b/src/main/resources/site/mixins/timelineCategory/timelineCategory.xml @@ -7,7 +7,6 @@ - aboutSsb diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index e226f685d8..b720b1f5a9 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -221,8 +221,10 @@ function Timeline(props: TimelineProps) { function addTitle() { return ( -
- {title} +
+ + {title} +

{ingress}

) @@ -246,8 +248,10 @@ function Timeline(props: TimelineProps) { return (
- {title && addTitle()} - {addFilter()} +
+ {title && addTitle()} + {addFilter()} +
{addTimeLine()}
) From a433f77506ba5a08ace12b1a1c891e8f6c9ec513 Mon Sep 17 00:00:00 2001 From: Carina Date: Thu, 6 Mar 2025 12:11:43 +0100 Subject: [PATCH 17/24] Fikser mer styling --- .../resources/assets/styles/_timeline.scss | 68 +++++++++++-------- .../site/parts/timeline/timeline.tsx | 46 +++++++------ 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index 597a3fb5bc..d0124d85df 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -1,37 +1,43 @@ .ssb-timeline { - .title-filter-container { + .title-container { display: grid; grid-template-columns: repeat(12, 1fr); margin-top: 4rem; - } - .title-ingress-wrapper { - grid-column: 2 / span 10; + .title-ingress-wrapper { + grid-column: 2 / span 10; - .title { - display: block; - margin: 0 auto; - } - .ingress { - display: block; - margin: 0 auto; - font-size: 1.25rem; + .title { + display: block; + margin: 0 auto; + } + .ingress { + display: block; + margin: 0 auto; + font-size: 1.25rem; + } } } - .filter { + .filter-container { display: flex; - grid-column: 3 / span 8; - flex-wrap: wrap; - gap: 0.75rem; - margin-top: 5rem; - margin-bottom: 4rem; - - .ssb-tag { - &.active { - background: $ssb-dark-5; - border: 2px solid $ssb-dark-5; - color: $ssb-white; + justify-content: center; + + .filter { + display: flex; + grid-column: 3 / span 8; + flex-wrap: wrap; + gap: 0.75rem; + margin-top: 5rem; + margin-bottom: 4rem; + width: 740px; + + .ssb-tag { + &.active { + background: $ssb-dark-5; + border: 2px solid $ssb-dark-5; + color: $ssb-white; + } } } } @@ -81,7 +87,7 @@ left: -20px; position: relative; margin-bottom: 30px; - max-width: 740px; + //max-width: 740px; .year { width: 180px; @@ -158,8 +164,16 @@ } @include media-breakpoint-down(lg) { - .filter { - margin-bottom: 4rem; + .title-container { + display: block; + margin-top: 2rem; + } + + .filter-container { + .filter { + margin-top: 3rem; + margin-bottom: 4rem; + } } .timeline-container { diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index b720b1f5a9..e95f2015a3 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -202,30 +202,34 @@ function Timeline(props: TimelineProps) { function addFilter() { return ( -
- setFilter('all')}> - Vis alt - - setFilter('statistic')}> - Statistikk - - setFilter('aboutSsb')}> - Om SSB - - setFilter('director')}> - Direktører - +
+
+ setFilter('all')}> + Vis alt + + setFilter('statistic')}> + Statistikk + + setFilter('aboutSsb')}> + Om SSB + + setFilter('director')}> + Direktører + +
) } function addTitle() { return ( -
- - {title} - -

{ingress}

+
+
+ + {title} + +

{ingress}

+
) } @@ -248,10 +252,8 @@ function Timeline(props: TimelineProps) { return (
-
- {title && addTitle()} - {addFilter()} -
+ {title && addTitle()} + {addFilter()} {addTimeLine()}
) From f7df74fc1149d62459b0e2587df894120dc53232 Mon Sep 17 00:00:00 2001 From: Carina Date: Thu, 6 Mar 2025 13:09:22 +0100 Subject: [PATCH 18/24] Mer designmikk --- .../resources/assets/styles/_timeline.scss | 32 +++++++++++-------- .../site/parts/timeline/timeline.tsx | 1 - 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index d0124d85df..716c6c572c 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -87,7 +87,6 @@ left: -20px; position: relative; margin-bottom: 30px; - //max-width: 740px; .year { width: 180px; @@ -97,6 +96,19 @@ position: absolute; align-content: center; + &:after { + content: ''; + position: absolute; + top: 0; + right: -1px; + width: 0; + height: 0; + border-top: 40px solid transparent; + border-bottom: 40px solid transparent; + border-right: 20px solid #f0f8f9; + border-radius: 4px; + } + span { @include roboto-condenced; color: #fff; @@ -105,17 +117,6 @@ } } - .triangle { - position: absolute; - width: 0; - height: 0; - border-top: 40px solid transparent; - border-bottom: 40px solid transparent; - border-right: 20px solid #f0f8f9; - border-radius: 4px; - left: 160px; - } - .events { padding-top: 90px; width: 100%; @@ -147,7 +148,8 @@ padding: 20px 40px; width: 100%; .title { - @include roboto-condenced; + @include roboto; + font-weight: bold; font-size: 20px; } .text { @@ -195,5 +197,9 @@ } } } + + .button-more { + left: -10px; + } } } diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index e95f2015a3..7ac337cf3f 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -194,7 +194,6 @@ function Timeline(props: TimelineProps) {
{timeline.year}
-
{events?.length && addEvents(events)}
) From 36194e7d8b4089eb56e19a050a480f1258739367 Mon Sep 17 00:00:00 2001 From: Carina Date: Thu, 6 Mar 2025 14:50:07 +0100 Subject: [PATCH 19/24] designendringer --- src/main/resources/assets/styles/_timeline.scss | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index 716c6c572c..8be4c532fa 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -183,16 +183,14 @@ } .timeline { - padding-left: 20px; - margin-right: 0; + padding-left: 10px; width: 100%; .timeline-content { - width: 100%; + width: calc(100% + 10px); left: -10px; .events { - width: 100%; min-width: 0; } } From c7abd718e589360b80fa1d20dd2ef034ff61f67e Mon Sep 17 00:00:00 2001 From: Carina Date: Thu, 6 Mar 2025 14:57:08 +0100 Subject: [PATCH 20/24] Mer mikk --- src/main/resources/assets/styles/_timeline.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index 8be4c532fa..9b9f610305 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -193,6 +193,10 @@ .events { min-width: 0; } + + .event-box { + padding: 20px; + } } } From c2f7213e31d98eb77f8f034f157c22fc2864d5b5 Mon Sep 17 00:00:00 2001 From: Carina Date: Thu, 6 Mar 2025 15:38:22 +0100 Subject: [PATCH 21/24] Fikset Vis flere knapp ved filtrering --- .../site/parts/timeline/timeline.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 7ac337cf3f..58decb91e6 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -25,7 +25,8 @@ function Timeline(props: TimelineProps) { useEffect(() => { if (selectedTag !== 'all') { - setFilteredElements(filterElementsByCategory(timelineElements, selectedTag)) + const filteredElementsResult = filterElementsByCategory(timelineElements, selectedTag) + setFilteredElements(filteredElementsResult) } else { setFilteredElements(props.timelineElements) } @@ -55,15 +56,16 @@ function Timeline(props: TimelineProps) { if (category === 'all') { return elements } - return elements - .map((element) => { - if (element.event) { - const filteredEvents = element.event.filter((event) => event.timelineCategory === category) - return filteredEvents ? { ...element, event: filteredEvents } : null + const filteredElements: TimelineElement[] = [] + elements.forEach((element) => { + if (element.event) { + const filteredEvents = element.event.filter((event) => event.timelineCategory === category) + if (filteredEvents.length > 0) { + filteredElements.push({ ...element, event: filteredEvents }) } - return null - }) - .filter((element) => element !== null) + } + }) + return filteredElements } const handleOnClick = () => { @@ -243,7 +245,7 @@ function Timeline(props: TimelineProps) { return <>{addTimelineYear(timeline, i)} })}
- {timelineElements.length > countYear && timelineElements.length > timelineCount && renderShowMoreButton()} + {filteredElements.length > countYear && filteredElements.length > timelineCount && renderShowMoreButton()}
) From 03c30875f71e68d162ec21d33459e7505a38bd61 Mon Sep 17 00:00:00 2001 From: Carina Date: Thu, 6 Mar 2025 15:49:46 +0100 Subject: [PATCH 22/24] Fikset typescriptfeil --- .../resources/lib/types/partTypes/timeline.ts | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts index 7fcc8878a3..d0b8ab657f 100644 --- a/src/main/resources/lib/types/partTypes/timeline.ts +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -21,36 +21,23 @@ export interface TimelineEvent { timelineCategory?: string targetUrl?: string } - -/* export interface TimelineEventOld { - - title: string - ingress?: string - eventText?: string - directorImage?: string - directorImageAltText?: string - category?: string - article?: string - urlArticle?: hrefManual | hrefContent - targetUrl?: string -} */ export interface SimpleBox { title: string - text: string + text?: string timelineCategory: string urlContentSelector?: hrefManual | hrefContent } export interface ExpansionBox { title: string - text: string + text?: string timelineCategory: string } export interface DirectorBox { title: string - text: string - directorImage: string + text?: string + directorImage?: string urlContentSelector?: hrefManual | hrefContent } From 4b463c3d04b8ae1f1834652ff01f901c17ffb028 Mon Sep 17 00:00:00 2001 From: Carina Date: Fri, 7 Mar 2025 09:43:34 +0100 Subject: [PATCH 23/24] Refaktorering --- .../resources/site/parts/timeline/timeline.ts | 4 +- .../site/parts/timeline/timeline.tsx | 45 +++++++++---------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts index c20ba9de07..f73429d436 100644 --- a/src/main/resources/site/parts/timeline/timeline.ts +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -32,7 +32,7 @@ function renderPart(req: XP.Request) { const timelineConfig: TimelinePartConfig = part.config const timelineItems: TimelinePartConfig['TimelineItemSet'] = forceArray(timelineConfig.TimelineItemSet) - const timelineProps: TimelineElement[] = timelineItems.map((element) => { + const timelineElements: TimelineElement[] = timelineItems.map((element) => { const events: Event[] = element.event ? forceArray(element.event) : [] const parsedEvents: TimelineEvent[] = parseEvents(events) return { @@ -49,7 +49,7 @@ function renderPart(req: XP.Request) { const props = { title: timelineConfig.title, ingress: timelineConfig.ingress, - timelineElements: timelineProps, + timelineElements, showMoreButtonText: showMoreText ?? 'Vis flere år', countYear: timelineConfig.numberOfYear ?? 10, } diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 58decb91e6..088ad64100 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef } from 'react' +import React, { useEffect, useState, useRef, useMemo } from 'react' import { Button, CategoryLink, @@ -17,20 +17,33 @@ import { usePaginationKeyboardNavigation } from '/lib/ssb/utils/customHooks/pagi function Timeline(props: TimelineProps) { const { timelineElements, countYear, showMoreButtonText, title, ingress } = props const [selectedTag, setSelectedTag] = useState('all') - const [filteredElements, setFilteredElements] = useState(timelineElements) const [timelineCount, setTimeLineCount] = useState(countYear) const [keyboardNavigation, setKeyboardNavigation] = useState(false) const firstNewTimelineRef = useRef(null) - useEffect(() => { + const filterElementsByCategory = (elements: TimelineElement[], category: string) => { + if (category === 'all') { + return elements + } + const filteredElements: TimelineElement[] = [] + elements.forEach((element) => { + if (element.event) { + const filteredEvents = element.event.filter((event) => event.timelineCategory === category) + if (filteredEvents.length > 0) { + filteredElements.push({ ...element, event: filteredEvents }) + } + } + }) + return filteredElements + } + + const filteredElements = useMemo(() => { if (selectedTag !== 'all') { - const filteredElementsResult = filterElementsByCategory(timelineElements, selectedTag) - setFilteredElements(filteredElementsResult) - } else { - setFilteredElements(props.timelineElements) + return filterElementsByCategory(timelineElements, selectedTag) } - }, [selectedTag]) + return timelineElements + }, [selectedTag, timelineElements]) useEffect(() => { if (keyboardNavigation && firstNewTimelineRef.current) { @@ -52,22 +65,6 @@ function Timeline(props: TimelineProps) { setSelectedTag(filter) } - const filterElementsByCategory = (elements: TimelineElement[], category: string) => { - if (category === 'all') { - return elements - } - const filteredElements: TimelineElement[] = [] - elements.forEach((element) => { - if (element.event) { - const filteredEvents = element.event.filter((event) => event.timelineCategory === category) - if (filteredEvents.length > 0) { - filteredElements.push({ ...element, event: filteredEvents }) - } - } - }) - return filteredElements - } - const handleOnClick = () => { setKeyboardNavigation(false) fetchMoreYear() From 459dccabbcc4e42c4d5f6b48beb3e8b215ed5579 Mon Sep 17 00:00:00 2001 From: Carina Date: Fri, 7 Mar 2025 11:44:33 +0100 Subject: [PATCH 24/24] =?UTF-8?q?Endringer=20p=C3=A5=20parten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/assets/styles/_timeline.scss | 2 +- src/main/resources/lib/types/partTypes/timeline.ts | 1 + src/main/resources/site/parts/timeline/timeline.ts | 1 + src/main/resources/site/parts/timeline/timeline.tsx | 4 ++-- src/main/resources/site/parts/timeline/timeline.xml | 8 +++++++- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/resources/assets/styles/_timeline.scss b/src/main/resources/assets/styles/_timeline.scss index 9b9f610305..5d3d3418c6 100644 --- a/src/main/resources/assets/styles/_timeline.scss +++ b/src/main/resources/assets/styles/_timeline.scss @@ -3,6 +3,7 @@ display: grid; grid-template-columns: repeat(12, 1fr); margin-top: 4rem; + margin-bottom: 5rem; .title-ingress-wrapper { grid-column: 2 / span 10; @@ -28,7 +29,6 @@ grid-column: 3 / span 8; flex-wrap: wrap; gap: 0.75rem; - margin-top: 5rem; margin-bottom: 4rem; width: 740px; diff --git a/src/main/resources/lib/types/partTypes/timeline.ts b/src/main/resources/lib/types/partTypes/timeline.ts index d0b8ab657f..ba5e93b84f 100644 --- a/src/main/resources/lib/types/partTypes/timeline.ts +++ b/src/main/resources/lib/types/partTypes/timeline.ts @@ -2,6 +2,7 @@ export interface TimelineProps { title: string ingress: string timelineElements: TimelineElement[] + showFilter: boolean showMoreButtonText: string countYear: number } diff --git a/src/main/resources/site/parts/timeline/timeline.ts b/src/main/resources/site/parts/timeline/timeline.ts index f73429d436..b792985596 100644 --- a/src/main/resources/site/parts/timeline/timeline.ts +++ b/src/main/resources/site/parts/timeline/timeline.ts @@ -50,6 +50,7 @@ function renderPart(req: XP.Request) { title: timelineConfig.title, ingress: timelineConfig.ingress, timelineElements, + showFilter: timelineConfig.showFilter, showMoreButtonText: showMoreText ?? 'Vis flere år', countYear: timelineConfig.numberOfYear ?? 10, } diff --git a/src/main/resources/site/parts/timeline/timeline.tsx b/src/main/resources/site/parts/timeline/timeline.tsx index 088ad64100..02cf08f014 100644 --- a/src/main/resources/site/parts/timeline/timeline.tsx +++ b/src/main/resources/site/parts/timeline/timeline.tsx @@ -15,7 +15,7 @@ import { sanitize } from '/lib/ssb/utils/htmlUtils' import { usePaginationKeyboardNavigation } from '/lib/ssb/utils/customHooks/paginationHooks' function Timeline(props: TimelineProps) { - const { timelineElements, countYear, showMoreButtonText, title, ingress } = props + const { timelineElements, countYear, showMoreButtonText, title, ingress, showFilter } = props const [selectedTag, setSelectedTag] = useState('all') const [timelineCount, setTimeLineCount] = useState(countYear) const [keyboardNavigation, setKeyboardNavigation] = useState(false) @@ -251,7 +251,7 @@ function Timeline(props: TimelineProps) { return (
{title && addTitle()} - {addFilter()} + {showFilter && addFilter()} {addTimeLine()}
) diff --git a/src/main/resources/site/parts/timeline/timeline.xml b/src/main/resources/site/parts/timeline/timeline.xml index 5aef52f75e..c2711a222c 100644 --- a/src/main/resources/site/parts/timeline/timeline.xml +++ b/src/main/resources/site/parts/timeline/timeline.xml @@ -12,6 +12,12 @@ + + + + right + + Hvor mange år skal vises før man må trykke Vis flere år @@ -21,7 +27,7 @@ - +