From 345369172ca145e3c1868c44f446040ae210d8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 20 Nov 2024 10:06:24 +0000 Subject: [PATCH 01/20] feat: init --- apps/web/screens/Grants/Grant/Grant.tsx | 2 +- .../src/lib/generated/contentfulTypes.d.ts | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/apps/web/screens/Grants/Grant/Grant.tsx b/apps/web/screens/Grants/Grant/Grant.tsx index d3f4caf7aa06..fbbc9f66dae2 100644 --- a/apps/web/screens/Grants/Grant/Grant.tsx +++ b/apps/web/screens/Grants/Grant/Grant.tsx @@ -22,6 +22,7 @@ import { } from '@island.is/web/graphql/schema' import { useLinkResolver } from '@island.is/web/hooks' import { withMainLayout } from '@island.is/web/layouts/main' +import { CustomNextError } from '@island.is/web/units/errors' import { webRichText } from '@island.is/web/utils/richText' import { @@ -32,7 +33,6 @@ import SidebarLayout from '../../Layouts/SidebarLayout' import { GET_GRANT_QUERY } from '../../queries' import { m } from '../messages' import { GrantSidebar } from './GrantSidebar' -import { CustomNextError } from '@island.is/web/units/errors' const GrantSinglePage: CustomScreen = ({ grant, locale }) => { const { formatMessage } = useIntl() diff --git a/libs/cms/src/lib/generated/contentfulTypes.d.ts b/libs/cms/src/lib/generated/contentfulTypes.d.ts index 1391d3119346..d5638066add7 100644 --- a/libs/cms/src/lib/generated/contentfulTypes.d.ts +++ b/libs/cms/src/lib/generated/contentfulTypes.d.ts @@ -1886,6 +1886,43 @@ export interface IGrant extends Entry { } } +export interface IGrantCardsListFields { + /** Title */ + grantCardListTitle: string + + /** Display title? */ + grantCardsListDisplayTitle?: boolean | undefined + + /** Funds */ + grantCardListFunds?: IFund[] | undefined + + /** Max number of cards */ + grantCardsListMaxNumberOfCards?: number | undefined + + /** Sorting */ + grantCardsListSorting?: + | 'Alphabetical' + | 'Most recently updated first' + | undefined +} + +export interface IGrantCardsList extends Entry { + sys: { + id: string + type: string + createdAt: string + updatedAt: string + locale: string + contentType: { + sys: { + id: 'grantCardsList' + linkType: 'ContentType' + type: 'Link' + } + } + } +} + export interface IGraphCardFields { /** Graph Title */ graphTitle: string @@ -5297,6 +5334,7 @@ export type CONTENT_TYPE = | 'genericTag' | 'genericTagGroup' | 'grant' + | 'grantCardsList' | 'graphCard' | 'groupedMenu' | 'hnippTemplate' From 1769fa8768646583c0e062c5c2b50e2192b1495f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 20 Nov 2024 13:43:07 +0000 Subject: [PATCH 02/20] feat: slice works --- .../GrantCardsList/GrantCardsListSlice.css.ts | 71 +++++++++++++++++++ .../GrantCardsList/GrantCardsListSlice.tsx | 59 +++++++++++++++ apps/web/screens/queries/fragments.ts | 15 ++++ apps/web/utils/richText.tsx | 5 ++ libs/cms/src/lib/cms.elasticsearch.service.ts | 25 +++++++ libs/cms/src/lib/dto/getGrants.input.ts | 5 ++ .../src/lib/models/grantCardsList.model.ts | 59 +++++++++++++++ libs/cms/src/lib/unions/slice.union.ts | 9 +++ 8 files changed, 248 insertions(+) create mode 100644 apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.css.ts create mode 100644 apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx create mode 100644 libs/cms/src/lib/models/grantCardsList.model.ts diff --git a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.css.ts b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.css.ts new file mode 100644 index 000000000000..acf08de11bef --- /dev/null +++ b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.css.ts @@ -0,0 +1,71 @@ +import { theme, themeUtils } from '@island.is/island-ui/theme' +import { style } from '@vanilla-extract/css' + +export const unorderedList = style({ + listStyle: 'none', + marginTop: 16, + marginBottom: 16, + selectors: { + 'ul &': { + marginTop: 0, + marginBottom: 0, + }, + }, +}) + +export const listItem = style({ + ...themeUtils.responsiveStyle({ + xs: { + selectors: { + 'ol &': { + listStyle: 'none', + position: 'relative', + paddingLeft: theme.spacing[3], + }, + 'ol ol &': { + paddingLeft: theme.spacing[3], + }, + 'ol &:before': { + position: 'absolute', + top: '2px', + left: '8px', + counterIncrement: 'section', + content: 'counters(section, ".") " "', + color: theme.color.red400, + fontWeight: theme.typography.semiBold, + transform: 'translate(-100%, 0)', + }, + 'ul &': { + position: 'relative', + paddingLeft: theme.spacing[3], + }, + 'ul &:before': { + content: '""', + position: 'absolute', + top: '10px', + left: 0, + borderRadius: '50%', + border: `4px solid red`, + counterIncrement: 'none', + transform: 'none', + }, + '&:not(:first-child), ul ul &:first-child, ol ol &:first-child': { + marginTop: 12, + }, + '&:not(:last-child), ul ul &:last-child, ol ol &:last-child': { + marginBottom: 12, + }, + }, + }, + md: { + selectors: { + '&:not(:first-child), ul ul &:first-child, ol ol &:first-child': { + marginTop: 14, + }, + '&:not(:last-child), ul ul &:last-child, ol ol &:last-child': { + marginBottom: 14, + }, + }, + }, + }), +}) diff --git a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx new file mode 100644 index 000000000000..d706a67a5ba0 --- /dev/null +++ b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx @@ -0,0 +1,59 @@ +import { useQuery } from '@apollo/client' + +import { Box, LinkV2, Text } from '@island.is/island-ui/core' +import { + ContentLanguage, + GrantCardsList, + Query, +} from '@island.is/web/graphql/schema' +import { LinkType, useLinkResolver } from '@island.is/web/hooks' +import { useI18n } from '@island.is/web/i18n' +import { GET_GRANTS_QUERY } from '@island.is/web/screens/queries' + +import * as styles from './GrantCardsListSlice.css' + +interface SliceProps { + slice: GrantCardsList +} + +export const GrantCardsListSlice = ({ slice }: SliceProps) => { + const { activeLocale } = useI18n() + const { linkResolver } = useLinkResolver() + + const { data, loading, error } = useQuery(GET_GRANTS_QUERY, { + variables: { + input: { + lang: activeLocale as ContentLanguage, + size: slice.maxNumberOfCards ?? 4, + funds: slice.funds ? slice.funds.map((f) => f.id).join(',') : undefined, + }, + }, + }) + + console.log(slice) + + if (!slice.funds) { + return undefined + } + + return ( + + {slice.funds.map((fund) => { + if (!fund.link) { + return null + } + return ( + + + {fund.title} + + + ) + })} + + ) +} diff --git a/apps/web/screens/queries/fragments.ts b/apps/web/screens/queries/fragments.ts index bae909c52854..6f5dc5e43280 100644 --- a/apps/web/screens/queries/fragments.ts +++ b/apps/web/screens/queries/fragments.ts @@ -792,6 +792,20 @@ export const slices = gql` aspectRatio } + fragment GrantCardsListFields on GrantCardsList { + title + displayTitle + funds { + title + link { + slug + type + } + } + maxNumberOfCards + sorting + } + fragment LatestEventsSliceFields on LatestEventsSlice { title events { @@ -965,6 +979,7 @@ export const slices = gql` ...FeaturedEventsFields ...GenericListFields ...LatestGenericListItemsFields + ...GrantCardsListFields } fragment AllSlices on Slice { diff --git a/apps/web/utils/richText.tsx b/apps/web/utils/richText.tsx index 41c1b857d440..af5c52d7a304 100644 --- a/apps/web/utils/richText.tsx +++ b/apps/web/utils/richText.tsx @@ -66,6 +66,7 @@ import { FeaturedSupportQnAs as FeaturedSupportQNAsSchema, Form as FormSchema, GenericList as GenericListSchema, + GrantCardsList, MultipleStatistics as MultipleStatisticsSchema, OneColumnText, OverviewLinks as OverviewLinksSliceSchema, @@ -91,6 +92,7 @@ import { UmsCostOfLivingCalculator } from '../components/connected/UmbodsmadurSk import FeaturedEvents from '../components/FeaturedEvents/FeaturedEvents' import FeaturedSupportQNAs from '../components/FeaturedSupportQNAs/FeaturedSupportQNAs' import { EmbedSlice } from '../components/Organization/Slice/EmbedSlice/EmbedSlice' +import { GrantCardsListSlice } from '../components/Organization/Slice/GrantCardsList/GrantCardsListSlice' interface TranslationNamespaceProviderProps { messages: IntlConfig['messages'] @@ -286,6 +288,9 @@ const defaultRenderComponent = { const url = slice?.url ? slice.url + '?w=800' : '' return }, + GrantCardsList: (slice: GrantCardsList) => ( + + ), } export const webRichText = ( diff --git a/libs/cms/src/lib/cms.elasticsearch.service.ts b/libs/cms/src/lib/cms.elasticsearch.service.ts index 6f83b2649b4e..04e0e77dfd8a 100644 --- a/libs/cms/src/lib/cms.elasticsearch.service.ts +++ b/libs/cms/src/lib/cms.elasticsearch.service.ts @@ -620,6 +620,7 @@ export class CmsElasticsearchService { categories, types, organizations, + funds, }: GetGrantsInput, ): Promise { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -703,6 +704,30 @@ export class CmsElasticsearchService { }) }) + if (funds) { + must.push({ + nested: { + path: 'tags', + query: { + bool: { + must: [ + { + terms: { + 'tags.key': funds, + }, + }, + { + term: { + 'tags.type': 'fund', + }, + }, + ], + }, + }, + }, + }) + } + const grantListResponse: ApiResponse> = await this.elasticService.findByQuery(index, { query: { diff --git a/libs/cms/src/lib/dto/getGrants.input.ts b/libs/cms/src/lib/dto/getGrants.input.ts index bfe512bad196..614df7dd9f54 100644 --- a/libs/cms/src/lib/dto/getGrants.input.ts +++ b/libs/cms/src/lib/dto/getGrants.input.ts @@ -42,4 +42,9 @@ export class GetGrantsInput { @IsArray() @IsOptional() organizations?: string[] + + @Field(() => [String], { nullable: true }) + @IsArray() + @IsOptional() + funds?: string[] } diff --git a/libs/cms/src/lib/models/grantCardsList.model.ts b/libs/cms/src/lib/models/grantCardsList.model.ts new file mode 100644 index 000000000000..30725fa53039 --- /dev/null +++ b/libs/cms/src/lib/models/grantCardsList.model.ts @@ -0,0 +1,59 @@ +import { Field, ObjectType, ID, registerEnumType, Int } from '@nestjs/graphql' + +import { IGrantCardsList } from '../generated/contentfulTypes' +import { CacheField } from '@island.is/nest/graphql' +import { Fund, mapFund } from './fund.model' +import { SystemMetadata } from '@island.is/shared/types' +import { logger } from '@island.is/logging' + +enum CardSorting { + ALPHABETICAL, + MOST_RECENTLY_UPDATED_FIRST, +} + +registerEnumType(CardSorting, { name: 'GrantCardsListSorting' }) + +@ObjectType() +export class GrantCardsList { + @Field(() => ID) + id!: string + + @Field() + title!: string + + @Field({ nullable: true }) + displayTitle?: boolean + + @CacheField(() => [Fund], { nullable: true }) + funds?: Array + + @Field(() => Int, { nullable: true }) + maxNumberOfCards?: number + + @CacheField(() => CardSorting, { nullable: true }) + sorting?: CardSorting +} + +export const mapGrantCardsList = ({ + fields, + sys, +}: IGrantCardsList): SystemMetadata => { + logger.warn('fields', fields) + + return { + typename: 'GrantCardsList', + id: sys.id, + title: fields.grantCardListTitle, + displayTitle: fields.grantCardsListDisplayTitle, + funds: fields.grantCardListFunds + ? fields.grantCardListFunds.map((g) => mapFund(g)) + : undefined, + maxNumberOfCards: fields.grantCardsListMaxNumberOfCards ?? undefined, + sorting: + fields.grantCardsListSorting === 'Alphabetical' + ? CardSorting.ALPHABETICAL + : fields.grantCardsListSorting === 'Most recently updated first' + ? CardSorting.MOST_RECENTLY_UPDATED_FIRST + : undefined, + } +} diff --git a/libs/cms/src/lib/unions/slice.union.ts b/libs/cms/src/lib/unions/slice.union.ts index c1030069963e..1f0f3241bc28 100644 --- a/libs/cms/src/lib/unions/slice.union.ts +++ b/libs/cms/src/lib/unions/slice.union.ts @@ -48,6 +48,7 @@ import { IFeaturedEvents, IGenericList, ILatestGenericListItems, + IGrantCardsList, } from '../generated/contentfulTypes' import { Image, mapImage } from '../models/image.model' import { Asset, mapAsset } from '../models/asset.model' @@ -145,6 +146,10 @@ import { LatestGenericListItems, mapLatestGenericListItems, } from '../models/latestGenericListItems.model' +import { + GrantCardsList, + mapGrantCardsList, +} from '../models/grantCardsList.model' export type SliceTypes = | ITimeline @@ -191,6 +196,7 @@ export type SliceTypes = | IChartNumberBox | IFeaturedEvents | IGenericList + | IGrantCardsList | ILatestGenericListItems export const SliceUnion = createUnionType({ @@ -244,6 +250,7 @@ export const SliceUnion = createUnionType({ FeaturedEvents, GenericList, LatestGenericListItems, + GrantCardsList, ], resolveType: (document) => document.typename, // typename is appended to request on indexing }) @@ -341,6 +348,8 @@ export const mapSliceUnion = (slice: SliceTypes): typeof SliceUnion => { return mapGenericList(slice as IGenericList) case 'latestGenericListItems': return mapLatestGenericListItems(slice as ILatestGenericListItems) + case 'grantCardsList': + return mapGrantCardsList(slice as IGrantCardsList) default: throw new ApolloError(`Can not convert to slice: ${contentType}`) } From a549c0730dc7f1c661ef677a5991f72ef69a1ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 20 Nov 2024 13:44:33 +0000 Subject: [PATCH 03/20] fix: link color --- .../Slice/GrantCardsList/GrantCardsListSlice.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx index d706a67a5ba0..1af9b3f21295 100644 --- a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx +++ b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx @@ -30,8 +30,6 @@ export const GrantCardsListSlice = ({ slice }: SliceProps) => { }, }) - console.log(slice) - if (!slice.funds) { return undefined } @@ -45,11 +43,12 @@ export const GrantCardsListSlice = ({ slice }: SliceProps) => { return ( - {fund.title} + {fund.title} ) From 9e1759b58654097289e4d4192da281d5964d84d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 20 Nov 2024 14:04:45 +0000 Subject: [PATCH 04/20] fix: removing logging --- .../Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx | 4 +++- libs/cms/src/lib/cms.elasticsearch.service.ts | 1 + libs/cms/src/lib/models/grantCardsList.model.ts | 2 -- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx index 1af9b3f21295..89dd22468400 100644 --- a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx +++ b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx @@ -34,6 +34,8 @@ export const GrantCardsListSlice = ({ slice }: SliceProps) => { return undefined } + data?.getGrants.items.forEach((i) => console.log(i.fund?.title)) + return ( {slice.funds.map((fund) => { @@ -44,7 +46,7 @@ export const GrantCardsListSlice = ({ slice }: SliceProps) => { diff --git a/libs/cms/src/lib/cms.elasticsearch.service.ts b/libs/cms/src/lib/cms.elasticsearch.service.ts index 04e0e77dfd8a..3e4c0c31f7ab 100644 --- a/libs/cms/src/lib/cms.elasticsearch.service.ts +++ b/libs/cms/src/lib/cms.elasticsearch.service.ts @@ -704,6 +704,7 @@ export class CmsElasticsearchService { }) }) + logger.warn('funds', funds) if (funds) { must.push({ nested: { diff --git a/libs/cms/src/lib/models/grantCardsList.model.ts b/libs/cms/src/lib/models/grantCardsList.model.ts index 30725fa53039..5d178db7f459 100644 --- a/libs/cms/src/lib/models/grantCardsList.model.ts +++ b/libs/cms/src/lib/models/grantCardsList.model.ts @@ -38,8 +38,6 @@ export const mapGrantCardsList = ({ fields, sys, }: IGrantCardsList): SystemMetadata => { - logger.warn('fields', fields) - return { typename: 'GrantCardsList', id: sys.id, From cfb5e77fe9034a58077d3a9eadd308a988c28a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 20 Nov 2024 14:04:55 +0000 Subject: [PATCH 05/20] fix: another log --- .../Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx index 89dd22468400..1902092c6ccf 100644 --- a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx +++ b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx @@ -34,8 +34,6 @@ export const GrantCardsListSlice = ({ slice }: SliceProps) => { return undefined } - data?.getGrants.items.forEach((i) => console.log(i.fund?.title)) - return ( {slice.funds.map((fund) => { From 087b2ee2659e19350a5c6abc3326b8285acbc6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Mon, 16 Dec 2024 15:46:38 +0000 Subject: [PATCH 06/20] feat: merge in info card --- .github/CODEOWNERS | 1 - .../web/components/PlazaCard/PlazaCard.css.ts | 5 - apps/web/components/real.ts | 1 - .../web/screens/Grants/Grant/GrantSidebar.tsx | 1 - .../Grants/SearchResults/SearchResults.tsx | 69 +++++-- .../SearchResults/SearchResultsContent.tsx | 172 +++++++++-------- apps/web/screens/Grants/messages.ts | 8 + apps/web/screens/Grants/utils.ts | 49 +++-- apps/web/screens/queries/Grants.ts | 1 + libs/cms/src/lib/cms.elasticsearch.service.ts | 1 - libs/cms/src/lib/models/grant.model.ts | 1 - .../lib/search/importers/grants.service.ts | 6 +- libs/island-ui/core/src/index.ts | 1 + .../src/lib/InfoCardGrid/DetailedInfoCard.tsx | 178 +++++++++--------- .../core/src/lib/InfoCardGrid/InfoCard.css.ts | 20 ++ .../core/src/lib/InfoCardGrid/InfoCard.tsx | 72 +++++++ .../src/lib/InfoCardGrid/InfoCardGrid.tsx | 50 +++++ .../src/lib/InfoCardGrid/SimpleInfoCard.tsx | 71 +++++++ .../core/src/lib/InfoCardGrid/index.ts | 1 + 19 files changed, 502 insertions(+), 206 deletions(-) delete mode 100644 apps/web/components/PlazaCard/PlazaCard.css.ts rename apps/web/components/PlazaCard/PlazaCard.tsx => libs/island-ui/core/src/lib/InfoCardGrid/DetailedInfoCard.tsx (52%) create mode 100644 libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.css.ts create mode 100644 libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.tsx create mode 100644 libs/island-ui/core/src/lib/InfoCardGrid/InfoCardGrid.tsx create mode 100644 libs/island-ui/core/src/lib/InfoCardGrid/SimpleInfoCard.tsx create mode 100644 libs/island-ui/core/src/lib/InfoCardGrid/index.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f4bc0d23934e..fab199409190 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -132,7 +132,6 @@ codemagic.yaml /apps/services/regulations-admin-backend/ @island-is/hugsmidjan /apps/services/user-profile/ @island-is/hugsmidjan @island-is/juni @island-is/aranja /apps/web/components/Grant/ @island-is/hugsmidjan -/apps/web/components/PlazaCard/ @island-is/hugsmidjan /apps/web/screens/Grants/ @island-is/hugsmidjan /apps/web/screens/Regulations/ @island-is/hugsmidjan /apps/web/components/Regulations/ @island-is/hugsmidjan diff --git a/apps/web/components/PlazaCard/PlazaCard.css.ts b/apps/web/components/PlazaCard/PlazaCard.css.ts deleted file mode 100644 index bb5b75f34928..000000000000 --- a/apps/web/components/PlazaCard/PlazaCard.css.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { style } from '@vanilla-extract/css' - -export const container = style({ - maxWidth: '476px', -}) diff --git a/apps/web/components/real.ts b/apps/web/components/real.ts index e03cf0f7843f..bcf7523b139d 100644 --- a/apps/web/components/real.ts +++ b/apps/web/components/real.ts @@ -12,7 +12,6 @@ */ export * from './Card/Card' -export * from './PlazaCard/PlazaCard' export * from './Header/Header' export * from './SearchInput/SearchInput' export * from './LanguageToggler/LanguageToggler' diff --git a/apps/web/screens/Grants/Grant/GrantSidebar.tsx b/apps/web/screens/Grants/Grant/GrantSidebar.tsx index c2f9fe31939c..5a1941ee5b2a 100644 --- a/apps/web/screens/Grants/Grant/GrantSidebar.tsx +++ b/apps/web/screens/Grants/Grant/GrantSidebar.tsx @@ -9,7 +9,6 @@ import { Stack, Text, } from '@island.is/island-ui/core' -import { useLocale } from '@island.is/localization' import { Locale } from '@island.is/shared/types' import { isDefined } from '@island.is/shared/utils' import { InstitutionPanel } from '@island.is/web/components' diff --git a/apps/web/screens/Grants/SearchResults/SearchResults.tsx b/apps/web/screens/Grants/SearchResults/SearchResults.tsx index 1dbb89da54d9..44df7b450a21 100644 --- a/apps/web/screens/Grants/SearchResults/SearchResults.tsx +++ b/apps/web/screens/Grants/SearchResults/SearchResults.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react' +import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react' import { useIntl } from 'react-intl' import { useWindowSize } from 'react-use' import debounce from 'lodash/debounce' @@ -16,6 +16,7 @@ import { BreadCrumbItem, Breadcrumbs, FilterInput, + Pagination, Text, } from '@island.is/island-ui/core' import { theme } from '@island.is/island-ui/theme' @@ -55,9 +56,11 @@ export interface SearchState { organization?: Array } +const PAGE_SIZE = 8 + const GrantsSearchResultsPage: CustomScreen = ({ locale, - initialGrants, + initialGrantList, tags, }) => { const { formatMessage } = useIntl() @@ -67,7 +70,12 @@ const GrantsSearchResultsPage: CustomScreen = ({ const parentUrl = linkResolver('styrkjatorg', [], locale).href const currentUrl = linkResolver('styrkjatorgsearch', [], locale).href - const [grants, setGrants] = useState>(initialGrants ?? []) + const [grants, setGrants] = useState>( + initialGrantList?.items ?? [], + ) + const [totalHits, setTotalHits] = useState( + initialGrantList?.total ?? 0, + ) const [searchState, setSearchState] = useState() const [initialRender, setInitialRender] = useState(true) @@ -89,7 +97,7 @@ const GrantsSearchResultsPage: CustomScreen = ({ const organizations = searchParams.getAll('organization') setSearchState({ - page: page ? Number.parseInt(page) : undefined, + page: page ? Number.parseInt(page) : 1, query: searchParams.get('query') ?? undefined, status: statuses.length ? statuses : undefined, category: categories.length ? categories : undefined, @@ -98,6 +106,13 @@ const GrantsSearchResultsPage: CustomScreen = ({ }) }, []) + const totalPages = useMemo(() => { + if (!totalHits) { + return + } + return totalHits > 8 ? Math.ceil(totalHits / PAGE_SIZE) : 1 + }, [totalHits]) + const updateUrl = useCallback(() => { if (!searchState) { return @@ -134,7 +149,7 @@ const GrantsSearchResultsPage: CustomScreen = ({ organizations: searchState?.organization, page: searchState?.page, search: searchState?.query, - size: 8, + size: PAGE_SIZE, statuses: searchState?.status, types: searchState?.type, }, @@ -143,6 +158,7 @@ const GrantsSearchResultsPage: CustomScreen = ({ .then((res) => { if (res.data) { setGrants(res.data.getGrants.items) + setTotalHits(res.data.getGrants.total) } else if (res.error) { setGrants([]) console.error('Error fetching grants', res.error) @@ -199,7 +215,7 @@ const GrantsSearchResultsPage: CustomScreen = ({ const onResetFilter = () => { setSearchState({ - page: undefined, + page: 1, query: undefined, status: undefined, category: undefined, @@ -210,18 +226,18 @@ const GrantsSearchResultsPage: CustomScreen = ({ } const hitsMessage = useMemo(() => { - if (!grants) { + if (!totalHits) { return } - if (grants.length === 1) { + if (totalHits === 1) { return formatMessage(m.search.resultFound, { - arg: {grants.length}, + arg: {totalHits}, }) } return formatMessage(m.search.resultsFound, { - arg: {grants.length}, + arg: {totalHits}, }) - }, [formatMessage, grants]) + }, [formatMessage, totalHits]) return ( = ({ locale={locale} /> + {totalPages && totalPages > 1 ? ( + + ( + { + updateSearchStateValue('page', page) + }} + > + {children} + + )} + /> + + ) : undefined} )} {isMobile && ( @@ -335,19 +373,19 @@ const GrantsSearchResultsPage: CustomScreen = ({ interface GrantsHomeProps { locale: Locale - initialGrants?: Array + initialGrantList?: GrantList tags?: Array } const GrantsSearchResults: CustomScreen = ({ - initialGrants, + initialGrantList, tags, customPageData, locale, }) => { return ( { }, }), ]) + return { - initialGrants: getGrants.items, + initialGrantList: getGrants, tags: getGenericTagsInTagGroups ?? undefined, locale: locale as Locale, themeConfig: { diff --git a/apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx b/apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx index d57cece2196d..d8c82876e7cb 100644 --- a/apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx +++ b/apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx @@ -1,13 +1,12 @@ +import { useState } from 'react' +import { useIntl } from 'react-intl' import { useWindowSize } from 'react-use' import format from 'date-fns/format' -import { useRouter } from 'next/router' -import { Box, Inline, Text } from '@island.is/island-ui/core' +import { Box, Button, InfoCardGrid, Text } from '@island.is/island-ui/core' import { theme } from '@island.is/island-ui/theme' -import { useLocale } from '@island.is/localization' import { Locale } from '@island.is/shared/types' import { isDefined } from '@island.is/shared/utils' -import { PlazaCard } from '@island.is/web/components' import { Grant } from '@island.is/web/graphql/schema' import { useLinkResolver } from '@island.is/web/hooks' @@ -21,93 +20,112 @@ interface Props { } export const SearchResultsContent = ({ grants, subheader, locale }: Props) => { - const { formatMessage } = useLocale() - const router = useRouter() + const { formatMessage } = useIntl() const { linkResolver } = useLinkResolver() const { width } = useWindowSize() const isMobile = width <= theme.breakpoints.md const isTablet = width <= theme.breakpoints.lg && width > theme.breakpoints.md + const [isGridLayout, setIsGridLayout] = useState(true) + return ( <> {!isMobile && ( - + {subheader} + )} {grants?.length ? ( - - {grants?.map((grant) => { - if (!grant) { - return null - } + { + if (!grant || !grant.applicationId) { + return null + } + + const status = parseStatus(grant, formatMessage, locale) - const status = parseStatus(grant, formatMessage, locale) - return ( - - {grant.applicationId && ( - { - router.push( - linkResolver( - 'styrkjatorggrant', - [grant?.applicationId ?? ''], - locale, - ).href, - ) - }, - icon: 'arrowForward', - }} - detailLines={[ - grant.dateFrom && grant.dateTo - ? { - icon: 'calendar' as const, - text: `${format( - new Date(grant.dateFrom), - 'dd.MM.', - )} - ${format( - new Date(grant.dateTo), - 'dd.MM.yyyy', - )}`, - } - : null, - status.deadlineStatus - ? { - icon: 'time' as const, - //todo: fix when the text is ready - text: status.deadlineStatus, - } - : undefined, - grant.categoryTags - ? { - icon: 'informationCircle' as const, - text: grant.categoryTags - .map((ct) => ct.title) - .filter(isDefined) - .join(', '), - } - : undefined, - ].filter(isDefined)} - /> - )} - - ) - })} - + return { + id: grant.id, + eyebrow: grant.fund?.title ?? grant.name ?? '', + subEyebrow: grant.fund?.parentOrganization?.title, + title: grant.name ?? '', + description: grant.description ?? '', + logo: + grant.fund?.featuredImage?.url ?? + grant.fund?.parentOrganization?.logo?.url ?? + '', + logoAlt: + grant.fund?.featuredImage?.title ?? + grant.fund?.parentOrganization?.logo?.title ?? + '', + tags: status.applicationStatus + ? [ + generateStatusTag( + status.applicationStatus, + formatMessage, + ), + ].filter(isDefined) + : undefined, + link: { + label: formatMessage(m.general.seeMore), + href: linkResolver( + 'styrkjatorggrant', + [grant?.applicationId ?? ''], + locale, + ).href, + }, + detailLines: [ + grant.dateFrom && grant.dateTo + ? { + icon: 'calendar' as const, + text: `${format( + new Date(grant.dateFrom), + 'dd.MM.yyyy', + )} - ${format(new Date(grant.dateTo), 'dd.MM.yyyy')}`, + } + : null, + { + icon: 'time' as const, + //todo: fix when the text is ready + text: status.deadlineStatus, + }, + grant.categoryTags + ? { + icon: 'informationCircle' as const, + text: grant.categoryTags + .map((ct) => ct.title) + .filter(isDefined) + .join(', '), + } + : undefined, + ].filter(isDefined), + } + }) + .filter(isDefined) ?? [] + } + /> ) : undefined} {!grants?.length && ( - format(date, stringFormat, { - locale: locale === 'is' ? localeIS : localeEn, - }) +): string | undefined => { + try { + return format(date, stringFormat, { + locale: locale === 'is' ? localeIS : localeEn, + }) + } catch (e) { + console.warn('Error formatting date') + return + } +} export const containsTimePart = (date: string) => date.includes('T') @@ -33,15 +38,18 @@ export const parseStatus = ( ): Status => { switch (grant.status) { case GrantStatus.Closed: { + const date = grant.dateTo + ? formatDate(new Date(grant.dateTo), locale) + : undefined return { applicationStatus: 'closed', - deadlineStatus: grant.dateTo + deadlineStatus: date ? formatMessage( - containsTimePart(grant.dateTo) + containsTimePart(date) ? m.search.applicationWasOpenToAndWith : m.search.applicationWasOpenTo, { - arg: formatDate(new Date(grant.dateTo), locale), + arg: date, }, ) : formatMessage(m.search.applicationClosed), @@ -49,22 +57,28 @@ export const parseStatus = ( } } case GrantStatus.ClosedOpeningSoon: { + const date = grant.dateFrom + ? formatDate(new Date(grant.dateFrom), locale) + : undefined return { applicationStatus: 'closed', - deadlineStatus: grant.dateFrom + deadlineStatus: date ? formatMessage(m.search.applicationOpensAt, { - arg: formatDate(new Date(grant.dateFrom), locale), + arg: date, }) : formatMessage(m.search.applicationClosed), note: grant.statusText ?? undefined, } } case GrantStatus.ClosedOpeningSoonWithEstimation: { + const date = grant.dateFrom + ? formatDate(new Date(grant.dateFrom), locale, 'MMMM yyyy') + : undefined return { applicationStatus: 'closed', - deadlineStatus: grant.dateFrom + deadlineStatus: date ? formatMessage(m.search.applicationEstimatedOpensAt, { - arg: formatDate(new Date(grant.dateFrom), locale, 'MMMM yyyy'), + arg: date, }) : formatMessage(m.search.applicationClosed), note: grant.statusText ?? undefined, @@ -85,15 +99,18 @@ export const parseStatus = ( } } case GrantStatus.Open: { + const date = grant.dateTo + ? formatDate(new Date(grant.dateTo), locale, 'dd.MMMM.') + : undefined return { applicationStatus: 'open', - deadlineStatus: grant.dateTo + deadlineStatus: date ? formatMessage( - containsTimePart(grant.dateTo) + containsTimePart(date) ? m.search.applicationOpensToWithDay : m.search.applicationOpensTo, { - arg: formatDate(new Date(grant.dateTo), locale, 'dd.MMMM.'), + arg: date, }, ) : formatMessage(m.search.applicationOpen), diff --git a/apps/web/screens/queries/Grants.ts b/apps/web/screens/queries/Grants.ts index 7518d29e81d1..c62a073a363b 100644 --- a/apps/web/screens/queries/Grants.ts +++ b/apps/web/screens/queries/Grants.ts @@ -5,6 +5,7 @@ import { nestedFields, slices } from './fragments' export const GET_GRANTS_QUERY = gql` query GetGrants($input: GetGrantsInput!) { getGrants(input: $input) { + total items { id name diff --git a/libs/cms/src/lib/cms.elasticsearch.service.ts b/libs/cms/src/lib/cms.elasticsearch.service.ts index 4bb3af9dc549..46508e3d8de6 100644 --- a/libs/cms/src/lib/cms.elasticsearch.service.ts +++ b/libs/cms/src/lib/cms.elasticsearch.service.ts @@ -753,7 +753,6 @@ export class CmsElasticsearchService { size, from: (page - 1) * size, }) - return { total: grantListResponse.body.hits.total.value, items: grantListResponse.body.hits.hits.map((response) => diff --git a/libs/cms/src/lib/models/grant.model.ts b/libs/cms/src/lib/models/grant.model.ts index ba4238814907..c119d9387395 100644 --- a/libs/cms/src/lib/models/grant.model.ts +++ b/libs/cms/src/lib/models/grant.model.ts @@ -162,7 +162,6 @@ export const mapGrant = ({ fields, sys }: IGrant): Grant => { files: (fields.grantFiles ?? []).map((file) => mapAsset(file)) ?? [], supportLinks: (fields.grantSupportLinks ?? []).map((link) => mapLink(link)) ?? [], - categoryTags: fields.grantCategoryTags ? fields.grantCategoryTags.map((tag) => mapGenericTag(tag)) : undefined, diff --git a/libs/cms/src/lib/search/importers/grants.service.ts b/libs/cms/src/lib/search/importers/grants.service.ts index 3f2336eb2e1e..ead7003d046b 100644 --- a/libs/cms/src/lib/search/importers/grants.service.ts +++ b/libs/cms/src/lib/search/importers/grants.service.ts @@ -17,13 +17,11 @@ import { isDefined } from '@island.is/shared/utils' @Injectable() export class GrantsSyncService implements CmsSyncProvider { processSyncData(entries: processSyncDataInput) { - // only process grants that we consider not to be empty and dont have circular structures + // only process grants that we consider not to be empty return entries.filter( // eslint-disable-next-line @typescript-eslint/no-explicit-any (entry: Entry): entry is IGrant => - entry.sys.contentType.sys.id === 'grant' && - entry.fields.grantName && - !isCircular(entry), + entry.sys.contentType.sys.id === 'grant' && entry.fields.grantName, ) } diff --git a/libs/island-ui/core/src/index.ts b/libs/island-ui/core/src/index.ts index dfce8e49b301..9136b255cb47 100644 --- a/libs/island-ui/core/src/index.ts +++ b/libs/island-ui/core/src/index.ts @@ -60,6 +60,7 @@ export * from './lib/VisuallyHidden/VisuallyHidden' export * from './lib/Drawer/Drawer' export * from './lib/ProblemTemplate/ProblemTemplate' export * from './lib/ProblemTemplate/ProblemTemplate.css' +export * from './lib/InfoCardGrid' // Cards export * from './lib/LinkCard/LinkCard' diff --git a/apps/web/components/PlazaCard/PlazaCard.tsx b/libs/island-ui/core/src/lib/InfoCardGrid/DetailedInfoCard.tsx similarity index 52% rename from apps/web/components/PlazaCard/PlazaCard.tsx rename to libs/island-ui/core/src/lib/InfoCardGrid/DetailedInfoCard.tsx index f18c1e2da060..899f15be1450 100644 --- a/apps/web/components/PlazaCard/PlazaCard.tsx +++ b/libs/island-ui/core/src/lib/InfoCardGrid/DetailedInfoCard.tsx @@ -1,46 +1,45 @@ -import * as React from 'react' - import { Box, - Button, + GridColumn, + GridContainer, + GridRow, Icon, IconMapIcon, + Inline, Stack, Tag, Text, -} from '@island.is/island-ui/core' -import { ActionCardProps } from '@island.is/island-ui/core/types' +} from '../..' +import { isDefined } from '@island.is/shared/utils' -import * as styles from './PlazaCard.css' +import { BaseProps } from './InfoCard' +import { ActionCardProps } from '../ActionCard/types' const eyebrowColor = 'blueberry600' -interface Props { - title: string - text: string +export type DetailedProps = BaseProps & { logo?: string logoAlt?: string - eyebrow?: string subEyebrow?: string + //max 5 lines detailLines?: Array<{ icon: IconMapIcon text: string }> - tag?: ActionCardProps['tag'] - cta?: ActionCardProps['cta'] + tags?: Array } -export const PlazaCard = ({ +export const DetailedInfoCard = ({ title, - text, + description, + size = 'medium', eyebrow, subEyebrow, detailLines, - tag, + tags, logo, logoAlt, - cta, -}: Props) => { +}: DetailedProps) => { const renderLogo = () => { if (!logo) { return null @@ -53,37 +52,6 @@ export const PlazaCard = ({ ) } - const renderEyebrow = () => { - if (!eyebrow) { - return null - } - - return ( - - {subEyebrow ? ( - - - {eyebrow} - - - {subEyebrow} - - - ) : ( - - {eyebrow} - - )} - {renderLogo()} - - ) - } - const renderDetails = () => { if (!detailLines?.length) { return null @@ -92,7 +60,7 @@ export const PlazaCard = ({ return ( - {detailLines?.map((d, index) => ( + {detailLines?.slice(0, 5).map((d, index) => ( - + {d.text} @@ -116,56 +84,98 @@ export const PlazaCard = ({ ) } - const renderTag = () => { - if (!tag) { + const renderTags = () => { + if (!tags?.length) { return null } - return {tag.label} + return ( + + {tags + .map((tag, index) => { + if (!tag) { + return null + } + return ( + + {tag.label} + + ) + }) + .filter(isDefined)} + + ) } - const renderCta = () => { - if (!cta) { - return null - } - + const renderHeader = () => { return ( - + {subEyebrow ? ( + + + {eyebrow} + + + {subEyebrow} + + + ) : ( + + {eyebrow} + + )} + {renderLogo()} + ) } - return ( - - - {renderEyebrow()} + const renderContent = () => { + if (size === 'large') { + return ( + + + + + {title} + + {description && ( + + {description} + + )} + + {renderDetails()} + + + ) + } + return ( + <> {title} - {text && ( + {description && ( - {text} + {description} )} {renderDetails()} - - {renderTag()} - {renderCta()} - + + ) + } + + return ( + <> + {renderHeader()} + {renderContent()} + + {renderTags()} - + ) } diff --git a/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.css.ts b/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.css.ts new file mode 100644 index 000000000000..4c27d84947de --- /dev/null +++ b/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.css.ts @@ -0,0 +1,20 @@ +import { style } from '@vanilla-extract/css' + +export const infoCardSmall = style({ + maxWidth: 310, + minHeight: 450, +}) + +export const infoCard = style({ + maxWidth: 477, + minHeight: 432, +}) + +export const infoCardWide = style({ + maxWidth: 978, + minHeight: 318, +}) + +export const wideTitleBox = style({ + flexGrow: 2, +}) diff --git a/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.tsx b/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.tsx new file mode 100644 index 000000000000..339d50453d1a --- /dev/null +++ b/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.tsx @@ -0,0 +1,72 @@ +import { useEffect, useState } from 'react' +import { useWindowSize } from 'react-use' + +import { theme } from '@island.is/island-ui/theme' + +import { DetailedInfoCard, DetailedProps } from './DetailedInfoCard' +import { SimpleInfoCard } from './SimpleInfoCard' +import * as styles from './InfoCard.css' +import { Box, FocusableBox, LinkV2 } from '../..' + +export interface BaseProps { + id: string + title: string + description: string + eyebrow: string + size: 'large' | 'medium' | 'small' + link: { + label: string + href: string + } +} + +export type InfoCardProps = + | (BaseProps & { + variant?: 'simple' + }) + | (DetailedProps & { + variant: 'detailed' + }) + +export const InfoCard = ({ size, ...restOfProps }: InfoCardProps) => { + const [isMobile, setIsMobile] = useState(false) + const { width } = useWindowSize() + + useEffect(() => { + if (width < theme.breakpoints.md) { + return setIsMobile(true) + } + setIsMobile(false) + }, [width]) + + const cardSize = isMobile ? 'small' : size + + return ( + + + {restOfProps.variant === 'detailed' ? ( + + ) : ( + + )} + + + ) +} diff --git a/libs/island-ui/core/src/lib/InfoCardGrid/InfoCardGrid.tsx b/libs/island-ui/core/src/lib/InfoCardGrid/InfoCardGrid.tsx new file mode 100644 index 000000000000..73b454a9cabb --- /dev/null +++ b/libs/island-ui/core/src/lib/InfoCardGrid/InfoCardGrid.tsx @@ -0,0 +1,50 @@ +import { useEffect, useState } from 'react' +import { useWindowSize } from 'react-use' + +import { Inline, Stack } from '../..' +import { theme } from '@island.is/island-ui/theme' + +import { InfoCard, InfoCardProps } from './InfoCard' + +export type InfoCardItemProps = Omit + +interface Props { + cards: Array + variant?: 'detailed' | 'simple' + columns?: 1 | 2 | 3 +} + +export const InfoCardGrid = ({ cards, variant, columns }: Props) => { + const [isMobile, setIsMobile] = useState(false) + const { width } = useWindowSize() + + useEffect(() => { + if (width < theme.breakpoints.md) { + return setIsMobile(true) + } + setIsMobile(false) + }, [width]) + + if (columns === 1 || isMobile) { + return ( + + {cards.map((c) => ( + + ))} + + ) + } + + return ( + + {cards.map((c, index) => ( + + ))} + + ) +} diff --git a/libs/island-ui/core/src/lib/InfoCardGrid/SimpleInfoCard.tsx b/libs/island-ui/core/src/lib/InfoCardGrid/SimpleInfoCard.tsx new file mode 100644 index 000000000000..34b633891737 --- /dev/null +++ b/libs/island-ui/core/src/lib/InfoCardGrid/SimpleInfoCard.tsx @@ -0,0 +1,71 @@ +import { Box, GridColumn, GridContainer, GridRow, Text } from '../..' + +import { BaseProps } from './InfoCard' + +const eyebrowColor = 'blueberry600' + +export const SimpleInfoCard = ({ + title, + description, + size = 'medium', + eyebrow, +}: BaseProps) => { + const renderHeader = () => { + if (!eyebrow) { + return + } + return ( + + + {eyebrow} + + + ) + } + + const renderContent = () => { + if (size === 'large') { + return ( + + + + + {title} + + {description && ( + + {description} + + )} + + + + ) + } + return ( + <> + + {title} + + {description && ( + + {description} + + )} + + ) + } + + return ( + <> + {renderHeader()} + {renderContent()} + + ) +} diff --git a/libs/island-ui/core/src/lib/InfoCardGrid/index.ts b/libs/island-ui/core/src/lib/InfoCardGrid/index.ts new file mode 100644 index 000000000000..29cb05d74923 --- /dev/null +++ b/libs/island-ui/core/src/lib/InfoCardGrid/index.ts @@ -0,0 +1 @@ +export { InfoCardGrid } from './InfoCardGrid' From 96c688f2a3d300d5e08eb1944e429035258f79e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Mon, 16 Dec 2024 16:33:46 +0000 Subject: [PATCH 07/20] feat: works a bit --- .../GrantCardsList/GrantCardsListSlice.tsx | 99 ++++++++++++++----- .../core/src/lib/InfoCardGrid/InfoCard.tsx | 2 +- 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx index 1902092c6ccf..8df6d86dd7b9 100644 --- a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx +++ b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx @@ -1,31 +1,36 @@ +import format from 'date-fns/format' import { useQuery } from '@apollo/client' -import { Box, LinkV2, Text } from '@island.is/island-ui/core' +import { Box, InfoCardGrid } from '@island.is/island-ui/core' +import { isDefined } from '@island.is/shared/utils' import { ContentLanguage, GrantCardsList, + GrantStatus, Query, } from '@island.is/web/graphql/schema' -import { LinkType, useLinkResolver } from '@island.is/web/hooks' +import { useLinkResolver, useNamespace } from '@island.is/web/hooks' import { useI18n } from '@island.is/web/i18n' import { GET_GRANTS_QUERY } from '@island.is/web/screens/queries' -import * as styles from './GrantCardsListSlice.css' - interface SliceProps { slice: GrantCardsList + namespace?: Record } -export const GrantCardsListSlice = ({ slice }: SliceProps) => { +const generateStatus = (grant: GrantStatus) => 'Opið fyrir umsóknir' + +export const GrantCardsListSlice = ({ slice, namespace }: SliceProps) => { const { activeLocale } = useI18n() const { linkResolver } = useLinkResolver() + const translations = useNamespace(namespace) - const { data, loading, error } = useQuery(GET_GRANTS_QUERY, { + const { data } = useQuery(GET_GRANTS_QUERY, { variables: { input: { lang: activeLocale as ContentLanguage, - size: slice.maxNumberOfCards ?? 4, - funds: slice.funds ? slice.funds.map((f) => f.id).join(',') : undefined, + size: slice.maxNumberOfCards ?? 50, + //funds: slice.funds ? slice.funds.map((f) => f.id).join(',') : undefined, }, }, }) @@ -34,25 +39,67 @@ export const GrantCardsListSlice = ({ slice }: SliceProps) => { return undefined } - return ( - - {slice.funds.map((fund) => { - if (!fund.link) { - return null + const cards = data?.getGrants?.items + ?.map((grant) => { + if (grant.id) { + return { + id: grant.id, + eyebrow: grant.fund?.title ?? grant.name ?? '', + subEyebrow: grant.fund?.parentOrganization?.title, + title: grant.name ?? '', + description: grant.description ?? '', + logo: + grant.fund?.featuredImage?.url ?? + grant.fund?.parentOrganization?.logo?.url ?? + '', + logoAlt: + grant.fund?.featuredImage?.title ?? + grant.fund?.parentOrganization?.logo?.title ?? + '', + link: { + label: 'Skoða nánar', + href: linkResolver( + 'styrkjatorggrant', + [grant?.applicationId ?? ''], + activeLocale, + ).href, + }, + detailLines: [ + grant.dateFrom && grant.dateTo + ? { + icon: 'calendar' as const, + text: `${format( + new Date(grant.dateFrom), + 'dd.MM.yyyy', + )} - ${format(new Date(grant.dateTo), 'dd.MM.yyyy')}`, + } + : null, + grant.status + ? { + icon: 'time' as const, + //todo: fix when the text is ready + text: generateStatus(grant?.status), + } + : undefined, + grant.categoryTags + ? { + icon: 'informationCircle' as const, + text: grant.categoryTags + .map((ct) => ct.title) + .filter(isDefined) + .join(', '), + } + : undefined, + ].filter(isDefined), } - return ( - - - {fund.title} - - - ) - })} + } + return null + }) + .filter(isDefined) + + return ( + + ) } diff --git a/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.tsx b/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.tsx index 339d50453d1a..3ec4e8776b7d 100644 --- a/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.tsx +++ b/libs/island-ui/core/src/lib/InfoCardGrid/InfoCard.tsx @@ -54,7 +54,7 @@ export const InfoCard = ({ size, ...restOfProps }: InfoCardProps) => { component={LinkV2} href={restOfProps.link.href} background={size === 'small' ? 'yellow100' : 'white'} - borderColor="white" + borderColor="blue200" color="blue" borderWidth="standard" width="full" From fa1197b0a9820e6c7d774e1372290613885183f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Tue, 17 Dec 2024 09:30:43 +0000 Subject: [PATCH 08/20] fix: build bug --- apps/web/screens/Home/Home.tsx | 39 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/apps/web/screens/Home/Home.tsx b/apps/web/screens/Home/Home.tsx index 98bd37bb102a..8101caf24a27 100644 --- a/apps/web/screens/Home/Home.tsx +++ b/apps/web/screens/Home/Home.tsx @@ -1,34 +1,35 @@ import React, { useContext } from 'react' -import { Box, GridContainer } from '@island.is/island-ui/core' -import { useI18n } from '@island.is/web/i18n' -import { Screen } from '@island.is/web/types' -import { useNamespace } from '@island.is/web/hooks' + +import { Box } from '@island.is/island-ui/core' +import { Locale } from '@island.is/shared/types' +import { + CategoryItems, + LifeEventsSection, + NewsItems, + SearchSection, + WatsonChatPanel, +} from '@island.is/web/components' +import { FRONTPAGE_NEWS_TAG_ID } from '@island.is/web/constants' +import { GlobalContext } from '@island.is/web/context' import { ContentLanguage, - QueryGetArticleCategoriesArgs, GetArticleCategoriesQuery, GetFrontpageQuery, - QueryGetFrontpageArgs, GetNewsQuery, + LifeEventPage, + QueryGetArticleCategoriesArgs, + QueryGetFrontpageArgs, } from '@island.is/web/graphql/schema' +import { useNamespace } from '@island.is/web/hooks' +import { useI18n } from '@island.is/web/i18n' +import { withMainLayout } from '@island.is/web/layouts/main' import { GET_CATEGORIES_QUERY, GET_FRONTPAGE_QUERY, GET_NEWS_QUERY, } from '@island.is/web/screens/queries' -import { - SearchSection, - CategoryItems, - NewLinks, - NewsItems, - LifeEventsSection, - WatsonChatPanel, -} from '@island.is/web/components' -import { withMainLayout } from '@island.is/web/layouts/main' -import { GlobalContext } from '@island.is/web/context' -import { LifeEventPage, QueryGetNewsArgs } from '@island.is/api/schema' -import { FRONTPAGE_NEWS_TAG_ID } from '@island.is/web/constants' -import { Locale } from '@island.is/shared/types' +import { Screen } from '@island.is/web/types' + import { watsonConfig } from './config' interface HomeProps { From ed7e3574fba2ccb40588912d79b981ac9a6a2ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Tue, 17 Dec 2024 13:33:42 +0000 Subject: [PATCH 09/20] feat: wip --- .../GrantCardsList/GrantCardsList.css.ts | 71 +++++++++++++++ .../GrantCardsList/GrantCardsList.tsx | 86 +++++++++++++++++++ apps/web/components/GrantCardsList/index.ts | 5 ++ 3 files changed, 162 insertions(+) create mode 100644 apps/web/components/GrantCardsList/GrantCardsList.css.ts create mode 100644 apps/web/components/GrantCardsList/GrantCardsList.tsx create mode 100644 apps/web/components/GrantCardsList/index.ts diff --git a/apps/web/components/GrantCardsList/GrantCardsList.css.ts b/apps/web/components/GrantCardsList/GrantCardsList.css.ts new file mode 100644 index 000000000000..acf08de11bef --- /dev/null +++ b/apps/web/components/GrantCardsList/GrantCardsList.css.ts @@ -0,0 +1,71 @@ +import { theme, themeUtils } from '@island.is/island-ui/theme' +import { style } from '@vanilla-extract/css' + +export const unorderedList = style({ + listStyle: 'none', + marginTop: 16, + marginBottom: 16, + selectors: { + 'ul &': { + marginTop: 0, + marginBottom: 0, + }, + }, +}) + +export const listItem = style({ + ...themeUtils.responsiveStyle({ + xs: { + selectors: { + 'ol &': { + listStyle: 'none', + position: 'relative', + paddingLeft: theme.spacing[3], + }, + 'ol ol &': { + paddingLeft: theme.spacing[3], + }, + 'ol &:before': { + position: 'absolute', + top: '2px', + left: '8px', + counterIncrement: 'section', + content: 'counters(section, ".") " "', + color: theme.color.red400, + fontWeight: theme.typography.semiBold, + transform: 'translate(-100%, 0)', + }, + 'ul &': { + position: 'relative', + paddingLeft: theme.spacing[3], + }, + 'ul &:before': { + content: '""', + position: 'absolute', + top: '10px', + left: 0, + borderRadius: '50%', + border: `4px solid red`, + counterIncrement: 'none', + transform: 'none', + }, + '&:not(:first-child), ul ul &:first-child, ol ol &:first-child': { + marginTop: 12, + }, + '&:not(:last-child), ul ul &:last-child, ol ol &:last-child': { + marginBottom: 12, + }, + }, + }, + md: { + selectors: { + '&:not(:first-child), ul ul &:first-child, ol ol &:first-child': { + marginTop: 14, + }, + '&:not(:last-child), ul ul &:last-child, ol ol &:last-child': { + marginBottom: 14, + }, + }, + }, + }), +}) diff --git a/apps/web/components/GrantCardsList/GrantCardsList.tsx b/apps/web/components/GrantCardsList/GrantCardsList.tsx new file mode 100644 index 000000000000..20dada08bdf4 --- /dev/null +++ b/apps/web/components/GrantCardsList/GrantCardsList.tsx @@ -0,0 +1,86 @@ +import format from 'date-fns/format' + +import { Box, InfoCardGrid } from '@island.is/island-ui/core' +import { isDefined } from '@island.is/shared/utils' +import { GrantCardsList as GrantCardsListSchema } from '@island.is/web/graphql/schema' +import { useLinkResolver } from '@island.is/web/hooks' +import { useI18n } from '@island.is/web/i18n' + +interface SliceProps { + slice: GrantCardsListSchema +} + +const GrantCardsList = ({ slice }: SliceProps) => { + const { activeLocale } = useI18n() + const { linkResolver } = useLinkResolver() + + if (!slice.funds) { + return undefined + } + + const cards = data?.getGrants?.items + ?.map((grant) => { + if (grant.id) { + return { + id: grant.id, + eyebrow: grant.fund?.title ?? grant.name ?? '', + subEyebrow: grant.fund?.parentOrganization?.title, + title: grant.name ?? '', + description: grant.description ?? '', + logo: + grant.fund?.featuredImage?.url ?? + grant.fund?.parentOrganization?.logo?.url ?? + '', + logoAlt: + grant.fund?.featuredImage?.title ?? + grant.fund?.parentOrganization?.logo?.title ?? + '', + link: { + label: 'Skoða nánar', + href: linkResolver( + 'styrkjatorggrant', + [grant?.applicationId ?? ''], + activeLocale, + ).href, + }, + detailLines: [ + grant.dateFrom && grant.dateTo + ? { + icon: 'calendar' as const, + text: `${format( + new Date(grant.dateFrom), + 'dd.MM.yyyy', + )} - ${format(new Date(grant.dateTo), 'dd.MM.yyyy')}`, + } + : null, + grant.status + ? { + icon: 'time' as const, + //todo: fix when the text is ready + text: generateStatus(grant?.status), + } + : undefined, + grant.categoryTags + ? { + icon: 'informationCircle' as const, + text: grant.categoryTags + .map((ct) => ct.title) + .filter(isDefined) + .join(', '), + } + : undefined, + ].filter(isDefined), + } + } + return null + }) + .filter(isDefined) + + return ( + + + + ) +} + +export default GrantCardsList diff --git a/apps/web/components/GrantCardsList/index.ts b/apps/web/components/GrantCardsList/index.ts new file mode 100644 index 000000000000..2af26be237b2 --- /dev/null +++ b/apps/web/components/GrantCardsList/index.ts @@ -0,0 +1,5 @@ +import dynamic from 'next/dynamic' + +export const GrantCardsList = dynamic(() => import('./GrantCardsList'), { + ssr: true, +}) From ca8eed3be2d97d609215409da965392a00b02090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Tue, 17 Dec 2024 16:16:01 +0000 Subject: [PATCH 10/20] feat: works much better --- .../constants/index.ts | 1 + .../GrantCardsList/GrantCardsList.tsx | 101 +++++++++++++++-- apps/web/components/GrantCardsList/types.ts | 17 +++ .../GrantCardsList/GrantCardsListSlice.css.ts | 71 ------------ .../GrantCardsList/GrantCardsListSlice.tsx | 105 ------------------ apps/web/screens/queries/fragments.ts | 58 ++++++++-- apps/web/utils/richText.tsx | 8 +- libs/cms/src/lib/cms.elasticsearch.service.ts | 4 +- libs/cms/src/lib/cms.module.ts | 2 + libs/cms/src/lib/cms.resolver.ts | 37 ++++++ .../src/lib/generated/contentfulTypes.d.ts | 29 ++--- .../src/lib/models/grantCardsList.model.ts | 38 +++---- .../lib/search/importers/grants.service.ts | 8 ++ 13 files changed, 245 insertions(+), 234 deletions(-) create mode 100644 apps/web/components/GrantCardsList/types.ts delete mode 100644 apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.css.ts delete mode 100644 apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx diff --git a/apps/tools/contentful-role-permissions/constants/index.ts b/apps/tools/contentful-role-permissions/constants/index.ts index 10c9a6ca3257..2953394c20b9 100644 --- a/apps/tools/contentful-role-permissions/constants/index.ts +++ b/apps/tools/contentful-role-permissions/constants/index.ts @@ -35,6 +35,7 @@ export const DEFAULT_EDITABLE_ENTRY_TYPE_IDS = [ 'genericTag', 'genericTagGroup', 'graphCard', + 'grantCardsList', 'latestNewsSlice', 'linkGroup', 'menuLink', diff --git a/apps/web/components/GrantCardsList/GrantCardsList.tsx b/apps/web/components/GrantCardsList/GrantCardsList.tsx index 20dada08bdf4..a7612435d9bc 100644 --- a/apps/web/components/GrantCardsList/GrantCardsList.tsx +++ b/apps/web/components/GrantCardsList/GrantCardsList.tsx @@ -1,24 +1,112 @@ import format from 'date-fns/format' +import localeEN from 'date-fns/locale/en-GB' +import localeIS from 'date-fns/locale/is' import { Box, InfoCardGrid } from '@island.is/island-ui/core' +import { Locale } from '@island.is/shared/types' import { isDefined } from '@island.is/shared/utils' -import { GrantCardsList as GrantCardsListSchema } from '@island.is/web/graphql/schema' +import { + Grant, + GrantCardsList as GrantCardsListSchema, + GrantStatus, +} from '@island.is/web/graphql/schema' import { useLinkResolver } from '@island.is/web/hooks' import { useI18n } from '@island.is/web/i18n' +import { TranslationKeys } from './types' + interface SliceProps { slice: GrantCardsListSchema } +const formatDate = ( + date: Date, + locale: Locale, + stringFormat = 'dd.MMMM yyyy', +): string | undefined => { + try { + return format(date, stringFormat, { + locale: locale === 'is' ? localeIS : localeEN, + }) + } catch (e) { + console.warn('Error formatting date') + return + } +} + +const containsTimePart = (date: string) => date.includes('T') + const GrantCardsList = ({ slice }: SliceProps) => { const { activeLocale } = useI18n() const { linkResolver } = useLinkResolver() - if (!slice.funds) { - return undefined + const namespace = slice.namespace + + const getTranslationString = ( + key: keyof TranslationKeys, + argToInterpolate?: string, + ) => + argToInterpolate + ? namespace[key].replace('{arg}', argToInterpolate) + : namespace[key] + + const parseStatus = (grant: Grant): string | undefined => { + switch (grant.status) { + case GrantStatus.Closed: { + const date = grant.dateTo + ? formatDate(new Date(grant.dateTo), activeLocale) + : undefined + return date + ? getTranslationString( + containsTimePart(date) + ? 'applicationWasOpenToAndWith' + : 'applicationWasOpenTo', + date, + ) + : getTranslationString('applicationClosed') + } + case GrantStatus.ClosedOpeningSoon: { + const date = grant.dateFrom + ? formatDate(new Date(grant.dateFrom), activeLocale) + : undefined + return date + ? getTranslationString('applicationOpensAt', date) + : getTranslationString('applicationClosed') + } + case GrantStatus.ClosedOpeningSoonWithEstimation: { + const date = grant.dateFrom + ? formatDate(new Date(grant.dateFrom), activeLocale, 'MMMM yyyy') + : undefined + return date + ? getTranslationString('applicationEstimatedOpensAt', date) + : getTranslationString('applicationClosed') + } + case GrantStatus.AlwaysOpen: { + return getTranslationString('applicationAlwaysOpen') + } + case GrantStatus.Open: { + const date = grant.dateTo + ? formatDate(new Date(grant.dateTo), activeLocale, 'dd.MMMM.') + : undefined + return date + ? getTranslationString( + containsTimePart(date) + ? 'applicationOpensToWithDay' + : 'applicationOpensTo', + date, + ) + : getTranslationString('applicationOpen') + } + case GrantStatus.ClosedWithNote: + case GrantStatus.OpenWithNote: { + return getTranslationString('applicationSeeDescription') + } + default: + return + } } - const cards = data?.getGrants?.items + const cards = slice.resolvedGrantsList?.items ?.map((grant) => { if (grant.id) { return { @@ -36,7 +124,7 @@ const GrantCardsList = ({ slice }: SliceProps) => { grant.fund?.parentOrganization?.logo?.title ?? '', link: { - label: 'Skoða nánar', + label: getTranslationString('applicationClosed'), href: linkResolver( 'styrkjatorggrant', [grant?.applicationId ?? ''], @@ -56,8 +144,7 @@ const GrantCardsList = ({ slice }: SliceProps) => { grant.status ? { icon: 'time' as const, - //todo: fix when the text is ready - text: generateStatus(grant?.status), + text: parseStatus(grant), } : undefined, grant.categoryTags diff --git a/apps/web/components/GrantCardsList/types.ts b/apps/web/components/GrantCardsList/types.ts new file mode 100644 index 000000000000..562c567caef4 --- /dev/null +++ b/apps/web/components/GrantCardsList/types.ts @@ -0,0 +1,17 @@ +export type TranslationKeys = Partial< + Record< + | 'seeMore' + | 'applicationOpen' + | 'applicationClosed' + | 'applicationOpensSoon' + | 'applicationSeeDescription' + | 'applicationOpensAt' + | 'applicationEstimatedOpensAt' + | 'applicationOpensTo' + | 'applicationOpensToWithDay' + | 'applicationWasOpenTo' + | 'applicationWasOpenToAndWith' + | 'applicationAlwaysOpen', + string + > +> diff --git a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.css.ts b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.css.ts deleted file mode 100644 index acf08de11bef..000000000000 --- a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.css.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { theme, themeUtils } from '@island.is/island-ui/theme' -import { style } from '@vanilla-extract/css' - -export const unorderedList = style({ - listStyle: 'none', - marginTop: 16, - marginBottom: 16, - selectors: { - 'ul &': { - marginTop: 0, - marginBottom: 0, - }, - }, -}) - -export const listItem = style({ - ...themeUtils.responsiveStyle({ - xs: { - selectors: { - 'ol &': { - listStyle: 'none', - position: 'relative', - paddingLeft: theme.spacing[3], - }, - 'ol ol &': { - paddingLeft: theme.spacing[3], - }, - 'ol &:before': { - position: 'absolute', - top: '2px', - left: '8px', - counterIncrement: 'section', - content: 'counters(section, ".") " "', - color: theme.color.red400, - fontWeight: theme.typography.semiBold, - transform: 'translate(-100%, 0)', - }, - 'ul &': { - position: 'relative', - paddingLeft: theme.spacing[3], - }, - 'ul &:before': { - content: '""', - position: 'absolute', - top: '10px', - left: 0, - borderRadius: '50%', - border: `4px solid red`, - counterIncrement: 'none', - transform: 'none', - }, - '&:not(:first-child), ul ul &:first-child, ol ol &:first-child': { - marginTop: 12, - }, - '&:not(:last-child), ul ul &:last-child, ol ol &:last-child': { - marginBottom: 12, - }, - }, - }, - md: { - selectors: { - '&:not(:first-child), ul ul &:first-child, ol ol &:first-child': { - marginTop: 14, - }, - '&:not(:last-child), ul ul &:last-child, ol ol &:last-child': { - marginBottom: 14, - }, - }, - }, - }), -}) diff --git a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx b/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx deleted file mode 100644 index 8df6d86dd7b9..000000000000 --- a/apps/web/components/Organization/Slice/GrantCardsList/GrantCardsListSlice.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import format from 'date-fns/format' -import { useQuery } from '@apollo/client' - -import { Box, InfoCardGrid } from '@island.is/island-ui/core' -import { isDefined } from '@island.is/shared/utils' -import { - ContentLanguage, - GrantCardsList, - GrantStatus, - Query, -} from '@island.is/web/graphql/schema' -import { useLinkResolver, useNamespace } from '@island.is/web/hooks' -import { useI18n } from '@island.is/web/i18n' -import { GET_GRANTS_QUERY } from '@island.is/web/screens/queries' - -interface SliceProps { - slice: GrantCardsList - namespace?: Record -} - -const generateStatus = (grant: GrantStatus) => 'Opið fyrir umsóknir' - -export const GrantCardsListSlice = ({ slice, namespace }: SliceProps) => { - const { activeLocale } = useI18n() - const { linkResolver } = useLinkResolver() - const translations = useNamespace(namespace) - - const { data } = useQuery(GET_GRANTS_QUERY, { - variables: { - input: { - lang: activeLocale as ContentLanguage, - size: slice.maxNumberOfCards ?? 50, - //funds: slice.funds ? slice.funds.map((f) => f.id).join(',') : undefined, - }, - }, - }) - - if (!slice.funds) { - return undefined - } - - const cards = data?.getGrants?.items - ?.map((grant) => { - if (grant.id) { - return { - id: grant.id, - eyebrow: grant.fund?.title ?? grant.name ?? '', - subEyebrow: grant.fund?.parentOrganization?.title, - title: grant.name ?? '', - description: grant.description ?? '', - logo: - grant.fund?.featuredImage?.url ?? - grant.fund?.parentOrganization?.logo?.url ?? - '', - logoAlt: - grant.fund?.featuredImage?.title ?? - grant.fund?.parentOrganization?.logo?.title ?? - '', - link: { - label: 'Skoða nánar', - href: linkResolver( - 'styrkjatorggrant', - [grant?.applicationId ?? ''], - activeLocale, - ).href, - }, - detailLines: [ - grant.dateFrom && grant.dateTo - ? { - icon: 'calendar' as const, - text: `${format( - new Date(grant.dateFrom), - 'dd.MM.yyyy', - )} - ${format(new Date(grant.dateTo), 'dd.MM.yyyy')}`, - } - : null, - grant.status - ? { - icon: 'time' as const, - //todo: fix when the text is ready - text: generateStatus(grant?.status), - } - : undefined, - grant.categoryTags - ? { - icon: 'informationCircle' as const, - text: grant.categoryTags - .map((ct) => ct.title) - .filter(isDefined) - .join(', '), - } - : undefined, - ].filter(isDefined), - } - } - return null - }) - .filter(isDefined) - - return ( - - - - ) -} diff --git a/apps/web/screens/queries/fragments.ts b/apps/web/screens/queries/fragments.ts index 6f5dc5e43280..0b5df98aab71 100644 --- a/apps/web/screens/queries/fragments.ts +++ b/apps/web/screens/queries/fragments.ts @@ -793,17 +793,61 @@ export const slices = gql` } fragment GrantCardsListFields on GrantCardsList { + __typename + id title displayTitle - funds { - title - link { - slug - type + namespace + resolvedGrantsList { + total + items { + id + name + description + applicationId + applicationUrl { + slug + type + } + dateFrom + dateTo + status + statusText + categoryTags { + id + title + genericTagGroup { + title + } + } + typeTag { + id + title + genericTagGroup { + title + } + } + fund { + id + title + link { + slug + type + } + featuredImage { + id + url + } + parentOrganization { + id + title + logo { + url + } + } + } } } - maxNumberOfCards - sorting } fragment LatestEventsSliceFields on LatestEventsSlice { diff --git a/apps/web/utils/richText.tsx b/apps/web/utils/richText.tsx index d028ebba6809..a49b8d6cf6a7 100644 --- a/apps/web/utils/richText.tsx +++ b/apps/web/utils/richText.tsx @@ -66,7 +66,7 @@ import { FeaturedSupportQnAs as FeaturedSupportQNAsSchema, Form as FormSchema, GenericList as GenericListSchema, - GrantCardsList, + GrantCardsList as GrantCardsListSchema, MultipleStatistics as MultipleStatisticsSchema, OneColumnText, OverviewLinks as OverviewLinksSliceSchema, @@ -92,8 +92,8 @@ import { UmsCostOfLivingCalculator } from '../components/connected/UmbodsmadurSk import { WHODASCalculator } from '../components/connected/WHODAS/Calculator' import FeaturedEvents from '../components/FeaturedEvents/FeaturedEvents' import FeaturedSupportQNAs from '../components/FeaturedSupportQNAs/FeaturedSupportQNAs' +import { GrantCardsList } from '../components/GrantCardsList' import { EmbedSlice } from '../components/Organization/Slice/EmbedSlice/EmbedSlice' -import { GrantCardsListSlice } from '../components/Organization/Slice/GrantCardsList/GrantCardsListSlice' interface TranslationNamespaceProviderProps { messages: IntlConfig['messages'] @@ -292,8 +292,8 @@ const defaultRenderComponent = { const url = slice?.url ? slice.url + '?w=800' : '' return }, - GrantCardsList: (slice: GrantCardsList) => ( - + GrantCardsList: (slice: GrantCardsListSchema) => ( + ), } diff --git a/libs/cms/src/lib/cms.elasticsearch.service.ts b/libs/cms/src/lib/cms.elasticsearch.service.ts index 46508e3d8de6..3e4bcf2ab57a 100644 --- a/libs/cms/src/lib/cms.elasticsearch.service.ts +++ b/libs/cms/src/lib/cms.elasticsearch.service.ts @@ -718,7 +718,7 @@ export class CmsElasticsearchService { }) } - if (funds) { + /*if (funds) { must.push({ nested: { path: 'tags', @@ -740,7 +740,7 @@ export class CmsElasticsearchService { }, }, }) - } + }*/ const grantListResponse: ApiResponse> = await this.elasticService.findByQuery(index, { diff --git a/libs/cms/src/lib/cms.module.ts b/libs/cms/src/lib/cms.module.ts index f638377a5c16..f40201661464 100644 --- a/libs/cms/src/lib/cms.module.ts +++ b/libs/cms/src/lib/cms.module.ts @@ -9,6 +9,7 @@ import { FeaturedArticlesResolver, FeaturedEventsResolver, FeaturedSupportQNAsResolver, + GrantCardsListResolver, PowerBiSliceResolver, LatestEventsSliceResolver, TeamListResolver, @@ -41,6 +42,7 @@ import { OrganizationTitleEnByReferenceIdLoader } from './loaders/organizationTi LatestNewsSliceResolver, FeaturedArticlesResolver, FeaturedEventsResolver, + GrantCardsListResolver, FeaturedSupportQNAsResolver, OrganizationLogoByNationalIdLoader, OrganizationLogoByReferenceIdLoader, diff --git a/libs/cms/src/lib/cms.resolver.ts b/libs/cms/src/lib/cms.resolver.ts index cc26a42e6209..07606c82efb1 100644 --- a/libs/cms/src/lib/cms.resolver.ts +++ b/libs/cms/src/lib/cms.resolver.ts @@ -136,6 +136,7 @@ import { GetOrganizationPageStandaloneSitemapLevel1Input, GetOrganizationPageStandaloneSitemapLevel2Input, } from './dto/getOrganizationPageStandaloneSitemap.input' +import { GrantCardsList } from './models/grantCardsList.model' const defaultCache: CacheControlOptions = { maxAge: CACHE_CONTROL_MAX_AGE } @@ -851,6 +852,42 @@ export class PowerBiSliceResolver { } } +@Resolver(() => GrantCardsList) +@CacheControl(defaultCache) +export class GrantCardsListResolver { + constructor( + private cmsElasticsearchService: CmsElasticsearchService, + private cmsContentfulService: CmsContentfulService, + ) {} + + @ResolveField(() => GrantList) + async resolvedGrantsList( + @Parent() { resolvedGrantsList: input }: GrantCardsList, + ): Promise { + if (!input || input?.size === 0) { + return { total: 0, items: [] } + } + + return this.cmsElasticsearchService.getGrants( + getElasticsearchIndex(input.lang), + input, + ) + } + @ResolveField(() => GraphQLJSONObject) + async namespace(@Parent() { resolvedGrantsList: input }: GrantCardsList) { + try { + const respones = await this.cmsContentfulService.getNamespace( + 'GrantsPlaza', + input?.lang ?? 'is', + ) + return JSON.parse(respones?.fields || '{}') + } catch { + // Fallback to empty object in case something goes wrong when fetching or parsing namespace + return {} + } + } +} + @Resolver(() => FeaturedEvents) @CacheControl(defaultCache) export class FeaturedEventsResolver { diff --git a/libs/cms/src/lib/generated/contentfulTypes.d.ts b/libs/cms/src/lib/generated/contentfulTypes.d.ts index c7ed27763fc5..e5d135e0eae3 100644 --- a/libs/cms/src/lib/generated/contentfulTypes.d.ts +++ b/libs/cms/src/lib/generated/contentfulTypes.d.ts @@ -1838,7 +1838,7 @@ export interface IGrantFields { /** Application button label */ grantButtonLabel?: string | undefined - /** Date from */ + /** Open from */ grantDateFrom?: string | undefined /** Open from hour */ @@ -2398,21 +2398,10 @@ export interface ILinkGroupFields { name: string /** Primary Link */ - primaryLink: - | ILink - | IOrganizationSubpage - | IProjectSubpage - | IOrganizationParentSubpage + primaryLink: ILink | IOrganizationSubpage | IProjectSubpage /** Children Links */ - childrenLinks?: - | ( - | ILink - | IProjectSubpage - | IOrganizationSubpage - | IOrganizationParentSubpage - )[] - | undefined + childrenLinks?: (ILink | IProjectSubpage | IOrganizationSubpage)[] | undefined } export interface ILinkGroup extends Entry { @@ -3131,9 +3120,6 @@ export interface IOrganizationFields { /** Kennitala */ kennitala?: string | undefined - - /** Alert Banner */ - alertBanner?: IAlertBanner | undefined } export interface IOrganization extends Entry { @@ -3193,6 +3179,7 @@ export interface IOrganizationPageFields { | ISectionWithImage | IChartNumberBox | ILatestGenericListItems + | ILatestNewsSlice )[] | undefined @@ -3211,6 +3198,7 @@ export interface IOrganizationPageFields { | ITimeline | ITwoColumnText | ILatestEventsSlice + | IOverviewLinks )[] | undefined @@ -3279,6 +3267,7 @@ export interface IOrganizationPageFields { | 'thjodskjalasafn' | 'faggilding' | 'standalone' + | 'rannis' /** Theme Properties */ themeProperties?: Record | undefined @@ -3454,9 +3443,12 @@ export interface IOrganizationTag extends Entry { } export interface IOverviewLinksFields { - /** Title */ + /** Internal Title */ title?: string | undefined + /** Displayed Title */ + displayedTitle?: string | undefined + /** Overview Links */ overviewLinks?: IIntroLinkImage[] | undefined @@ -4097,6 +4089,7 @@ export interface ISliceConnectedComponentFields { | 'Starfsrettindi/ProfessionRights' | 'VMST/ParentalLeaveCalculator' | 'DigitalIceland/BenefitsOfDigitalProcesses' + | 'WHODAS/Calculator' | undefined /** Localized JSON */ diff --git a/libs/cms/src/lib/models/grantCardsList.model.ts b/libs/cms/src/lib/models/grantCardsList.model.ts index 5d178db7f459..cf6ed1e654b1 100644 --- a/libs/cms/src/lib/models/grantCardsList.model.ts +++ b/libs/cms/src/lib/models/grantCardsList.model.ts @@ -1,10 +1,13 @@ -import { Field, ObjectType, ID, registerEnumType, Int } from '@nestjs/graphql' +import { Field, ObjectType, ID, registerEnumType } from '@nestjs/graphql' import { IGrantCardsList } from '../generated/contentfulTypes' import { CacheField } from '@island.is/nest/graphql' -import { Fund, mapFund } from './fund.model' +import { mapFund } from './fund.model' import { SystemMetadata } from '@island.is/shared/types' -import { logger } from '@island.is/logging' +import { GrantList } from './grantList.model' +import { GraphQLJSONObject } from 'graphql-type-json' +import { GetGrantsInput } from '../dto/getGrants.input' +import { ElasticsearchIndexLocale } from '@island.is/content-search-index-manager' enum CardSorting { ALPHABETICAL, @@ -24,14 +27,11 @@ export class GrantCardsList { @Field({ nullable: true }) displayTitle?: boolean - @CacheField(() => [Fund], { nullable: true }) - funds?: Array + @CacheField(() => GrantList, { nullable: true }) + resolvedGrantsList?: GetGrantsInput - @Field(() => Int, { nullable: true }) - maxNumberOfCards?: number - - @CacheField(() => CardSorting, { nullable: true }) - sorting?: CardSorting + @CacheField(() => GraphQLJSONObject) + namespace?: typeof GraphQLJSONObject } export const mapGrantCardsList = ({ @@ -43,15 +43,13 @@ export const mapGrantCardsList = ({ id: sys.id, title: fields.grantCardListTitle, displayTitle: fields.grantCardsListDisplayTitle, - funds: fields.grantCardListFunds - ? fields.grantCardListFunds.map((g) => mapFund(g)) - : undefined, - maxNumberOfCards: fields.grantCardsListMaxNumberOfCards ?? undefined, - sorting: - fields.grantCardsListSorting === 'Alphabetical' - ? CardSorting.ALPHABETICAL - : fields.grantCardsListSorting === 'Most recently updated first' - ? CardSorting.MOST_RECENTLY_UPDATED_FIRST - : undefined, + resolvedGrantsList: { + lang: + sys.locale === 'is-IS' + ? 'is' + : (sys.locale as ElasticsearchIndexLocale), + funds: fields?.grantCardListFunds?.map((f) => f.sys.id) ?? undefined, + size: fields.grantCardsListMaxNumberOfCards, + }, } } diff --git a/libs/cms/src/lib/search/importers/grants.service.ts b/libs/cms/src/lib/search/importers/grants.service.ts index ead7003d046b..31a12e4b4ee0 100644 --- a/libs/cms/src/lib/search/importers/grants.service.ts +++ b/libs/cms/src/lib/search/importers/grants.service.ts @@ -91,6 +91,14 @@ export class GrantsSyncService implements CmsSyncProvider { } }) + if (mapped.fund) { + tags.push({ + type: 'referencedBy', + key: mapped.fund.id, + value: mapped.fund.title, + }) + } + if (mapped.fund?.parentOrganization?.slug) { tags.push({ key: mapped.fund.parentOrganization.slug, From 1986325bbc9de5601d3d7050c00e196f57a62655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Tue, 17 Dec 2024 16:19:28 +0000 Subject: [PATCH 11/20] chore: remove unused files --- .../GrantCardsList/GrantCardsList.css.ts | 71 ------------------- 1 file changed, 71 deletions(-) delete mode 100644 apps/web/components/GrantCardsList/GrantCardsList.css.ts diff --git a/apps/web/components/GrantCardsList/GrantCardsList.css.ts b/apps/web/components/GrantCardsList/GrantCardsList.css.ts deleted file mode 100644 index acf08de11bef..000000000000 --- a/apps/web/components/GrantCardsList/GrantCardsList.css.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { theme, themeUtils } from '@island.is/island-ui/theme' -import { style } from '@vanilla-extract/css' - -export const unorderedList = style({ - listStyle: 'none', - marginTop: 16, - marginBottom: 16, - selectors: { - 'ul &': { - marginTop: 0, - marginBottom: 0, - }, - }, -}) - -export const listItem = style({ - ...themeUtils.responsiveStyle({ - xs: { - selectors: { - 'ol &': { - listStyle: 'none', - position: 'relative', - paddingLeft: theme.spacing[3], - }, - 'ol ol &': { - paddingLeft: theme.spacing[3], - }, - 'ol &:before': { - position: 'absolute', - top: '2px', - left: '8px', - counterIncrement: 'section', - content: 'counters(section, ".") " "', - color: theme.color.red400, - fontWeight: theme.typography.semiBold, - transform: 'translate(-100%, 0)', - }, - 'ul &': { - position: 'relative', - paddingLeft: theme.spacing[3], - }, - 'ul &:before': { - content: '""', - position: 'absolute', - top: '10px', - left: 0, - borderRadius: '50%', - border: `4px solid red`, - counterIncrement: 'none', - transform: 'none', - }, - '&:not(:first-child), ul ul &:first-child, ol ol &:first-child': { - marginTop: 12, - }, - '&:not(:last-child), ul ul &:last-child, ol ol &:last-child': { - marginBottom: 12, - }, - }, - }, - md: { - selectors: { - '&:not(:first-child), ul ul &:first-child, ol ol &:first-child': { - marginTop: 14, - }, - '&:not(:last-child), ul ul &:last-child, ol ol &:last-child': { - marginBottom: 14, - }, - }, - }, - }), -}) From 9070ba591899c8361bc2aa2d037bc0635d8b6a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Tue, 17 Dec 2024 16:22:45 +0000 Subject: [PATCH 12/20] chore: remove not my contentful updates --- .../src/lib/generated/contentfulTypes.d.ts | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/libs/cms/src/lib/generated/contentfulTypes.d.ts b/libs/cms/src/lib/generated/contentfulTypes.d.ts index e5d135e0eae3..19c5e8fdbadf 100644 --- a/libs/cms/src/lib/generated/contentfulTypes.d.ts +++ b/libs/cms/src/lib/generated/contentfulTypes.d.ts @@ -2398,10 +2398,21 @@ export interface ILinkGroupFields { name: string /** Primary Link */ - primaryLink: ILink | IOrganizationSubpage | IProjectSubpage + primaryLink: + | ILink + | IOrganizationSubpage + | IProjectSubpage + | IOrganizationParentSubpage /** Children Links */ - childrenLinks?: (ILink | IProjectSubpage | IOrganizationSubpage)[] | undefined + childrenLinks?: + | ( + | ILink + | IProjectSubpage + | IOrganizationSubpage + | IOrganizationParentSubpage + )[] + | undefined } export interface ILinkGroup extends Entry { @@ -3120,6 +3131,9 @@ export interface IOrganizationFields { /** Kennitala */ kennitala?: string | undefined + + /** Alert Banner */ + alertBanner?: IAlertBanner | undefined } export interface IOrganization extends Entry { @@ -3179,7 +3193,6 @@ export interface IOrganizationPageFields { | ISectionWithImage | IChartNumberBox | ILatestGenericListItems - | ILatestNewsSlice )[] | undefined @@ -3198,7 +3211,6 @@ export interface IOrganizationPageFields { | ITimeline | ITwoColumnText | ILatestEventsSlice - | IOverviewLinks )[] | undefined @@ -3443,12 +3455,9 @@ export interface IOrganizationTag extends Entry { } export interface IOverviewLinksFields { - /** Internal Title */ + /** Title */ title?: string | undefined - /** Displayed Title */ - displayedTitle?: string | undefined - /** Overview Links */ overviewLinks?: IIntroLinkImage[] | undefined @@ -4089,7 +4098,6 @@ export interface ISliceConnectedComponentFields { | 'Starfsrettindi/ProfessionRights' | 'VMST/ParentalLeaveCalculator' | 'DigitalIceland/BenefitsOfDigitalProcesses' - | 'WHODAS/Calculator' | undefined /** Localized JSON */ From 50d74fe0ed8e043e114e203896c8b7d2559e41e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Tue, 17 Dec 2024 16:24:20 +0000 Subject: [PATCH 13/20] chore: fix up tags --- libs/cms/src/lib/search/importers/grants.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/cms/src/lib/search/importers/grants.service.ts b/libs/cms/src/lib/search/importers/grants.service.ts index 31a12e4b4ee0..a586c9942a80 100644 --- a/libs/cms/src/lib/search/importers/grants.service.ts +++ b/libs/cms/src/lib/search/importers/grants.service.ts @@ -93,7 +93,7 @@ export class GrantsSyncService implements CmsSyncProvider { if (mapped.fund) { tags.push({ - type: 'referencedBy', + type: 'fund', key: mapped.fund.id, value: mapped.fund.title, }) @@ -101,8 +101,8 @@ export class GrantsSyncService implements CmsSyncProvider { if (mapped.fund?.parentOrganization?.slug) { tags.push({ - key: mapped.fund.parentOrganization.slug, type: 'organization', + key: mapped.fund.parentOrganization.slug, value: mapped.fund.parentOrganization.title, }) } From 8d33ff6948cd2b662a43a38ba05d141f37c65f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 18 Dec 2024 10:46:34 +0000 Subject: [PATCH 14/20] feat: different ui for 1 grant --- .../GrantCardsList/GrantCardsList.tsx | 21 ++++++++++++++++++- apps/web/components/GrantCardsList/types.ts | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/web/components/GrantCardsList/GrantCardsList.tsx b/apps/web/components/GrantCardsList/GrantCardsList.tsx index a7612435d9bc..ac025f07e6af 100644 --- a/apps/web/components/GrantCardsList/GrantCardsList.tsx +++ b/apps/web/components/GrantCardsList/GrantCardsList.tsx @@ -1,8 +1,9 @@ import format from 'date-fns/format' import localeEN from 'date-fns/locale/en-GB' import localeIS from 'date-fns/locale/is' +import { useRouter } from 'next/router' -import { Box, InfoCardGrid } from '@island.is/island-ui/core' +import { ActionCard, Box, InfoCardGrid } from '@island.is/island-ui/core' import { Locale } from '@island.is/shared/types' import { isDefined } from '@island.is/shared/utils' import { @@ -39,6 +40,7 @@ const containsTimePart = (date: string) => date.includes('T') const GrantCardsList = ({ slice }: SliceProps) => { const { activeLocale } = useI18n() const { linkResolver } = useLinkResolver() + const router = useRouter() const namespace = slice.namespace @@ -106,6 +108,23 @@ const GrantCardsList = ({ slice }: SliceProps) => { } } + if (slice.resolvedGrantsList?.items.length === 1) { + const grant = slice.resolvedGrantsList.items[0] + return ( + router.push(grant.applicationUrl?.slug ?? ''), + icon: 'open', + iconType: 'outline', + }} + /> + ) + } + const cards = slice.resolvedGrantsList?.items ?.map((grant) => { if (grant.id) { diff --git a/apps/web/components/GrantCardsList/types.ts b/apps/web/components/GrantCardsList/types.ts index 562c567caef4..b7d504feb245 100644 --- a/apps/web/components/GrantCardsList/types.ts +++ b/apps/web/components/GrantCardsList/types.ts @@ -1,6 +1,7 @@ export type TranslationKeys = Partial< Record< | 'seeMore' + | 'apply' | 'applicationOpen' | 'applicationClosed' | 'applicationOpensSoon' From 78c8ed8369ba41133d8e8cd685978c054ad10e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 18 Dec 2024 10:47:37 +0000 Subject: [PATCH 15/20] fix: use fund in query --- libs/cms/src/lib/cms.elasticsearch.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/cms/src/lib/cms.elasticsearch.service.ts b/libs/cms/src/lib/cms.elasticsearch.service.ts index 3e4bcf2ab57a..46508e3d8de6 100644 --- a/libs/cms/src/lib/cms.elasticsearch.service.ts +++ b/libs/cms/src/lib/cms.elasticsearch.service.ts @@ -718,7 +718,7 @@ export class CmsElasticsearchService { }) } - /*if (funds) { + if (funds) { must.push({ nested: { path: 'tags', @@ -740,7 +740,7 @@ export class CmsElasticsearchService { }, }, }) - }*/ + } const grantListResponse: ApiResponse> = await this.elasticService.findByQuery(index, { From 71a8d65610d59f4f9f84d97c72ae0d4600122e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 18 Dec 2024 10:58:07 +0000 Subject: [PATCH 16/20] fix: review comments --- apps/web/components/GrantCardsList/GrantCardsList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/components/GrantCardsList/GrantCardsList.tsx b/apps/web/components/GrantCardsList/GrantCardsList.tsx index ac025f07e6af..c2b816118539 100644 --- a/apps/web/components/GrantCardsList/GrantCardsList.tsx +++ b/apps/web/components/GrantCardsList/GrantCardsList.tsx @@ -23,7 +23,7 @@ interface SliceProps { const formatDate = ( date: Date, locale: Locale, - stringFormat = 'dd.MMMM yyyy', + stringFormat = 'dd. MMMM yyyy', ): string | undefined => { try { return format(date, stringFormat, { @@ -88,7 +88,7 @@ const GrantCardsList = ({ slice }: SliceProps) => { } case GrantStatus.Open: { const date = grant.dateTo - ? formatDate(new Date(grant.dateTo), activeLocale, 'dd.MMMM.') + ? formatDate(new Date(grant.dateTo), activeLocale, 'dd. MMMM.') : undefined return date ? getTranslationString( From c5a8b46543632a19e264b43ee850dc7783797e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 18 Dec 2024 14:42:43 +0000 Subject: [PATCH 17/20] fix: add import --- apps/web/screens/Home/Home.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/screens/Home/Home.tsx b/apps/web/screens/Home/Home.tsx index 8101caf24a27..a6b9087537ea 100644 --- a/apps/web/screens/Home/Home.tsx +++ b/apps/web/screens/Home/Home.tsx @@ -19,6 +19,7 @@ import { LifeEventPage, QueryGetArticleCategoriesArgs, QueryGetFrontpageArgs, + QueryGetNewsArgs, } from '@island.is/web/graphql/schema' import { useNamespace } from '@island.is/web/hooks' import { useI18n } from '@island.is/web/i18n' From 6c5db772a87bc3051cfa9f202c11e01dd40d2971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Wed, 18 Dec 2024 16:23:37 +0000 Subject: [PATCH 18/20] chore: remove import --- libs/cms/src/lib/models/grantCardsList.model.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/cms/src/lib/models/grantCardsList.model.ts b/libs/cms/src/lib/models/grantCardsList.model.ts index cf6ed1e654b1..98a749704aa3 100644 --- a/libs/cms/src/lib/models/grantCardsList.model.ts +++ b/libs/cms/src/lib/models/grantCardsList.model.ts @@ -2,7 +2,6 @@ import { Field, ObjectType, ID, registerEnumType } from '@nestjs/graphql' import { IGrantCardsList } from '../generated/contentfulTypes' import { CacheField } from '@island.is/nest/graphql' -import { mapFund } from './fund.model' import { SystemMetadata } from '@island.is/shared/types' import { GrantList } from './grantList.model' import { GraphQLJSONObject } from 'graphql-type-json' From 56eed5a2479ece59f06bab3f3944bd249ebc9994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Thu, 19 Dec 2024 09:21:23 +0000 Subject: [PATCH 19/20] fix: import different --- apps/web/components/TableOfContents/TableOfContents.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/components/TableOfContents/TableOfContents.tsx b/apps/web/components/TableOfContents/TableOfContents.tsx index ca369e5327a4..0a2c3a607cf6 100644 --- a/apps/web/components/TableOfContents/TableOfContents.tsx +++ b/apps/web/components/TableOfContents/TableOfContents.tsx @@ -1,7 +1,7 @@ import { FC, useMemo } from 'react' -import { Slice } from '@island.is/api/schema' import { TableOfContents } from '@island.is/island-ui/core' +import { Slice } from '@island.is/web/graphql/schema' import { scrollTo } from '@island.is/web/hooks/useScrollSpy' export const TOC: FC< From 36beec4c517104ff76f459b02443a1ef5cf58850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Mon, 6 Jan 2025 10:24:57 +0000 Subject: [PATCH 20/20] fix: init --- .../Grants/SearchResults/SearchResultsContent.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx b/apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx index b95daf770f97..5e4d53eeacea 100644 --- a/apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx +++ b/apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx @@ -7,7 +7,7 @@ import { Box, Button, InfoCardGrid, Text } from '@island.is/island-ui/core' import { theme } from '@island.is/island-ui/theme' import { Locale } from '@island.is/shared/types' import { isDefined } from '@island.is/shared/utils' -import { Grant } from '@island.is/web/graphql/schema' +import { Grant, GrantStatus } from '@island.is/web/graphql/schema' import { useLinkResolver } from '@island.is/web/hooks' import { m } from '../messages' @@ -97,7 +97,14 @@ export const SearchResultsContent = ({ grants, subheader, locale }: Props) => { ).href, }, detailLines: [ - grant.dateFrom && grant.dateTo + { + icon: 'time' as const, + text: status.deadlineStatus, + }, + grant.status !== + GrantStatus.ClosedOpeningSoonWithEstimation && + grant.dateFrom && + grant.dateTo ? { icon: 'calendar' as const, text: `${format( @@ -106,10 +113,6 @@ export const SearchResultsContent = ({ grants, subheader, locale }: Props) => { )} - ${format(new Date(grant.dateTo), 'dd.MM.yyyy')}`, } : null, - { - icon: 'time' as const, - text: status.deadlineStatus, - }, grant.categoryTags ? { icon: 'informationCircle' as const,