-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
select visible columns in settings side panel (#614)
feat(explorer): select visible columns in settings side panel Co-authored-by: Jules HABLOT <[email protected]>
- Loading branch information
Showing
11 changed files
with
314 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
libs/ui/src/components/Explorer/edit-settings/ColumnItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import {KitTypography} from 'aristid-ds'; | ||
import {FunctionComponent, ReactNode} from 'react'; | ||
import {FaChevronRight, FaEye, FaEyeSlash, FaGripLines} from 'react-icons/fa'; | ||
import styled from 'styled-components'; | ||
|
||
const StyledValue = styled(KitTypography.Text)` | ||
color: var(--general-utilities-disabled); | ||
`; | ||
|
||
const StyledConfigurationItem = styled.li` | ||
list-style: none; | ||
color: var(--general-utilities-text-primary); | ||
display: flex; | ||
width: 100%; | ||
height: 40px; | ||
padding: 0 calc(var(--general-spacing-xs) * 1px); | ||
align-items: center; | ||
gap: calc(var(--general-spacing-xs) * 1px); | ||
border-radius: calc(var(--general-spacing-xs) * 1px); | ||
text-align: left; | ||
&:first-child { | ||
margin-top: calc(var(--general-spacing-xs) * 1px); | ||
} | ||
&:hover { | ||
background: var(--general-utilities-main-light); | ||
${StyledValue} { | ||
color: var(--general-utilities-text-primary); | ||
} | ||
} | ||
.title { | ||
flex: 1 1 auto; | ||
} | ||
> svg { | ||
flex: 0 0 calc(var(--general-spacing-s) * 1px); | ||
} | ||
> button { | ||
border: none; | ||
background: transparent; | ||
padding: 0; | ||
&:not([disabled]) { | ||
cursor: pointer; | ||
} | ||
} | ||
`; | ||
|
||
const StyledFaEye = styled(FaEye)` | ||
color: currentColor; | ||
`; | ||
|
||
const StyledEyeSlash = styled(FaEyeSlash)` | ||
color: var(--general-utilities-disabled); | ||
`; | ||
|
||
const StyledEmptyIcon = styled.div` | ||
width: calc(var(--general-spacing-s) * 1px); | ||
`; | ||
|
||
interface IColumnItemProps { | ||
dragHandler?: ReactNode; | ||
visible: boolean; | ||
title: string; | ||
onVisibilityClick?: () => void; | ||
disabled?: boolean; | ||
value?: string; | ||
} | ||
|
||
export const ColumnItem: FunctionComponent<IColumnItemProps> = ({ | ||
dragHandler, | ||
title, | ||
disabled, | ||
visible, | ||
onVisibilityClick | ||
}) => ( | ||
<StyledConfigurationItem className={disabled ? 'disabled' : ''}> | ||
{dragHandler || <StyledEmptyIcon />} | ||
<KitTypography.Text size="fontSize5" ellipsis className="title"> | ||
{title} | ||
</KitTypography.Text> | ||
<button disabled={disabled} onClick={onVisibilityClick}> | ||
{visible ? <StyledFaEye /> : <StyledEyeSlash />} | ||
</button> | ||
</StyledConfigurationItem> | ||
); |
58 changes: 52 additions & 6 deletions
58
libs/ui/src/components/Explorer/edit-settings/DisplayMode.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,57 @@ | ||
// Copyright LEAV Solutions 2017 until 2023/11/05, Copyright Aristid from 2023/11/06 | ||
// This file is released under LGPL V3 | ||
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt | ||
import {useSharedTranslation} from '_ui/hooks/useSharedTranslation'; | ||
import {FunctionComponent} from 'react'; | ||
import {KitRadio, KitSpace, KitTag} from 'aristid-ds'; | ||
import {RadioChangeEvent} from 'aristid-ds/dist/Kit/DataEntry/Radio'; | ||
import {FunctionComponent, useState} from 'react'; | ||
import styled from 'styled-components'; | ||
import {DisplayModeTable} from './DisplayModeTable'; | ||
|
||
export const DisplayMode: FunctionComponent = () => { | ||
const StyledWrapperDiv = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
gap: calc(var(--general-spacing-l) * 1px); | ||
.ant-radio-wrapper { | ||
padding: calc(var(--general-spacing-xs) * 1px); | ||
} | ||
`; | ||
|
||
interface IDisplayModeProps { | ||
library: string; | ||
} | ||
|
||
export const DisplayMode: FunctionComponent<IDisplayModeProps> = ({library}) => { | ||
const {t} = useSharedTranslation(); | ||
const [currentDisplayMode, setCurrentDisplayMode] = useState('table'); | ||
|
||
const _handleDisplayModeChange = (event: RadioChangeEvent) => { | ||
setCurrentDisplayMode(event.target.value); | ||
}; | ||
|
||
const comingSoonTag = <KitTag type="secondary" idCardProps={{description: String(t('explorer.coming-soon'))}} />; | ||
|
||
return <div>TODO</div>; | ||
return ( | ||
<StyledWrapperDiv> | ||
<KitRadio.Group value={currentDisplayMode} onChange={_handleDisplayModeChange}> | ||
<KitSpace direction="vertical" size={0}> | ||
<KitRadio value="list" disabled> | ||
<KitSpace> | ||
{t('explorer.display-mode-list')} {comingSoonTag} | ||
</KitSpace> | ||
</KitRadio> | ||
<KitRadio value="table">{t('explorer.display-mode-table')}</KitRadio> | ||
<KitRadio value="mosaic" disabled> | ||
<KitSpace> | ||
{t('explorer.display-mode-mosaic')} {comingSoonTag} | ||
</KitSpace> | ||
</KitRadio> | ||
<KitRadio value="planning" disabled> | ||
<KitSpace> | ||
{t('explorer.display-mode-planning')} {comingSoonTag} | ||
</KitSpace> | ||
</KitRadio> | ||
</KitSpace> | ||
</KitRadio.Group> | ||
{currentDisplayMode === 'table' && <DisplayModeTable library={library} />} | ||
</StyledWrapperDiv> | ||
); | ||
}; |
115 changes: 115 additions & 0 deletions
115
libs/ui/src/components/Explorer/edit-settings/DisplayModeTable.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import {useDebouncedValue} from '_ui/hooks/useDebouncedValue/useDebouncedValue'; | ||
import {useSharedTranslation} from '_ui/hooks/useSharedTranslation'; | ||
import {KitInput, KitTypography} from 'aristid-ds'; | ||
import {ChangeEvent, FunctionComponent, useMemo, useState} from 'react'; | ||
import styled from 'styled-components'; | ||
import {FaGripLines} from 'react-icons/fa'; | ||
import {ColumnItem} from './ColumnItem'; | ||
import {useGetLibraryColumns} from './useGetLibraryColumns'; | ||
|
||
const StyledList = styled.ul` | ||
padding: 0; | ||
margin: 0; | ||
list-style: none; | ||
color: var(--general-utilities-text-primary); | ||
`; | ||
|
||
const StyledDivider = styled.hr` | ||
display: block; | ||
height: 1px; | ||
border: 0; | ||
border-top: 1px solid var(--general-utilities-main-light); | ||
margin: 0 calc(var(--general-spacing-s) * 1px); | ||
padding: 0; | ||
`; | ||
|
||
interface IDisplayModeTableProps { | ||
library: string; | ||
} | ||
|
||
export const DisplayModeTable: FunctionComponent<IDisplayModeTableProps> = ({library}) => { | ||
const {t} = useSharedTranslation(); | ||
// TODO Where to stock visible columns list | ||
// TODO when are changes saved (and thus, when is the table updated) ? | ||
const [orderedVisibleColumns, setOrderedVisibleColumns] = useState<string[]>([]); | ||
const [searchInput, setSearchInput] = useState(''); | ||
const debouncedSearchInput = useDebouncedValue(searchInput, 300); | ||
|
||
const {attributeDetailsById} = useGetLibraryColumns(library); | ||
|
||
const searchFilteredColumns = useMemo(() => { | ||
const columnIds = Object.keys(attributeDetailsById); | ||
if (columnIds.length === 0) { | ||
return {}; | ||
} | ||
if (searchInput === '') { | ||
return attributeDetailsById; | ||
} | ||
|
||
return columnIds.reduce((acc, columnId) => { | ||
if (attributeDetailsById[columnId].label.includes(searchInput) || columnId.includes(searchInput)) { | ||
acc[columnId] = attributeDetailsById[columnId]; | ||
} | ||
return acc; | ||
}, {}); | ||
}, [debouncedSearchInput, attributeDetailsById]); | ||
const searchFilteredColumnsIds = Object.keys(searchFilteredColumns); | ||
|
||
const _onSearchChanged = (event: ChangeEvent<HTMLInputElement>) => { | ||
const shouldIgnoreInputChange = event.target.value.length < 3 && searchInput.length < 3; | ||
if (shouldIgnoreInputChange) { | ||
return; | ||
} | ||
setSearchInput(() => { | ||
if (event.target.value.length > 2) { | ||
return event.target.value; | ||
} | ||
return ''; | ||
}); | ||
}; | ||
|
||
const _toggleColumnVisibility = (columnId: string) => () => { | ||
setOrderedVisibleColumns(() => { | ||
if (orderedVisibleColumns.includes(columnId)) { | ||
return orderedVisibleColumns.filter(id => id !== columnId); | ||
} | ||
return [...orderedVisibleColumns, columnId]; | ||
}); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<KitTypography.Title level="h4">{t('items_list.columns')}</KitTypography.Title> | ||
<KitInput placeholder={String(t('global.search'))} onChange={_onSearchChanged} allowClear></KitInput> | ||
<div> | ||
<StyledList> | ||
<ColumnItem title={t('record_edition.whoAmI')} visible={false} disabled /> | ||
{orderedVisibleColumns | ||
.filter(columnId => searchFilteredColumnsIds[columnId]) | ||
.map(columnId => ( | ||
<ColumnItem | ||
key={columnId} | ||
title={attributeDetailsById[columnId].label} | ||
visible | ||
onVisibilityClick={_toggleColumnVisibility(columnId)} | ||
dragHandler={<FaGripLines />} | ||
/> | ||
))} | ||
</StyledList> | ||
<StyledDivider /> | ||
<StyledList> | ||
{searchFilteredColumnsIds | ||
.filter(columnId => !orderedVisibleColumns.includes(columnId)) | ||
.map(columnId => ( | ||
<ColumnItem | ||
key={attributeDetailsById[columnId].id} | ||
visible={false} | ||
title={attributeDetailsById[columnId].label} | ||
onVisibilityClick={_toggleColumnVisibility(columnId)} | ||
/> | ||
))} | ||
</StyledList> | ||
</div> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
libs/ui/src/components/Explorer/edit-settings/useGetLibraryColumns.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Copyright LEAV Solutions 2017 until 2023/11/05, Copyright Aristid from 2023/11/06 | ||
// This file is released under LGPL V3 | ||
// License text available at https://www.gnu.org/licenses/lgpl-3.0.txt | ||
import {AttributeDetailsFragment, GetAttributesByLibQuery, useGetAttributesByLibQuery} from '../../../_gqlTypes'; | ||
import {useLang} from '../../../hooks'; | ||
import {localizedTranslation} from '@leav/utils'; | ||
|
||
interface IColumnsById { | ||
[attributeId: string]: AttributeDetailsFragment; | ||
} | ||
|
||
const _mapping = (data: GetAttributesByLibQuery | undefined, availableLangs: string[]): IColumnsById => | ||
data?.attributes?.list.reduce((acc, attribute) => { | ||
acc[attribute.id] = { | ||
...attribute, | ||
label: localizedTranslation(attribute.label, availableLangs) | ||
}; | ||
return acc; | ||
}, {}) ?? {}; | ||
|
||
export const useGetLibraryColumns = (library: string) => { | ||
const {lang: availableLangs} = useLang(); | ||
const {data, error, loading} = useGetAttributesByLibQuery({ | ||
variables: { | ||
library | ||
} | ||
}); | ||
|
||
const attributeDetailsById = _mapping(data, availableLangs); | ||
|
||
return {attributeDetailsById, error, loading}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.