Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): Add order by for team list #17545

Merged
merged 7 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ interface TeamMemberListWrapperProps {
id: string
filterTags?: GenericTag[] | null
showSearchInput?: boolean
orderBy?: string
RunarVestmann marked this conversation as resolved.
Show resolved Hide resolved
}

export const TeamMemberListWrapper = ({
id,
filterTags,
showSearchInput,
orderBy,
}: TeamMemberListWrapperProps) => {
const searchQueryId = `${id}q`
const pageQueryId = `${id}page`
Expand Down Expand Up @@ -86,6 +88,7 @@ export const TeamMemberListWrapper = ({
queryString: searchValue,
tags,
tagGroups,
orderBy,
},
},
})
Expand Down Expand Up @@ -113,6 +116,7 @@ interface TeamListSliceProps extends TeamListProps {
id: string
filterTags?: GenericTag[] | null
showSearchInput?: boolean
orderBy?: string
}

export const TeamListSlice = ({
Expand All @@ -121,13 +125,15 @@ export const TeamListSlice = ({
filterTags,
id,
showSearchInput = true,
orderBy = 'Name',
RunarVestmann marked this conversation as resolved.
Show resolved Hide resolved
}: TeamListSliceProps) => {
if (variant === 'accordion') {
return (
<TeamMemberListWrapper
id={id}
filterTags={filterTags}
showSearchInput={showSearchInput}
orderBy={orderBy}
/>
)
}
Expand Down
1 change: 1 addition & 0 deletions apps/web/screens/queries/fragments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ export const slices = gql`
}
}
showSearchInput
teamMemberOrder
}

fragment ContactUsFields on ContactUs {
Expand Down
2 changes: 2 additions & 0 deletions apps/web/utils/richText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import {
FeaturedSupportQnAs as FeaturedSupportQNAsSchema,
Form as FormSchema,
GenericList as GenericListSchema,
GetTeamMembersInputOrderBy,
GrantCardsList as GrantCardsListSchema,
MultipleStatistics as MultipleStatisticsSchema,
OneColumnText,
Expand Down Expand Up @@ -284,6 +285,7 @@ const defaultRenderComponent = {
filterTags={slice.filterTags}
variant={slice.variant as 'accordion' | 'card'}
showSearchInput={slice.showSearchInput ?? true}
orderBy={slice.teamMemberOrder ?? GetTeamMembersInputOrderBy.Name}
/>
),
Image: (slice: ImageProps) => {
Expand Down
11 changes: 9 additions & 2 deletions libs/cms/src/lib/cms.elasticsearch.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ import { GenericListItemResponse } from './models/genericListItemResponse.model'
import { GetCustomSubpageInput } from './dto/getCustomSubpage.input'
import { GetGenericListItemBySlugInput } from './dto/getGenericListItemBySlug.input'
import { GenericListItem } from './models/genericListItem.model'
import { GetTeamMembersInput } from './dto/getTeamMembers.input'
import {
GetTeamMembersInput,
GetTeamMembersInputOrderBy,
} from './dto/getTeamMembers.input'
import { TeamMemberResponse } from './models/teamMemberResponse.model'
import { GetGrantsInput } from './dto/getGrants.input'
import { Grant } from './models/grant.model'
Expand Down Expand Up @@ -473,7 +476,7 @@ export class CmsElasticsearchService {
tags?: string[]
tagGroups?: Record<string, string[]>
type: ListItemType
orderBy?: GetGenericListItemsInputOrderBy
orderBy?: GetGenericListItemsInputOrderBy | GetTeamMembersInputOrderBy
}): Promise<
ListItemType extends 'webGenericListItem'
? Omit<GenericListItemResponse, 'input'>
Expand Down Expand Up @@ -603,6 +606,10 @@ export class CmsElasticsearchService {
...input,
type: 'webTeamMember',
listId: input.teamListId,
orderBy:
input.orderBy === GetTeamMembersInputOrderBy.MANUAL
? GetGenericListItemsInputOrderBy.DATE
: GetGenericListItemsInputOrderBy.TITLE,
})

return {
Expand Down
10 changes: 9 additions & 1 deletion libs/cms/src/lib/cms.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ import {
GetOrganizationPageStandaloneSitemapLevel2Input,
} from './dto/getOrganizationPageStandaloneSitemap.input'
import { GrantCardsList } from './models/grantCardsList.model'
import { sortAlpha } from '@island.is/shared/utils'
import { GetTeamMembersInputOrderBy } from './dto/getTeamMembers.input'

const defaultCache: CacheControlOptions = { maxAge: CACHE_CONTROL_MAX_AGE }

Expand Down Expand Up @@ -928,8 +930,14 @@ export class FeaturedEventsResolver {
export class TeamListResolver {
@ResolveField(() => [TeamMember])
async teamMembers(@Parent() teamList: TeamList) {
if (teamList?.variant === 'accordion') {
return []
}

// The 'accordion' variant has a search so to reduce the inital payload (since it isn't used) we simply return an empty list
return teamList?.variant === 'accordion' ? [] : teamList?.teamMembers ?? []
return teamList?.teamMemberOrder !== GetTeamMembersInputOrderBy.MANUAL
? teamList?.teamMembers?.sort(sortAlpha('name') as any)
: teamList?.teamMembers
RunarVestmann marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
21 changes: 20 additions & 1 deletion libs/cms/src/lib/dto/getTeamMembers.input.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
import { Field, InputType, Int, ObjectType } from '@nestjs/graphql'
import {
Field,
InputType,
Int,
ObjectType,
registerEnumType,
} from '@nestjs/graphql'
import { IsInt, IsOptional, IsString } from 'class-validator'
import GraphQLJSON from 'graphql-type-json'
import { ElasticsearchIndexLocale } from '@island.is/content-search-index-manager'
import { CacheField } from '@island.is/nest/graphql'

export enum GetTeamMembersInputOrderBy {
NAME = 'Name',
MANUAL = 'Manual',
}

RunarVestmann marked this conversation as resolved.
Show resolved Hide resolved
registerEnumType(GetTeamMembersInputOrderBy, {
name: 'GetTeamMembersInputOrderBy',
})

@InputType()
@ObjectType('TeamMemberResponseInput')
Expand Down Expand Up @@ -34,4 +50,7 @@ export class GetTeamMembersInput {

@Field(() => GraphQLJSON, { nullable: true })
tagGroups?: Record<string, string[]>

@CacheField(() => GetTeamMembersInputOrderBy, { nullable: true })
orderBy?: GetTeamMembersInputOrderBy
}
3 changes: 3 additions & 0 deletions libs/cms/src/lib/generated/contentfulTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4733,6 +4733,9 @@ export interface ITeamListFields {

/** Show Search Input */
showSearchInput?: boolean | undefined

/** Order By */
orderBy?: 'A - Z' | 'Manual' | undefined
}

/** list of team members */
Expand Down
14 changes: 13 additions & 1 deletion libs/cms/src/lib/models/teamList.model.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Field, ObjectType, ID } from '@nestjs/graphql'
import { CacheField } from '@island.is/nest/graphql'
import { ITeamList } from '../generated/contentfulTypes'
import { ITeamList, ITeamListFields } from '../generated/contentfulTypes'
import { SystemMetadata } from '@island.is/shared/types'
import { TeamMember, mapTeamMember } from './teamMember.model'
import { GenericTag } from './genericTag.model'
import { GetTeamMembersInputOrderBy } from '../dto/getTeamMembers.input'

@ObjectType()
export class TeamList {
Expand All @@ -19,6 +20,9 @@ export class TeamList {
@CacheField(() => [GenericTag], { nullable: true })
filterTags?: GenericTag[]

@CacheField(() => GetTeamMembersInputOrderBy, { nullable: true })
teamMemberOrder?: GetTeamMembersInputOrderBy

@Field(() => Boolean, { nullable: true })
showSearchInput?: boolean
}
Expand Down Expand Up @@ -57,12 +61,20 @@ export const mapTeamList = ({
teamMember.tagGroups = tagGroups
}

const mapOrderBy = (orderBy?: ITeamListFields['orderBy']) => {
if (orderBy === GetTeamMembersInputOrderBy.MANUAL) {
return GetTeamMembersInputOrderBy.MANUAL
}
return GetTeamMembersInputOrderBy.NAME
}

return {
typename: 'TeamList',
id: sys.id,
teamMembers,
variant: fields.variant === 'accordion' ? 'accordion' : 'card',
filterTags,
showSearchInput: fields.showSearchInput ?? true,
teamMemberOrder: mapOrderBy(fields.orderBy),
}
}
2 changes: 2 additions & 0 deletions libs/cms/src/lib/search/importers/teamList.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class TeamListSyncService implements CmsSyncProvider<ITeamList> {

for (const teamListEntry of entries) {
const teamList = mapTeamList(teamListEntry)
let counter = teamList.teamMembers?.length ?? 0
for (const member of teamList.teamMembers ?? []) {
try {
const memberEntry = teamListEntry.fields.teamMembers?.find(
Expand Down Expand Up @@ -62,6 +63,7 @@ export class TeamListSyncService implements CmsSyncProvider<ITeamList> {
],
dateCreated: member.createdAt ?? '',
dateUpdated: new Date().getTime().toString(),
releaseDate: String(counter--),
})
} catch (error) {
logger.warn('Failed to import Team Member', {
Expand Down
1 change: 1 addition & 0 deletions libs/island-ui/contentful/src/lib/TeamList/TeamList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface TeamListProps {
email?: string
phone?: string
}
orderBy?: string
RunarVestmann marked this conversation as resolved.
Show resolved Hide resolved
teamMembers: {
title: string
name: string
Expand Down
Loading