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

Browse/Search facets section #466

Merged
merged 30 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
50f0665
refactor: remove temporal use case to get all blocks with get all blo…
g-saracca Aug 19, 2024
048e624
feat: add get collection facets domain infra and hook
g-saracca Aug 19, 2024
ee63d00
feat: domain & infra & hook for all facetable fields
g-saracca Aug 19, 2024
97275d2
fix: label index and avoid scaling item while dragging
g-saracca Aug 19, 2024
fa30cd2
feat(design sytem): export item interface also
g-saracca Aug 20, 2024
8c36f7a
feat: integrate transfer list comp
g-saracca Aug 20, 2024
9799fef
feat: improve transfer list responsiveness
g-saracca Aug 20, 2024
260535e
feat: use facets from parent checkbox
g-saracca Aug 20, 2024
32e43b1
tests: fix and add tests
g-saracca Aug 20, 2024
75f56f9
test: fix e2e test
g-saracca Aug 20, 2024
c41eeac
feat: change and add locale
g-saracca Aug 20, 2024
6c960c2
Merge branch 'develop' into feat/460-browse-search-facets-section
g-saracca Aug 21, 2024
9eaa5e7
feat: disabled tranfer list when use facets from parent is checked
g-saracca Aug 21, 2024
fae1d97
feat: add allowed tags helper text to description field
g-saracca Aug 21, 2024
8d05282
refactor: avoid reducing metadata blocks info data
g-saracca Aug 21, 2024
ddf844e
feat: remove hardcoded conditionally required field, decide it based …
g-saracca Aug 21, 2024
c0472bf
feat(desing system): fix filter to left
g-saracca Aug 23, 2024
2565991
test: increase defaultCommandTimeout
g-saracca Aug 23, 2024
eef989d
feat: add block info to facetable fields
g-saracca Aug 23, 2024
ec94a3d
feat(design system): fix filter all to left
g-saracca Aug 23, 2024
64d20b2
feat: select to filter facets by block
g-saracca Aug 23, 2024
7875e4c
feat: select container styles
g-saracca Aug 23, 2024
41e524d
test: add cases for select facets by block
g-saracca Aug 23, 2024
f26803d
change locale
g-saracca Aug 27, 2024
0fd7bd4
feat: S3 as default selected, temporary
g-saracca Aug 28, 2024
5d0ea68
docs: storage s3 selector
g-saracca Aug 28, 2024
06ad7dc
Merge branch 'develop' into feat/460-browse-search-facets-section
g-saracca Sep 6, 2024
3e221a1
feat: handle data loading errors and add test to it
g-saracca Sep 10, 2024
2ffddd8
test: e2e test case for selected facets
g-saracca Sep 10, 2024
e4280a5
test: force on click to avoid timeouts
g-saracca Sep 10, 2024
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ The environment is accessible through the following URLs:
> #### Create/Edit Collection Page Identifier Field
>
> A feature has been added to suggest an identifier to the user based on the collection name entered.
>
> #### Create/Edit Collection Page Storage Field
>
> Given that at the moment the SPA only supports file uploading through direct upload (S3), the storage selector on the create collection
> page is disabled. The collection is always created using the default storage, which must be S3

</details>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type ListProps =
side: 'left'
checked: TransferListItem[]
onToggle: (item: TransferListItem) => () => void
disabled: boolean
rightItems?: never
setRight?: never
onChange?: never
Expand All @@ -21,6 +22,7 @@ type ListProps =
side: 'right'
checked: TransferListItem[]
onToggle: (item: TransferListItem) => () => void
disabled: boolean
rightItems: TransferListItem[]
setRight: React.Dispatch<React.SetStateAction<TransferListItem[]>>
onChange?: (selected: TransferListItem[]) => void
Expand All @@ -31,6 +33,7 @@ export const ItemsList = ({
side,
checked,
onToggle,
disabled,
rightItems,
setRight,
onChange
Expand All @@ -44,6 +47,7 @@ export const ItemsList = ({
side={side}
checked={checked}
onToggle={onToggle}
disabled={disabled}
key={item.value}
/>
))}
Expand Down Expand Up @@ -76,6 +80,7 @@ export const ItemsList = ({
side={side}
checked={checked}
onToggle={onToggle}
disabled={disabled}
key={item.value}
/>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,57 @@ interface ListItemProps {
side: 'left' | 'right'
checked: readonly TransferListItem[]
onToggle: (item: TransferListItem) => () => void
disabled: boolean
}

export const ListItem = ({ item, side, checked, onToggle }: ListItemProps) => {
export const ListItem = ({ item, side, checked, onToggle, disabled }: ListItemProps) => {
const { attributes, listeners, transform, transition, setNodeRef, setActivatorNodeRef } =
useSortable({ id: item.id })

const attributesCheckingDisabled = disabled
? { ...attributes, ['aria-disabled']: true, tabIndex: -1 }
: attributes

const uniqueID = useId()
const labelId = `transfer-list-item-${item.value}-label-${uniqueID}`

if (side === 'left') {
return (
<ListGroup.Item className={styles['list-item']}>
<ListGroup.Item
className={`${styles['list-item']} ${disabled ? styles['disabled'] : ''}`}
disabled={disabled}>
<Form.Group.Checkbox
label={item.label}
onChange={onToggle(item)}
id={labelId}
checked={checked.indexOf(item) !== -1}
disabled={disabled}
/>
</ListGroup.Item>
)
}

const style = {
transform: CSS.Transform.toString(transform),
transform: CSS.Translate.toString(transform),
transition
}

return (
<ListGroup.Item
ref={setNodeRef}
{...attributes}
{...attributesCheckingDisabled}
role=""
style={style}
className={styles['list-item']}>
className={`${styles['list-item']} ${disabled ? styles['disabled'] : ''}`}
disabled={disabled}>
<Stack direction="horizontal" gap={1}>
<button
type="button"
ref={setActivatorNodeRef}
{...listeners}
className={styles['drag-handle']}
aria-label="press space to select and keys to drag">
className={`${styles['drag-handle']} ${disabled ? styles['disabled'] : ''}`}
aria-label="press space to select and keys to drag"
disabled={disabled}>
<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg">
<circle cx="9" cy="6" r="1.5" fill="#777" />
<circle cx="15" cy="6" r="1.5" fill="#777" />
Expand All @@ -67,6 +77,7 @@ export const ListItem = ({ item, side, checked, onToggle }: ListItemProps) => {
onChange={onToggle(item)}
id={labelId}
checked={checked.indexOf(item) !== -1}
disabled={disabled}
/>
</Stack>
</ListGroup.Item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,21 @@
.items-column {
position: relative;
z-index: 1;
width: 230px;
width: 100%;
height: 240px;
overflow-x: hidden;
overflow-y: auto;
border: solid 1px $dv-border-color;
border-radius: 6px;

@media screen and (min-width: 768px) {
width: 230px;
}

@media screen and (min-width: 1280px) {
width: 275px;
}

&::-webkit-scrollbar {
width: 8px;
}
Expand Down Expand Up @@ -78,17 +86,22 @@
border-radius: 4px;
cursor: grab;

&:hover {
&:hover:not(.disabled) {
background-color: $dv-secondary-color;
}

&:active {
&:active:not(.disabled) {
cursor: grabbing;
}

&.disabled {
opacity: 0.5;
pointer-events: none;
}
}

&:hover,
&:focus-visible {
&:hover:not(.disabled),
&:focus-visible:not(.disabled) {
color: $dv-text-color;
background-color: color.adjust($dv-secondary-color, $alpha: -0.7);
}
Expand All @@ -108,6 +121,7 @@
position: sticky;
top: 0;
left: 0;
z-index: 1;
margin: 0;
padding: 0.35rem 0.5rem;
font-weight: bold;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,20 @@ export interface TransferListProps {
onChange?: (selected: TransferListItem[]) => void
leftLabel?: string
rightLabel?: string
disabled?: boolean
}

export const TransferList = ({
availableItems,
defaultSelected = [],
onChange,
leftLabel,
rightLabel
rightLabel,
disabled = false
}: TransferListProps) => {
const [checked, setChecked] = useState<TransferListItem[]>([])
const [left, setLeft] = useState<TransferListItem[]>(not(availableItems, defaultSelected))
const [right, setRight] = useState<TransferListItem[]>(
intersection(availableItems, defaultSelected)
)
const [right, setRight] = useState<TransferListItem[]>(defaultSelected)

const leftChecked = intersection(checked, left)
const rightChecked = intersection(checked, right)
Expand All @@ -66,22 +66,24 @@ export const TransferList = ({
setLeft([])
}

const handleCheckedRight = () => {
const handleCheckedToRight = () => {
setRight(right.concat(leftChecked))
onChange && onChange(right.concat(leftChecked))
setLeft(not(left, leftChecked))
setChecked(not(checked, leftChecked))
}

const handleCheckedLeft = () => {
setLeft(left.concat(rightChecked.filter((item) => availableItems.includes(item))))
const handleCheckedToLeft = () => {
setLeft(
left.concat(rightChecked.filter((item) => availableItems.find((a) => a.value === item.value)))
)
setRight(not(right, rightChecked))
onChange && onChange(not(right, rightChecked))
setChecked(not(checked, rightChecked))
}

const handleAllLeft = () => {
setLeft(left.concat(right.filter((item) => availableItems.includes(item))))
setLeft(left.concat(right.filter((item) => availableItems.find((a) => a.value === item.value))))
setRight([])
onChange && onChange([])
}
Expand All @@ -94,47 +96,57 @@ export const TransferList = ({

return (
<div className={styles['transfer-list']}>
<div className={styles['items-column']} tabIndex={0}>
<div className={styles['items-column']} tabIndex={disabled ? -1 : 0}>
{leftLabel && <p className={styles['column-label']}>{leftLabel}</p>}
<ItemsList items={left} side="left" checked={checked} onToggle={handleToggle} />
<ItemsList
items={left}
side="left"
checked={checked}
onToggle={handleToggle}
disabled={disabled}
/>
</div>
<div className={styles['middle-column']} data-testid="actions-column">
<Button
size="sm"
type="button"
onClick={handleAllRight}
disabled={left.length === 0}
disabled={left.length === 0 || disabled}
icon={<ChevronDoubleRight />}
aria-label="move all right"
className={styles['transfer-button']}
/>

<Button
size="sm"
onClick={handleCheckedRight}
disabled={leftChecked.length === 0}
type="button"
onClick={handleCheckedToRight}
disabled={leftChecked.length === 0 || disabled}
icon={<ChevronRight />}
aria-label="move selected to right"
className={styles['transfer-button']}
/>

<Button
size="sm"
onClick={handleCheckedLeft}
disabled={rightChecked.length === 0}
type="button"
onClick={handleCheckedToLeft}
disabled={rightChecked.length === 0 || disabled}
icon={<ChevronLeft />}
aria-label="move selected to left"
className={styles['transfer-button']}
/>
<Button
size="sm"
type="button"
onClick={handleAllLeft}
disabled={right.length === 0}
disabled={right.length === 0 || disabled}
icon={<ChevronDoubleLeft />}
aria-label="move all left"
className={styles['transfer-button']}
/>
</div>
<div className={styles['items-column']} tabIndex={0}>
<div className={styles['items-column']} tabIndex={disabled ? -1 : 0}>
{rightLabel && <p className={styles['column-label']}>{rightLabel}</p>}
<ItemsList
items={right}
Expand All @@ -144,6 +156,7 @@ export const TransferList = ({
rightItems={right}
setRight={setRight}
onChange={onChange}
disabled={disabled}
/>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/design-system/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ export { SelectAdvanced } from './components/select-advanced/SelectAdvanced'
export { Card } from './components/card/Card'
export { ProgressBar } from './components/progress-bar/ProgressBar'
export { Stack } from './components/stack/Stack'
export { TransferList } from './components/transfer-list/TransferList'
export { TransferList, type TransferListItem } from './components/transfer-list/TransferList'
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,7 @@ const WithChangingAvailableItemsComponent = () => {
</div>
)
}

export const Disabled: Story = {
render: () => <TransferList availableItems={aToEitems} disabled />
}
16 changes: 7 additions & 9 deletions public/locales/en/createCollection.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
},
"description": {
"label": "Description",
"description": "A summary describing the purpose, nature or scope of this collection."
"description": "A summary describing the purpose, nature or scope of this collection.",
"subLabel": "This field supports only certain <htmlTooltip>HTML tags</htmlTooltip>.",
"htmlAllowedTags": "<a>, <b>, <blockquote>, <br>, <code>, <del>, <dd>, <dl>, <dt>, <em>, <hr>, <h1>-<h3>, <i>, <img>, <kbd>, <li>, <ol>, <p>, <pre>, <s>, <sup>, <sub>, <strong>, <strike>, <u>, <ul>"
},
"contacts": {
"label": "Email",
Expand All @@ -46,14 +48,8 @@
},
"metadataFields": {
"sectionLabel": "Metadata Fields",
"helperText": "Choose the metadata fields to use in dataset templates and when adding a dataset to this dataverse.",
"helperText": "Choose the metadata fields to use in dataset templates and when adding a dataset to this collection.",
"useMetadataFieldsFrom": "Use metadata fields from",
"citationMetadata": "Citation Metadata (Required)",
"geospatialMetadata": "Geospatial Metadata",
"socialScienceMetadata": "Social Science and Humanities Metadata",
"astrophysicsMetadata": "Astronomy and Astrophysics Metadata",
"biomedicalMetadata": "Life Sciences Metadata",
"journalMetadata": "Journal Metadata",
"inputLevelsTable": {
"hideTableAriaLabel": "Hide input levels table",
"requiredByDataverse": "Required by Dataverse",
Expand All @@ -65,7 +61,9 @@
},
"browseSearchFacets": {
"label": "Browse/Search Facets",
"helperText": "Choose the metadata fields to use as facets for browsing datasets and dataverses in this dataverse."
"helperText": "Choose and order the metadata fields to use as facets when browsing this collection.",
"useBrowseSearchFacetsFrom": "Use browse/search facets from",
"selectedFacets": "Selected"
}
},
"confirmResetModal": {
Expand Down
5 changes: 5 additions & 0 deletions src/collection/domain/models/CollectionFacet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface CollectionFacet {
id: number
name: string
displayName: string
}
2 changes: 2 additions & 0 deletions src/collection/domain/repositories/CollectionRepository.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Collection } from '../models/Collection'
import { CollectionFacet } from '../models/CollectionFacet'
import { CollectionUserPermissions } from '../models/CollectionUserPermissions'
import { CollectionDTO } from '../useCases/DTOs/CollectionDTO'

export interface CollectionRepository {
getById: (id: string) => Promise<Collection>
create(collection: CollectionDTO, hostCollection?: string): Promise<number>
getFacets(collectionIdOrAlias: number | string): Promise<CollectionFacet[]>
getUserPermissions(collectionIdOrAlias: number | string): Promise<CollectionUserPermissions>
}
5 changes: 2 additions & 3 deletions src/collection/domain/useCases/DTOs/CollectionDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ export const collectionTypeOptions = {
value: CollectionType.DEPARTMENT
}
} as const

// 👇 To be defined, at the moment the SPA only supports file uploading through direct upload (S3), so we are disabling the storage selector
export const collectionStorageOptions = {
LOCAL_DEFAULT: 'Local (Default)',
LOCAL: 'Local'
S3: 'S3'
} as const

export type CollectionStorage =
Expand Down
Loading
Loading