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

Feature/addbutton change #520

Merged
merged 15 commits into from
Jan 7, 2020
3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.formatOnSave": true,
"eslint.validate": [{ "language": "typescript", "autoFix": true }, { "language": "typescriptreact", "autoFix": true }]
"editor.formatOnSave": true
}
135 changes: 106 additions & 29 deletions apps/sensenet/src/components/AddButton.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,49 @@
import Button from '@material-ui/core/Button'
import Fab from '@material-ui/core/Fab'
import SwipeableDrawer from '@material-ui/core/SwipeableDrawer'
import Tooltip from '@material-ui/core/Tooltip'
import Typography from '@material-ui/core/Typography'
import Add from '@material-ui/icons/Add'
import CloudUpload from '@material-ui/icons/CloudUpload'
import { GenericContent, Schema } from '@sensenet/default-content-types'
import React, { useContext, useEffect, useState } from 'react'
import { CurrentContentContext, useLogger, useRepository } from '@sensenet/hooks-react'
import {
Button,
createStyles,
IconButton,
ListItem,
ListItemIcon,
ListItemText,
makeStyles,
SwipeableDrawer,
Theme,
Tooltip,
Typography,
} from '@material-ui/core'
import { useLocalization } from '../hooks'
import { Icon } from './Icon'
import { useDialog } from './dialogs'

const useStyles = makeStyles((theme: Theme) => {
return createStyles({
addButton: {
width: '32px',
height: '32px',
minHeight: 0,
padding: 0,
margin: '0.5rem 0.5rem',
backgroundColor: theme.palette.primary.main,
'&:hover': {
backgroundColor: theme.palette.primary.dark,
},
},
})
})

export interface AddButtonProps {
parent?: GenericContent
allowedTypes?: string[]
isOpened?: boolean
path: string
}

export const AddButton: React.FunctionComponent<AddButtonProps> = props => {
const classes = useStyles()
const repo = useRepository()
const { openDialog } = useDialog()
const parentContext = useContext(CurrentContentContext)
Expand All @@ -26,6 +52,7 @@ export const AddButton: React.FunctionComponent<AddButtonProps> = props => {
const [allowedChildTypes, setAllowedChildTypes] = useState<Schema[]>([])
const localization = useLocalization().addButton
const logger = useLogger('AddButton')
const [isAvailable, setAvailable] = useState(false)

useEffect(() => {
props.parent && setParent(props.parent)
Expand All @@ -36,33 +63,83 @@ export const AddButton: React.FunctionComponent<AddButtonProps> = props => {
}, [parentContext, props.parent])

useEffect(() => {
if (props.allowedTypes && props.allowedTypes.length > 0) {
setAllowedChildTypes(props.allowedTypes.map(type => repo.schemas.getSchemaByName(type)))
} else if (showSelectType) {
repo
.getAllowedChildTypes({ idOrPath: parent.Id })
.then(types => setAllowedChildTypes(types.d.results.map(t => repo.schemas.getSchemaByName(t.Name))))
.catch(error => {
logger.error({
message: localization.errorGettingAllowedContentTypes,
data: {
details: { error },
},
})
const getActions = async () => {
try {
const actions = await repo.getActions({ idOrPath: props.parent ? parent.Id : props.path })
const isActionFound = actions.d.Actions.some(action => action.Name === 'Add' || action.Name === 'Upload')
setAvailable(isActionFound)
} catch (error) {
logger.error({
message: localization.errorGettingActions,
data: {
details: { error },
},
})
}
}

if (props.parent || props.path !== '') {
getActions()
} else {
setAvailable(false)
}
}, [localization.errorGettingActions, logger, parent, props.parent, props.path, repo])

useEffect(() => {
const getAllowedChildTypes = async () => {
try {
const allowedChildTypesFromRepo = await repo.getAllowedChildTypes({
idOrPath: props.parent ? parent.Id : props.path,
})
const allowedChildTypeList = allowedChildTypesFromRepo.d.results.map(t => repo.schemas.getSchemaByName(t.Name))
setAllowedChildTypes(allowedChildTypeList)
} catch (error) {
logger.error({
message: localization.errorGettingAllowedContentTypes,
data: {
details: { error },
},
})
}
}

if (showSelectType) {
props.parent || props.path !== '' ? getAllowedChildTypes() : setAllowedChildTypes([])
}
}, [localization.errorGettingAllowedContentTypes, logger, parent.Id, props.allowedTypes, repo, showSelectType])
}, [localization.errorGettingAllowedContentTypes, logger, parent.Id, props.parent, props.path, repo, showSelectType])

return (
<div>
<Tooltip title={localization.tooltip} placement="top-end">
<Fab
color="primary"
style={{ position: 'fixed', bottom: '1em', right: '1em' }}
onClick={() => setShowSelectType(true)}>
<Add />
</Fab>
</Tooltip>
<div
style={{
display: 'flex',
justifyContent: 'center',
position: 'relative',
}}>
{!props.isOpened ? (
<Tooltip title={localization.tooltip} placement="right">
<span>
<IconButton className={classes.addButton} onClick={() => setShowSelectType(true)} disabled={!isAvailable}>
<Add />
</IconButton>
</span>
</Tooltip>
) : (
<ListItem
style={{
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-evenly',
}}
button={true}
onClick={() => setShowSelectType(true)}
disabled={!isAvailable}>
<ListItemIcon>
<Add />
</ListItemIcon>
<ListItemText primary={localization.addNew} />
</ListItem>
)}
<SwipeableDrawer
anchor="bottom"
onClose={() => setShowSelectType(false)}
Expand Down
4 changes: 0 additions & 4 deletions apps/sensenet/src/components/content/Commander.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
useRepository,
} from '@sensenet/hooks-react'
import { useSelectionService } from '../../hooks'
import { AddButton } from '../AddButton'
import { CollectionComponent } from '../content-list'
import { useDialog } from '../dialogs'

Expand All @@ -29,7 +28,6 @@ export const CommanderComponent: React.FunctionComponent<CommanderComponentProps
const repo = useRepository()
const { openDialog } = useDialog()
const selectionService = useSelectionService()

const [_leftPanelRef, setLeftPanelRef] = useState<null | any>(null)
const [_rightPanelRef, setRightPanelRef] = useState<null | any>(null)

Expand Down Expand Up @@ -141,8 +139,6 @@ export const CommanderComponent: React.FunctionComponent<CommanderComponentProps
</CurrentChildrenProvider>
</CurrentContentProvider>
</LoadSettingsContextProvider>

{activeParent ? <AddButton parent={activeParent} /> : null}
</div>
)
}
Expand Down
3 changes: 0 additions & 3 deletions apps/sensenet/src/components/content/Explore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
LoadSettingsContextProvider,
} from '@sensenet/hooks-react'
import { useSelectionService } from '../../hooks'
import { AddButton } from '../AddButton'
import { ContentBreadcrumbs } from '../ContentBreadcrumbs'
import { CollectionComponent } from '../content-list'
import { Tree } from '../tree/index'
Expand Down Expand Up @@ -70,8 +69,6 @@ export const Explore: React.FunctionComponent<ExploreComponentProps> = props =>
fieldsToDisplay={props.fieldsToDisplay}
onActiveItemChange={item => selectionService.activeContent.setValue(item)}
/>

<AddButton />
</div>
</CurrentAncestorsProvider>
</CurrentChildrenProvider>
Expand Down
2 changes: 0 additions & 2 deletions apps/sensenet/src/components/content/Simple.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
LoadSettingsContextProvider,
} from '@sensenet/hooks-react'
import { useSelectionService } from '../../hooks'
import { AddButton } from '../AddButton'
import { CollectionComponent, CollectionComponentProps } from '../content-list'

export interface SimpleListComponentProps {
Expand Down Expand Up @@ -36,7 +35,6 @@ export const SimpleList: React.FunctionComponent<SimpleListComponentProps> = pro
onActiveItemChange={item => selectionService.activeContent.setValue(item)}
{...props.collectionComponentProps}
/>
<AddButton />
</CurrentAncestorsProvider>
</CurrentChildrenProvider>
</CurrentContentProvider>
Expand Down
67 changes: 34 additions & 33 deletions apps/sensenet/src/components/drawer/PermanentDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,24 @@ import Settings from '@material-ui/icons/Settings'
import { PathHelper } from '@sensenet/client-utils'
import React, { useContext, useEffect, useState } from 'react'
import { withRouter } from 'react-router'
import { Link, matchPath, NavLink, RouteComponentProps } from 'react-router-dom'
import { matchPath, NavLink, RouteComponentProps } from 'react-router-dom'
import { useRepository, useSession } from '@sensenet/hooks-react'
import { ResponsiveContext, ResponsivePersonalSetttings } from '../../context'
import { useDrawerItems, useLocalization, usePersonalSettings, useTheme } from '../../hooks'
import { useDrawerItems, useLocalization, usePersonalSettings, useSelectionService, useTheme } from '../../hooks'
import { LogoutButton } from '../LogoutButton'
import { UserAvatar } from '../UserAvatar'
import { AddButton } from '../AddButton'

const PermanentDrawer: React.FunctionComponent<RouteComponentProps> = props => {
const settings = useContext(ResponsivePersonalSetttings)
const selectionService = useSelectionService()
const personalSettings = usePersonalSettings()
const theme = useTheme()
const session = useSession()
const repo = useRepository()
const device = useContext(ResponsiveContext)

const [currentComponent, setCurrentComponent] = useState(selectionService.activeContent.getValue())
const [currentPath, setCurrentPath] = useState('')
const [opened, setOpened] = useState(settings.drawer.type === 'permanent')
const items = useDrawerItems()
const localization = useLocalization().drawer
Expand All @@ -35,13 +38,21 @@ const PermanentDrawer: React.FunctionComponent<RouteComponentProps> = props => {
personalSettings.repositories.find(r => r.url === PathHelper.trimSlashes(repo.configuration.repositoryUrl)),
)

useEffect(
() =>
setCurrentRepoEntry(
personalSettings.repositories.find(r => r.url === PathHelper.trimSlashes(repo.configuration.repositoryUrl)),
),
[personalSettings, repo],
)
useEffect(() => {
const activeComponentObserve = selectionService.activeContent.subscribe(newActiveComponent =>
setCurrentComponent(newActiveComponent),
)

return function cleanup() {
activeComponentObserve.dispose()
}
}, [selectionService.activeContent])

useEffect(() => {
setCurrentRepoEntry(
personalSettings.repositories.find(r => r.url === PathHelper.trimSlashes(repo.configuration.repositoryUrl)),
)
}, [personalSettings, repo])

if (!settings.drawer.enabled) {
return null
Expand All @@ -63,28 +74,18 @@ const PermanentDrawer: React.FunctionComponent<RouteComponentProps> = props => {
transition: 'width 100ms ease-in-out',
}}>
<div style={{ paddingTop: '1em', overflowY: 'auto', overflowX: 'hidden' }}>
<AddButton isOpened={opened} parent={currentComponent} path={currentPath} />
{items.map((item, index) => {
const isActive = matchPath(props.location.pathname, `/:repositoryId${item.url}`)
return isActive ? (
<ListItem button={true} key={index} selected>
<Tooltip
title={
<React.Fragment>
{item.primaryText} <br /> {item.secondaryText}
</React.Fragment>
}
placement="right">
<ListItemIcon>{item.icon}</ListItemIcon>
</Tooltip>
{opened ? <ListItemText primary={item.primaryText} secondary={item.secondaryText} /> : null}
</ListItem>
) : (
return (
<NavLink
to={`/${btoa(repo.configuration.repositoryUrl)}${item.url}`}
activeStyle={{ opacity: 1 }}
style={{ textDecoration: 'none', opacity: 0.54 }}
key={index}>
<ListItem button={true}>
key={index}
onClick={() => setCurrentPath(item.root ? item.root : '')}>
<ListItem
button={true}
key={index}
selected={matchPath(props.location.pathname, `/:repositoryId${item.url}`) === null ? false : true}>
<Tooltip
title={
<React.Fragment>
Expand Down Expand Up @@ -121,11 +122,11 @@ const PermanentDrawer: React.FunctionComponent<RouteComponentProps> = props => {
/>
<ListItemSecondaryAction>
{device === 'mobile' ? null : (
<Link to={`/personalSettings`} style={{ textDecoration: 'none' }}>
<NavLink to="/personalSettings" style={{ textDecoration: 'none' }}>
<IconButton title={localization.personalSettingsTitle}>
<Settings />
</IconButton>
</Link>
</NavLink>
)}
<LogoutButton />
</ListItemSecondaryAction>
Expand All @@ -134,10 +135,10 @@ const PermanentDrawer: React.FunctionComponent<RouteComponentProps> = props => {
) : (
<>
<NavLink
to={'/personalSettings'}
activeStyle={{ opacity: 1 }}
to="/personalSettings"
style={{ textDecoration: 'none', opacity: 0.54 }}
key={'personalSettings'}>
key="personalSettings"
onClick={() => setCurrentPath('')}>
<ListItem button={true}>
<Tooltip
title={
Expand Down
Loading