Skip to content

Commit

Permalink
feat: allow section customisation
Browse files Browse the repository at this point in the history
  • Loading branch information
acezard committed May 29, 2024
1 parent 049e727 commit 14ebfd3
Show file tree
Hide file tree
Showing 10 changed files with 307 additions and 119 deletions.
127 changes: 107 additions & 20 deletions src/components/Sections/SectionActions.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,122 @@
import React from 'react'

import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem'
import FileIcon from 'cozy-ui/transpiled/react/Icons/File'
import Icon from 'cozy-ui/transpiled/react/Icon'
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
import { makeActions } from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
import { Action, DisplayMode } from 'components/Sections/SectionsTypes'
import Icon from 'cozy-ui/transpiled/react/Icon'
import ListMin from 'cozy-ui/transpiled/react/Icons/ListMin'
import MosaicMin from 'cozy-ui/transpiled/react/Icons/MosaicMin'
import RadioChecked from 'cozy-ui/transpiled/react/Icons/RadioChecked'
import RadioUnchecked from 'cozy-ui/transpiled/react/Icons/RadioUnchecked'
import Switch from 'cozy-ui/transpiled/react/Switch'
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
import {
Action,
divider,
makeActions
} from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
import { useSettings } from 'cozy-client'

import {
DisplayMode,
GroupMode,
Section,
SectionViewProps
} from 'components/Sections/SectionsTypes'
import {
computeDisplayMode,
handleSectionAction
} from 'components/Sections/utils'

const isDisplayMode = (
value: DisplayMode | GroupMode
): value is DisplayMode => {
return Object.values(DisplayMode).includes(value as DisplayMode)
}

// This feature is disabled in this pull request
const StateSwitch = (): JSX.Element => {
return <Switch className="u-w-auto u-pr-0" disabled />
}

const createSectionAction = (primaryText: DisplayMode): (() => Action) => {
return () => ({
name: `sectionAction_${primaryText}`,
action: (_doc, opts): void => {
opts.handleAction(primaryText)
},
Component: React.forwardRef(function SectionActionComponent(props, ref) {
return (
<ActionsMenuItem {...props} ref={ref}>
<ListItemIcon>
<Icon icon={FileIcon} />
</ListItemIcon>
<ListItemText primary={primaryText} />
</ActionsMenuItem>
const createSectionAction = (
actionLabel: DisplayMode | GroupMode
): (() => Action) => {
if (isDisplayMode(actionLabel)) {
return () => ({
name: `sectionAction_${actionLabel}`,
Component: React.forwardRef<{ docs?: Section[] }>(
function SectionActionComponent(props: { docs?: Section[] }, ref) {
const { isMobile } = useBreakpoints()
const { values, save } = useSettings('home', ['shortcutsLayout'])
const section = props.docs?.[0] as SectionViewProps['section']
const currentDisplayMode = computeDisplayMode(isMobile, section)
const handleClick = (): void =>
handleSectionAction(section, isMobile, actionLabel, values, save)
const { t } = useI18n()
const isActive = actionLabel === currentDisplayMode

return (
<ActionsMenuItem
{...props}
ref={ref}
onClick={handleClick}
className="u-miw-auto u-w-auto"
>
<ListItemIcon>
<Icon
icon={
actionLabel === DisplayMode.COMPACT ? MosaicMin : ListMin
}
/>
</ListItemIcon>

<ListItemText
className="u-mr-half"
primary={t(`sections.label_${actionLabel}`)}
/>

<Icon
icon={isActive ? RadioChecked : RadioUnchecked}
color={`var(--${isActive ? 'primary' : 'borderMain'}Color)`}
/>
</ActionsMenuItem>
)
}
)
})
})
} else {
return () => ({
name: `sectionAction_${actionLabel}`,
Component: React.forwardRef(function SectionActionComponent(props, ref) {
const { t } = useI18n()

return (
<ActionsMenuItem
{...props}
ref={ref}
disabled
className="u-miw-auto u-w-auto"
>
<ListItemText
className="u-mr-half"
primary={t(`sections.label_grouped`)}
/>

<StateSwitch />
</ActionsMenuItem>
)
})
})
}
}

const actionArray = [
createSectionAction(DisplayMode.COMPACT),
createSectionAction(DisplayMode.DETAILED)
createSectionAction(DisplayMode.DETAILED),
divider,
createSectionAction(GroupMode.DEFAULT)
]

export const actions = makeActions(actionArray)
74 changes: 45 additions & 29 deletions src/components/Sections/SectionHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,66 @@
import React from 'react'
import cx from 'classnames'

import ActionsMenu from 'cozy-ui/transpiled/react/ActionsMenu'
import Button from 'cozy-ui/transpiled/react/Buttons'
import CozyTheme from 'cozy-ui/transpiled/react/providers/CozyTheme'
import Divider from 'cozy-ui/transpiled/react/MuiCozyTheme/Divider'
import DotsIcon from 'cozy-ui/transpiled/react/Icons/Dots'
import Icon from 'cozy-ui/transpiled/react/Icon'
import flag from 'cozy-flags'
import { makeStyles } from 'cozy-ui/transpiled/react/styles'

import { actions } from 'components/Sections/SectionActions'
import { SectionHeaderProps } from 'components/Sections/SectionsTypes'
import { actions } from 'components/Sections/SectionActions'

const useStyles = makeStyles(() => ({
headerWrapper: {
display: 'flex',
justifyContent: 'space-between',
width: '100%'
}
}))

export const SectionHeader = ({
name,
section,
anchorRef,
toggleMenu,
menuState,
handleAction
}: SectionHeaderProps): JSX.Element => (
<>
<Divider className="u-mv-0" variant="subtitle2">
{name}
</Divider>
menuState
}: SectionHeaderProps): JSX.Element => {
const classes = useStyles()

{flag('home.detailed_section.show_more-dev') && (
<>
<Button
label={<Icon icon={DotsIcon} />}
ref={anchorRef}
onClick={toggleMenu}
/>
return (
<>
<div className={cx([classes.headerWrapper])}>
<Divider className="u-mv-0 u-flex-grow-1" variant="subtitle2">
{section.name}
</Divider>

{flag('home.detailed-sections.show-more-dev') && (
<Button
className="u-p-1"
label={<Icon icon={DotsIcon} />}
onClick={toggleMenu}
ref={anchorRef}
variant="text"
/>
)}
</div>

<CozyTheme variant="normal">
<ActionsMenu
ref={anchorRef}
open={menuState}
actions={actions}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left'
horizontal: 'right',
vertical: 'bottom'
}}
docs={[name]}
actions={actions}
autoClose
docs={[section]}
onClose={toggleMenu}
componentsProps={{
actionsItems: { actionOptions: { handleAction } }
}}
open={menuState}
ref={anchorRef}
/>
</>
)}
</>
)
</CozyTheme>
</>
)
}
23 changes: 6 additions & 17 deletions src/components/Sections/SectionView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,36 @@ import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'

import {
DisplayMode,
Section,
SectionViewProps
} from 'components/Sections/SectionsTypes'
import { SectionHeader } from 'components/Sections/SectionHeader'
import { ShortcutLink } from 'components/ShortcutLink'

const computeDisplayMode = (
isMobile: boolean,
section: Section
): DisplayMode => {
const layout = section.layout[isMobile ? 'mobile' : 'desktop']
return layout.detailedLines ? DisplayMode.DETAILED : DisplayMode.COMPACT
}
import { computeDisplayMode } from 'components/Sections/utils'

export const SectionView = ({ section }: SectionViewProps): JSX.Element => {
const [menuState, setMenuState] = useState(false)
const anchorRef = React.useRef(null)
const { isMobile } = useBreakpoints()
const toggleMenu = (): void => setMenuState(!menuState)
const display = computeDisplayMode(isMobile, section)
const handleAction = (): void => {
// noop for now, will be needed for switching display user side
}
const currentDisplayMode = computeDisplayMode(isMobile, section)

return (
<div className="shortcuts-list-wrapper u-m-auto u-w-100">
<SectionHeader
name={section.name}
section={section}
anchorRef={anchorRef}
toggleMenu={toggleMenu}
menuState={menuState}
handleAction={handleAction}
/>

<div
className={cx(
'shortcuts-list u-w-100 u-mv-3 u-mv-2-t u-mh-auto u-flex-justify-center',
{ detailed: display === DisplayMode.DETAILED }
{ detailed: Boolean(currentDisplayMode === DisplayMode.DETAILED) }
)}
>
{section.items.map((item, index) => (
<ShortcutLink key={index} file={item} display={display} />
<ShortcutLink key={index} file={item} display={currentDisplayMode} />
))}
</div>
</div>
Expand Down
13 changes: 9 additions & 4 deletions src/components/Sections/SectionsTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DirectoryDataArray, FileData } from 'components/Shortcuts/types'
import React from 'react'

export interface DeviceSettings {
detailedLines: boolean
Expand Down Expand Up @@ -45,18 +46,22 @@ export enum DisplayMode {
DETAILED = 'detailed'
}

type HandleActionCallback = (action: DisplayMode) => void
export enum GroupMode {
DEFAULT = 'default',
GROUPED = 'grouped'
}

export type HandleActionCallback = (action: DisplayMode | GroupMode) => void

export type Action = {
name: string
action: (doc: Section, opts: { handleAction: HandleActionCallback }) => void
action: (doc: Section[], opts: { handleAction: HandleActionCallback }) => void
Component: React.FC
}

export interface SectionHeaderProps {
name: string
section: Section
anchorRef?: React.RefObject<HTMLButtonElement>
toggleMenu: () => void
menuState: boolean
handleAction: (action: DisplayMode) => void
}
Loading

0 comments on commit 14ebfd3

Please sign in to comment.