Skip to content

Commit

Permalink
feat: add tags to map filters
Browse files Browse the repository at this point in the history
  • Loading branch information
benfurber committed Nov 11, 2024
1 parent 69bd593 commit f58266d
Show file tree
Hide file tree
Showing 19 changed files with 300 additions and 147 deletions.
16 changes: 16 additions & 0 deletions packages/components/src/MapFilterList/MapFilterList.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ const availableFilters: MapFilterOptionsList = [
filterType: 'workspaceType',
label: 'Mix',
},
{
_id: 'tag1',
filterType: 'profileTag',
label: 'Tag 1',
},
{
_id: 'tag2',
filterType: 'profileTag',
label: 'Tag 2',
},
{
_id: 'tag3',
filterType: 'profileTag',
label: 'Tag 3',
},
]

export const Default: StoryFn<typeof MapFilterList> = () => {
Expand All @@ -82,6 +97,7 @@ export const Default: StoryFn<typeof MapFilterList> = () => {
availableFilters={availableFilters}
onFilterChange={onFilterChange}
onClose={onClose}
pinsCount={7}
/>
)
}
71 changes: 45 additions & 26 deletions packages/components/src/MapFilterList/MapFilterList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Flex, Heading, Image, Text } from 'theme-ui'
import { Flex, Heading, Text } from 'theme-ui'

import { Button } from '../Button/Button'
import { ButtonIcon } from '../ButtonIcon/ButtonIcon'
import { MemberBadge } from '../MemberBadge/MemberBadge'
import { MapFilterListItem } from './MapFilterListItem'
Expand All @@ -16,31 +17,43 @@ export interface IProps {
availableFilters: MapFilterOptionsList
onClose: () => void
onFilterChange: (filter: MapFilterOption) => void
pinsCount: number
}

export const MapFilterList = (props: IProps) => {
const { activeFilters, availableFilters, onClose, onFilterChange } = props
const {
activeFilters,
availableFilters,
onClose,
onFilterChange,
pinsCount,
} = props

const profileFilters = availableFilters.filter(
({ filterType }) => filterType === 'profileType',
)
const workspaceFilters = availableFilters.filter(
({ filterType }) => filterType === 'workspaceType',

const tagFilters = availableFilters.filter(
({ filterType }) => filterType === 'profileTag',
)

const isActive = (checkingFilter: string) =>
!!activeFilters.find((filter) => filter.label === checkingFilter)

const buttonLabel = `Show ${pinsCount} result${pinsCount === 1 ? '' : 's'}`

return (
<Flex
data-cy="MapFilterList"
sx={{
flexDirection: 'column',
position: 'relative',
gap: 2,
gap: 4,
}}
>
<Flex sx={{ gap: 2 }}>
<Flex
sx={{ alignItems: 'center', gap: 2, justifyContent: 'space-between' }}
>
<Heading as="h3" variant="small">
So what are you looking for?
</Heading>
Expand All @@ -53,61 +66,67 @@ export const MapFilterList = (props: IProps) => {
/>
</Flex>

{workspaceFilters.length > 0 && (
<>
<Text>Workspace:</Text>
{profileFilters.length > 0 && (
<Flex sx={{ gap: 1, flexDirection: 'column' }}>
<Text>Profiles:</Text>
<MapFilterListWrapper>
{workspaceFilters.map((typeFilter, index) => {
{profileFilters.map((typeFilter, index) => {
const onClick = () => onFilterChange(typeFilter)

return (
<MapFilterListItem
active={isActive(typeFilter.label)}
key={index}
onClick={onClick}
filterType="profile"
>
{typeFilter.imageSrc && (
<Image
src={typeFilter.imageSrc}
sx={{ height: 30, width: 30 }}
/>
)}
<MemberBadge
size={30}
profileType={typeFilter._id as ProfileTypeName}
/>
<Text variant="quiet" sx={{ fontSize: 1 }}>
{typeFilter.label}
</Text>
</MapFilterListItem>
)
})}
</MapFilterListWrapper>
</>
</Flex>
)}

{profileFilters.length > 0 && (
<>
<Text>Profiles:</Text>
{tagFilters.length > 0 && (
<Flex sx={{ gap: 1, flexDirection: 'column' }}>
<Text>Activities:</Text>
<MapFilterListWrapper>
{profileFilters.map((typeFilter, index) => {
{tagFilters.map((typeFilter, index) => {
const onClick = () => onFilterChange(typeFilter)

return (
<MapFilterListItem
active={isActive(typeFilter.label)}
key={index}
onClick={onClick}
sx={{ maxWidth: 'auto', width: 'auto' }}
filterType="tag"
>
<MemberBadge
size={30}
profileType={typeFilter._id as ProfileTypeName}
/>
<Text variant="quiet" sx={{ fontSize: 1 }}>
{typeFilter.label}
</Text>
</MapFilterListItem>
)
})}
</MapFilterListWrapper>
</>
</Flex>
)}

<Button
data-cy="MapFilterList-ShowResultsButton"
icon="sliders"
onClick={() => onClose()}
sx={{ alignSelf: 'flex-start' }}
>
{buttonLabel}
</Button>
</Flex>
)
}
12 changes: 10 additions & 2 deletions packages/components/src/MapFilterList/MapFilterListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { CardButton } from '../CardButton/CardButton'

import type { ThemeUIStyleObject } from 'theme-ui'

interface IProps {
active: boolean
onClick: () => void
children: React.ReactNode
filterType: string
sx?: ThemeUIStyleObject | undefined
}

export const MapFilterListItem = ({ active, onClick, children }: IProps) => {
export const MapFilterListItem = (props: IProps) => {
const { active, onClick, children, filterType, sx } = props
return (
<CardButton
data-cy={`MapFilterListItem${active ? '-active' : ''}`}
data-cy={`MapFilterListItem-${filterType}${active ? '-active' : ''}`}
onClick={onClick}
extrastyles={{
display: 'flex',
maxWidth: ['100%', '49%'],
width: '500px',
flexDirection: 'row',
backgroundColor: 'offWhite',
padding: 1,
Expand All @@ -27,6 +34,7 @@ export const MapFilterListItem = ({ active, onClick, children }: IProps) => {
borderColor: 'offWhite',
':hover': { borderColor: 'offWhite' },
}),
...sx,
}}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export const MapFilterListWrapper = ({ children }: IProps) => (
data-cy="MapFilterList"
sx={{
listStyle: 'none',
flexWrap: 'nowrap',
flexWrap: 'wrap',
gap: 2,
flexDirection: 'column',
flexDirection: 'row',
padding: 0,
}}
>
Expand Down
6 changes: 4 additions & 2 deletions packages/components/src/ProfileTagsList/ProfileTagsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { Flex } from 'theme-ui'
import { Category } from '../Category/Category'

import type { ITag } from 'oa-shared'
import type { ThemeUIStyleObject } from 'theme-ui'

export interface IProps {
tags: ITag[]
sx?: ThemeUIStyleObject | undefined
}

export const ProfileTagsList = ({ tags }: IProps) => {
export const ProfileTagsList = ({ sx, tags }: IProps) => {
return (
<Flex data-cy="ProfileTagsList" sx={{ gap: 2, flexWrap: 'wrap' }}>
<Flex sx={{ gap: 2, flexWrap: 'wrap', ...sx }}>
{tags.map(
(tag, index) =>
tag?.label && (
Expand Down
10 changes: 7 additions & 3 deletions packages/cypress/src/integration/map.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ describe('[Map]', () => {
.children()
.should('have.length', profileTypesCount)
cy.get('[data-cy=MapListFilter]').first().click()
// Reduction in coverage until temp API removed
// cy.get('[data-cy="list-results"]').contains('6 results in view')

cy.get('[data-cy=MapListFilter-active]').first().click()
cy.get('[data-cy="list-results"]').contains(/\d+ results in view/)

Expand All @@ -57,7 +56,12 @@ describe('[Map]', () => {
cy.get('[data-cy=MapFilterList]').should('not.exist')
cy.get('[data-cy=MapFilterList-OpenButton]').first().click()
cy.get('[data-cy=MapFilterList]').should('be.visible')
cy.get('[data-cy=MapFilterList-CloseButton]').first().click()
cy.get('[data-cy=MapFilterListItem-profile]').first().click()
cy.get('[data-cy=MapFilterListItem-profile-active]').first().click()
cy.get('[data-cy=MapFilterListItem-tag]').first().click()
cy.get('[data-cy=MapFilterListItem-tag-active]').first().click()
cy.get('[data-cy=MapFilterList-ShowResultsButton]').first().click()

cy.step('As the user moves in the list updates')
for (let i = 0; i < 6; i++) {
cy.get('.leaflet-control-zoom-in').click()
Expand Down
13 changes: 11 additions & 2 deletions packages/cypress/src/integration/settings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('[Settings]', () => {
const description = "I'm a very active member"
const mapPinDescription = 'Fun, vibrant and full of amazing people'
const profileType = 'member'
const tag = 'Sewing'
const tag = ['Sewing', 'Accounting']
const user = generateNewUserDetails()
const url = 'https://social.network'

Expand Down Expand Up @@ -80,7 +80,8 @@ describe('[Settings]', () => {
country,
description,
})
cy.selectTag(tag, '[data-cy=tag-select]')
cy.selectTag(tag[0], '[data-cy=tag-select]')
cy.selectTag(tag[1], '[data-cy=tag-select]')
cy.get('[data-cy="country:BO"]')

cy.step('Errors if trying to upload invalid image')
Expand Down Expand Up @@ -131,6 +132,8 @@ describe('[Settings]', () => {
cy.contains(displayName)
cy.contains(description)
cy.contains(country)
cy.contains(tag[0])
cy.contains(tag[1])
cy.get('[data-cy="country:bo"]')
cy.get(`[data-cy="MemberBadge-${profileType}"]`)
cy.get('[data-cy="profile-avatar"]')
Expand All @@ -153,7 +156,13 @@ describe('[Settings]', () => {
cy.get('[data-cy="tab-Profile"]').click()
cy.get('[data-cy=location-dropdown]').should('not.exist')

cy.step('Can view pin on new map')
cy.visit('/map#ci_myn7wmq')
cy.get('[data-cy=Banner]').contains('Test it out!').click()
cy.get('[data-cy=CardListItem]').contains(user.username)

cy.step('Can delete map pin')
cy.visit('/settings')
cy.get('[data-cy="tab-Map"]').click()
cy.get('[data-cy=remove-map-pin]').click()
cy.get('[data-cy="Confirm.modal: Confirm"]').click()
Expand Down
10 changes: 0 additions & 10 deletions packages/cypress/src/support/db/endpoints.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
import { generateDBEndpoints } from 'oa-shared'

// React apps populate a process variable, however it might not always be accessible outside
// (e.g. cypress will instead use it's own env to populate a prefix)

/**
* A prefix can be used to simplify large-scale schema changes or multisite hosting
* and allow multiple sites to use one DB (used for parallel test seed DBs)
* e.g. oa_
* SessionStorage prefixes are used to allow test ci environments to dynamically set a db endpoint
*/

/**
* Mapping of generic database endpoints to specific prefixed and revisioned versions for the
* current implementation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const asOptions = (mapPins, items: Array<IMapGrouping>): FilterGroupOption[] =>
return {
label: item.displayName,
value,
number: filterMapPinsByType(mapPins, filterType).length,
number: filterMapPinsByType(mapPins, filterType, false).length,
imageElement:
(item.type as string) === 'verified' ? (
<Image src={VerifiedBadgeIcon} width={ICON_SIZE} />
Expand Down
Loading

0 comments on commit f58266d

Please sign in to comment.