Skip to content

Commit

Permalink
feat: Replace Settings menu by ActionsMenu / ActionsItems
Browse files Browse the repository at this point in the history
  • Loading branch information
JF-Cozy committed Aug 12, 2024
1 parent 8ca419b commit d8a5fcd
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 293 deletions.
11 changes: 9 additions & 2 deletions src/components/Drawer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { connect } from 'react-redux'
import Hammer from 'hammerjs'
import PropTypes from 'prop-types'

import Divider from 'cozy-ui/transpiled/react/Divider'
import List from 'cozy-ui/transpiled/react/List'
import Paper from 'cozy-ui/transpiled/react/Paper'
import AppsContent from 'components/Apps/AppsContent'
import SettingsContent from 'components/Settings/SettingsContent'
import { fetchSettingsData } from 'lib/reducers'
Expand Down Expand Up @@ -166,9 +169,13 @@ class Drawer extends Component {
isInvertedTheme={isInvertedTheme}
/>
</nav>
<hr className="coz-sep-flex" />
<Divider />
<nav className="coz-drawer--settings">
<SettingsContent isDrawer onLogOut={onLogOut} />
<Paper elevation={0} square>
<List>
<SettingsContent isDrawer onLogOut={onLogOut} />
</List>
</Paper>
</nav>
</aside>
</div>
Expand Down
272 changes: 60 additions & 212 deletions src/components/Settings/SettingsContent.jsx
Original file line number Diff line number Diff line change
@@ -1,226 +1,74 @@
import React, { useCallback } from 'react'
import React from 'react'
import PropTypes from 'prop-types'
import flag from 'cozy-flags'

import { isFlagshipApp } from 'cozy-device-helper'
import { useClient, useInstanceInfo, generateWebLink } from 'cozy-client'
import { useInstanceInfo } from 'cozy-client'
import {
hasAnOffer,
shouldDisplayOffers,
buildPremiumLink
} from 'cozy-client/dist/models/instance'
import { useWebviewIntent } from 'cozy-intent'
import Icon from 'cozy-ui/transpiled/react/Icon'
import OpenwithIcon from 'cozy-ui/transpiled/react/Icons/Openwith'
import PeopleIcon from 'cozy-ui/transpiled/react/Icons/People'
import PaletteIcon from 'cozy-ui/transpiled/react/Icons/Palette'
import GraphCircleIcon from 'cozy-ui/transpiled/react/Icons/GraphCircle'
import CozyCircleIcon from 'cozy-ui/transpiled/react/Icons/CozyCircle'
import HandIcon from 'cozy-ui/transpiled/react/Icons/Hand'
import DevicesIcon from 'cozy-ui/transpiled/react/Icons/Devices'
import GlobeIcon from 'cozy-ui/transpiled/react/Icons/Globe'
import LogoutIcon from 'cozy-ui/transpiled/react/Icons/Logout'
import HelpIcon from 'cozy-ui/transpiled/react/Icons/Help'
import EmailIcon from 'cozy-ui/transpiled/react/Icons/Email'
makeActions,
divider
} from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
import ActionsMenu from 'cozy-ui/transpiled/react/ActionsMenu'
import ActionsItems from 'cozy-ui/transpiled/react/ActionsMenu/ActionsItems'

import { getSettingsLink } from 'components/Settings/helper'
import StorageData from 'components/Settings/StorageData'
import {
profile,
appearance,
plans,
storage,
permissions,
connectedDevices,
connections,
help,
contact,
logout
} from 'components/Settings/actions'
import useI18n from 'components/useI18n'

const MenuIcon = ({ icon }) => {
return <Icon className="u-mr-1" color="var(--iconTextColor)" icon={icon} />
}

const ExternalLinkIcon = () => {
return (
<Icon
className="coz-nav-settings-item-btn-external-icon"
color="var(--iconTextColor)"
icon={OpenwithIcon}
/>
)
}

const NavGroup = ({ children }) => {
return <ul className="coz-nav-group">{children}</ul>
}

const NavItem = ({ children }) => {
return <li className="coz-nav-settings-item">{children}</li>
}

const SettingsContent = ({ instanceInfo, onLogOut, isDrawer }) => {
const SettingsContent = ({
anchorRef,
instanceInfo,
onLogOut,
isDrawer,
onClose
}) => {
const { t } = useI18n()
const client = useClient()
const webviewIntent = useWebviewIntent()
const hasSubscription = flag('settings.subscription')

const shouldDisplayViewOfferButton =
shouldDisplayOffers(instanceInfo) || hasAnOffer(instanceInfo)

const managerUrlPremiumLink =
hasSubscription && client
? generateWebLink({
cozyUrl: client.getStackClient().uri,
hash: '/subscription',
pathname: '/',
slug: 'settings',
subDomainType: client.getInstanceOptions().subdomain
})
: buildPremiumLink(instanceInfo)

const logOut = useCallback(async () => {
await client.logout()

return isFlagshipApp() && webviewIntent
? webviewIntent.call('logout')
: window.location.reload()
}, [client, webviewIntent])

const handleLogout = async () => {
if (onLogOut && typeof onLogOut === 'function') {
const res = onLogOut()
if (res instanceof Promise) {
await res
}
} else {
logOut()
const actions = makeActions(
[
profile,
appearance,
plans,
storage,
permissions,
divider,
connectedDevices,
connections,
divider,
help,
contact,
logout
],
{
t,
instanceInfo,
onLogOut
}
}

return (
<div className="coz-nav-pop-content">
{isDrawer && <hr />}
)

<NavGroup>
<NavItem>
<a
role="menuitem"
href={getSettingsLink({ client, hash: 'profile' })}
target="_self"
title={t('profile')}
>
<MenuIcon icon={PeopleIcon} />
{t('profile')}
</a>
</NavItem>
{flag('ui.darkmode.enabled') && (
<NavItem>
<a
role="menuitem"
href={getSettingsLink({ client, hash: 'appearance' })}
target="_self"
title={t('appearance')}
>
<MenuIcon icon={PaletteIcon} />
{t('appearance')}
</a>
</NavItem>
)}
{shouldDisplayViewOfferButton && (
<NavItem>
<a
role="menuitem"
href={managerUrlPremiumLink}
target="_self"
title={t('plans')}
>
<MenuIcon icon={CozyCircleIcon} />
{t('plans')}
{!flag('settings.subscription') && <ExternalLinkIcon />}
</a>
</NavItem>
)}
<NavItem>
<a
role="menuitem"
target="_self"
title={t('storage')}
href={getSettingsLink({ client, hash: 'storage' })}
>
<MenuIcon icon={GraphCircleIcon} />
<span>
{t('storage')}
<StorageData />
</span>
</a>
</NavItem>
</NavGroup>
<NavGroup>
{flag('settings.permissions-dashboard') && (
<NavItem>
<a
role="menuitem"
href={getSettingsLink({ client, hash: 'permissions/slug' })}
target="_self"
title={t('permissions')}
>
<MenuIcon icon={HandIcon} />
{t('permissions')}
</a>
</NavItem>
)}
<NavItem>
<a
role="menuitem"
href={getSettingsLink({ client, hash: 'connectedDevices' })}
target="_self"
title={t('connectedDevices')}
>
<MenuIcon icon={DevicesIcon} />
{t('connectedDevices')}
</a>
</NavItem>
<NavItem>
<a
role="menuitem"
href={getSettingsLink({ client, hash: 'sessions' })}
target="_self"
title={t('connections')}
>
<MenuIcon icon={GlobeIcon} />
{t('connections')}
</a>
</NavItem>
</NavGroup>
<NavGroup>
<NavItem>
<a
role="menuitem"
target="_blank"
rel="noopener noreferrer"
href="https://support.cozy.io/"
title={t('help')}
>
<MenuIcon icon={HelpIcon} />
{t('help')}
<ExternalLinkIcon />
</a>
</NavItem>
<NavItem>
<a
role="menuitem"
href={getSettingsLink({ client, hash: 'support' })}
target="_self"
title={t('contact')}
>
<MenuIcon icon={EmailIcon} />
{t('contact')}
</a>
</NavItem>
if (isDrawer) return <ActionsItems actions={actions} />

<NavItem>
<button
type="button"
role="menuitem"
onClick={handleLogout}
title={t('logout')}
>
<MenuIcon icon={LogoutIcon} /> {t('logout')}
</button>
</NavItem>
</NavGroup>
</div>
return (
<ActionsMenu
ref={anchorRef}
open={true}
docs={[]}
actions={actions}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
autoClose
onClose={onClose}
/>
)
}

Expand Down
36 changes: 16 additions & 20 deletions src/components/Settings/StorageData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,36 @@ import React from 'react'

import { useInstanceInfo } from 'cozy-client'
import { makeDiskInfos } from 'cozy-client/dist/models/instance'
import { LinearProgress } from 'cozy-ui/transpiled/react/Progress'

import useI18n from 'components/useI18n'

const StorageData = () => {
const { t } = useI18n()
const { isLoaded, ...instanceInfo } = useInstanceInfo()
const { isLoaded, diskUsage } = useInstanceInfo()

if (!isLoaded) return null

// we used this default quota set in getStorageData, we just reuse it here
const storageData = makeDiskInfos(
instanceInfo.diskUsage.data.attributes.used,
instanceInfo.diskUsage.data.attributes.quota ||
Math.max(
10 ** 12,
10 * parseInt(instanceInfo.diskUsage.data.attributes.used, 10)
)
diskUsage.data.attributes.used,
diskUsage.data.attributes.quota ||
Math.max(10 ** 12, 10 * parseInt(diskUsage.data.attributes.used, 10))
)

return (
<div className="coz-nav-storage">
<p className="coz-nav-storage-text">
{t('storage_phrase', {
diskUsage: storageData.humanDiskUsage,
diskQuota: storageData.humanDiskQuota
})}
</p>
<progress
className="cozy-nav-storage-bar"
value={storageData.humanDiskUsage}
max={storageData.humanDiskQuota}
min="0"
<>
{t('storage_phrase', {
diskUsage: storageData.humanDiskUsage,
diskQuota: storageData.humanDiskQuota
})}
<LinearProgress
style={{ width: '85%' }}
className="u-mt-half"
variant="determinate"
value={parseInt(storageData.percentUsage)}
/>
</div>
</>
)
}

Expand Down
Loading

0 comments on commit d8a5fcd

Please sign in to comment.