Skip to content

Commit

Permalink
Merge pull request #1618 from SenseNet/feature/2073-advanced-fields
Browse files Browse the repository at this point in the history
Advanced field groups in content editor
  • Loading branch information
hashtagnulla authored Jun 11, 2024
2 parents 40eba8f + f738c9c commit 5e36c21
Show file tree
Hide file tree
Showing 14 changed files with 8,215 additions and 9,258 deletions.
2 changes: 1 addition & 1 deletion apps/sensenet/src/components/view-controls/browse-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const BrowseView: React.FC<BrowseViewProps> = (props) => {
repository={repository}
handleCancel={() => navigateToAction({ history, routeMatch })}
controlMapper={controlMapper}
localization={{ close: localization.forms.close }}
localization={{ close: localization.forms.close, advancedFields: localization.forms.advancedFields }}
locale={LocalizationObject[personalSettings.language].locale}
classes={{
...classes,
Expand Down
6 changes: 5 additions & 1 deletion apps/sensenet/src/components/view-controls/edit-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ export const EditView: React.FC<EditViewProps> = (props) => {
showTitle={true}
uploadFolderpath="/Root/Content/demoavatars"
controlMapper={controlMapper}
localization={{ submit: localization.forms.submit, cancel: localization.forms.cancel }}
localization={{
submit: localization.forms.submit,
cancel: localization.forms.cancel,
advancedFields: localization.forms.advancedFields,
}}
hideDescription
locale={LocalizationObject[personalSettings.language].locale}
classes={{
Expand Down
1 change: 1 addition & 0 deletions apps/sensenet/src/localization/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ const values = {
addReference: 'Add reference',
ok: 'Ok',
cancel: 'Cancel',
advancedFields: 'Advanced fields',
close: 'Close',
upload: 'Upload',
submit: 'Submit',
Expand Down
1 change: 1 addition & 0 deletions apps/sensenet/src/localization/hungarian.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ const values: Localization = {
removeAvatar: 'Avatar törlése',
changeReference: 'Referencia módosítása',
addReference: 'Referencia hozzáadása',
advancedFields: 'Haladó mezők',
ok: 'Ok',
cancel: 'Vissza',
upload: 'Feltöltés',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Button, Container, Typography } from '@material-ui/core'
import { History } from 'history'
import React, { ElementType } from 'react'
import React from 'react'
import { getUserManager } from '../authentication-service'
import { authenticateUser } from '../oidc-service'

Expand All @@ -20,7 +20,7 @@ export const SessionLost = ({ onAuthenticate }: SessionLostProps) => (

type SessionLostContainerProps = {
history: History
SessionLostComponentOverride?: ElementType<SessionLostProps>
SessionLostComponentOverride?: any
}

export const SessionLostContainer = ({ history, SessionLostComponentOverride }: SessionLostContainerProps) => {
Expand Down
1 change: 1 addition & 0 deletions packages/sn-controls-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@material-ui/core": "~4.11.4",
"@material-ui/icons": "^4.11.3",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^22.0.1",
"@rollup/plugin-node-resolve": "^13.3.0",
Expand Down
175 changes: 141 additions & 34 deletions packages/sn-controls-react/src/viewcontrols/browse-view.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
/**
* @module ViewControls
*/
import { Button, createStyles, Grid, makeStyles, Typography } from '@material-ui/core'
import { Box, Button, createStyles, Grid, IconButton, makeStyles, Theme, Typography } from '@material-ui/core'
import { KeyboardArrowDown, KeyboardArrowUp } from '@material-ui/icons'
import { Repository } from '@sensenet/client-core'
import { ControlMapper } from '@sensenet/control-mapper'
import { GenericContent } from '@sensenet/default-content-types'
import { ActionName, ControlMapper } from '@sensenet/control-mapper'
import { FieldSetting, FieldVisibility, GenericContent } from '@sensenet/default-content-types'
import { useRepository } from '@sensenet/hooks-react'
import type { Locale } from 'date-fns'
import React, { createElement, ReactElement, useEffect, useState } from 'react'
import { FieldLocalization } from '../fieldcontrols/localization'
import { isFullWidthField } from '../helpers'
import { reactControlMapper } from '../react-control-mapper'
import { AdvancedFieldGroup, DEFAULT_GROUP_KEY } from './edit-view'

/**
* Interface for BrowseView properties
Expand All @@ -23,14 +25,15 @@ export interface BrowseViewProps {
controlMapper?: ControlMapper<any, any>
handleCancel?: () => void
localization?: {
advancedFields?: string
close?: string
}
fieldLocalization?: FieldLocalization
classes?: BrowseViewClassKey
locale?: Locale
}

const useStyles = makeStyles(() => {
const useStyles = makeStyles((theme: Theme) => {
return createStyles({
grid: {},
fieldWrapper: {},
Expand All @@ -40,6 +43,24 @@ const useStyles = makeStyles(() => {
textAlign: 'right',
},
cancel: {},
advancedFieldContainer: {
padding: '15px',
fontSize: '18px',
width: '100%',
},
advancedFieldBox: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
width: '88%',
margin: '0 auto',
},
divider: {
width: '88%',
height: '1px',
margin: '16px auto',
backgroundColor: theme.palette.primary.main,
},
})
})

Expand All @@ -52,6 +73,8 @@ export const BrowseView: React.FC<BrowseViewProps> = (props) => {
const controlMapper = props.controlMapper || reactControlMapper(props.repository)
const [schema, setSchema] = useState(controlMapper.getFullSchemaForContentType(props.content.Type, 'browse'))
const classes = useStyles(props)
const [advancedFields, setAdvancedFields] = useState<AdvancedFieldGroup[]>([])
const [advancedFieldStateGroup, setAdvancedFieldStateGroup] = useState<Array<{ key: string; isOpened: boolean }>>([])
const repository = useRepository()

useEffect(() => {
Expand All @@ -61,6 +84,81 @@ export const BrowseView: React.FC<BrowseViewProps> = (props) => {
return () => schemaObservable.dispose()
}, [repository.schemas, props.content.Type, controlMapper])

useEffect(() => {
if (schema) {
const groups: AdvancedFieldGroup[] = [
{
key: DEFAULT_GROUP_KEY,
fields: [],
},
]

schema.fieldMappings.forEach((e) => {
if (e.fieldSettings.VisibleBrowse === FieldVisibility.Advanced) {
const category = e.fieldSettings.Customization?.Categories?.split(' ')[0]
if (category) {
const group = groups.find((g) => g.key === category)
if (group) {
group.fields.push(e)
} else {
groups.push({
key: category,
fields: [e],
})
}
} else {
groups.find((g) => g.key === DEFAULT_GROUP_KEY)?.fields.push(e)
}
}
})

setAdvancedFieldStateGroup(
groups.map((g) => {
return { key: g.key, isOpened: false }
}),
)
setAdvancedFields(groups)
}
}, [schema])

const renderField = (field: { fieldSettings: FieldSetting; actionName: ActionName; controlType: any }) => {
const isFullWidth = isFullWidthField(field, props.content, repository)

return (
<Grid
item={true}
xs={12}
sm={12}
md={12}
lg={12}
xl={12}
key={field.fieldSettings.Name}
className={classes.fieldWrapper}>
<div className={isFullWidth ? classes.fieldFullWidth : classes.field}>
{createElement(
controlMapper.getControlForContentField(props.content.Type, field.fieldSettings.Name, 'browse'),
{
actionName: 'browse',
settings: field.fieldSettings,
content: props.content,
fieldValue: (props.content as any)[field.fieldSettings.Name],
renderIcon: props.renderIcon,
repository: props.repository,
localization: props.fieldLocalization,
locale: props.locale,
},
)}
</div>
</Grid>
)
}

const toggleAdvancedFieldGroup = (key: string) => {
setAdvancedFieldStateGroup((prevItems) =>
prevItems.map((item) => (item.key === key ? { ...item, isOpened: !item.isOpened } : item)),
)
}

return (
<>
{props.renderTitle ? (
Expand All @@ -72,38 +170,47 @@ export const BrowseView: React.FC<BrowseViewProps> = (props) => {
)}
<Grid container={true} spacing={2} className={classes.grid}>
{schema.fieldMappings
.filter(
(i) =>
!advancedFields
.flatMap((g) => g.fields)
.map((g) => g.fieldSettings.Name)
.includes(i.fieldSettings.Name),
)
.sort((item1, item2) => (item2.fieldSettings.FieldIndex || 0) - (item1.fieldSettings.FieldIndex || 0))
.map((field) => {
const isFullWidth = isFullWidthField(field, props.content, repository)
.map((field) => renderField(field))}

return (
<Grid
item={true}
xs={12}
sm={12}
md={12}
lg={12}
xl={12}
key={field.fieldSettings.Name}
className={classes.fieldWrapper}>
<div className={isFullWidth ? classes.fieldFullWidth : classes.field}>
{createElement(
controlMapper.getControlForContentField(props.content.Type, field.fieldSettings.Name, 'browse'),
{
actionName: 'browse',
settings: field.fieldSettings,
content: props.content,
fieldValue: (props.content as any)[field.fieldSettings.Name],
renderIcon: props.renderIcon,
repository: props.repository,
localization: props.fieldLocalization,
locale: props.locale,
},
)}
</div>
</Grid>
)
})}
<Box className={classes.advancedFieldContainer} data-test="advanced-field-container">
{advancedFields.map((group, index) =>
group.fields.length > 0 ? (
<Box key={index} data-test="group-container">
<Box className={classes.divider} />
<Box data-test="group-header">
<Box className={classes.advancedFieldBox}>
<span data-test="advanced-field-group-title">{`${
props.localization?.advancedFields ?? 'Advanced fields'
}${group.key === DEFAULT_GROUP_KEY ? '' : ` - ${group.key}`}`}</span>
<IconButton onClick={() => toggleAdvancedFieldGroup(group.key)}>
{advancedFieldStateGroup.find((g) => g.key === group.key)?.isOpened ? (
<KeyboardArrowUp />
) : (
<KeyboardArrowDown />
)}
</IconButton>
</Box>
</Box>
{advancedFieldStateGroup.find((g) => g.key === group.key)?.isOpened &&
group.fields
.sort(
(item1, item2) => (item2.fieldSettings.FieldIndex || 0) - (item1.fieldSettings.FieldIndex || 0),
)
.map((field) => renderField(field))}
</Box>
) : (
<></>
),
)}
</Box>
</Grid>

<div className={classes.actionButtonWrapper}>
Expand Down
Loading

0 comments on commit 5e36c21

Please sign in to comment.