feat: remove duplication of config in tests
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
@import '../../../../scss/styles';
|
||||
|
||||
.action-panel {
|
||||
|
||||
&__remove-row {
|
||||
margin: 0 0 base(.3);
|
||||
}
|
||||
|
||||
&__add-row {
|
||||
margin: base(.3) 0 0;
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import Button from '../../../elements/Button';
|
||||
import Popup from '../../../elements/Popup';
|
||||
import BlockSelector from '../../field-types/Blocks/BlockSelector';
|
||||
import { Props } from './types';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'action-panel';
|
||||
|
||||
const ActionPanel: React.FC<Props> = (props) => {
|
||||
const {
|
||||
addRow,
|
||||
removeRow,
|
||||
label = 'Row',
|
||||
blockType,
|
||||
blocks = [],
|
||||
rowIndex,
|
||||
isHovered,
|
||||
hasMaxRows,
|
||||
} = props;
|
||||
|
||||
const classes = [
|
||||
baseClass,
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<Popup
|
||||
showOnHover
|
||||
size="wide"
|
||||
color="dark"
|
||||
horizontalAlign="right"
|
||||
buttonType="custom"
|
||||
button={(
|
||||
<Button
|
||||
className={`${baseClass}__remove-row`}
|
||||
round
|
||||
buttonStyle="none"
|
||||
icon="x"
|
||||
iconPosition="left"
|
||||
iconStyle="with-border"
|
||||
onClick={() => removeRow(rowIndex)}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
Remove
|
||||
{label}
|
||||
</Popup>
|
||||
|
||||
{!hasMaxRows && (
|
||||
<React.Fragment>
|
||||
{blockType === 'blocks'
|
||||
? (
|
||||
<Popup
|
||||
buttonType="custom"
|
||||
size="large"
|
||||
horizontalAlign="right"
|
||||
button={(
|
||||
<Button
|
||||
className={`${baseClass}__add-row`}
|
||||
round
|
||||
buttonStyle="none"
|
||||
icon="plus"
|
||||
iconPosition="left"
|
||||
iconStyle="with-border"
|
||||
/>
|
||||
)}
|
||||
render={({ close }) => (
|
||||
<BlockSelector
|
||||
blocks={blocks}
|
||||
addRow={addRow}
|
||||
addRowIndex={rowIndex}
|
||||
close={close}
|
||||
parentIsHovered={isHovered}
|
||||
watchParentHover
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<Popup
|
||||
showOnHover
|
||||
size="wide"
|
||||
color="dark"
|
||||
horizontalAlign="center"
|
||||
buttonType="custom"
|
||||
button={(
|
||||
<Button
|
||||
className={`${baseClass}__add-row`}
|
||||
round
|
||||
buttonStyle="none"
|
||||
icon="plus"
|
||||
iconPosition="left"
|
||||
iconStyle="with-border"
|
||||
onClick={() => addRow(rowIndex)}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
Add
|
||||
{label}
|
||||
</Popup>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ActionPanel;
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Block } from '../../../../../fields/config/types';
|
||||
|
||||
export type Props = {
|
||||
label: string
|
||||
addRow?: (index: number, blockType?: string) => void
|
||||
removeRow?: (index: number) => void
|
||||
blockType?: string
|
||||
isHovered: boolean
|
||||
rowIndex: number
|
||||
blocks?: Block[]
|
||||
hasMaxRows?: boolean
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
@import '../../../../scss/styles';
|
||||
|
||||
.position-panel {
|
||||
&__move-backward {
|
||||
transform: rotate(.5turn);
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&__move-forward {
|
||||
margin: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&__current-position {
|
||||
text-align: center;
|
||||
color: var(--theme-elevation-400);
|
||||
}
|
||||
|
||||
padding-right: base(.5);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import React from 'react';
|
||||
import Button from '../../../elements/Button';
|
||||
import { Props } from './types';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'position-panel';
|
||||
|
||||
const PositionPanel: React.FC<Props> = (props) => {
|
||||
const { moveRow, positionIndex, rowCount, readOnly } = props;
|
||||
|
||||
const adjustedIndex = positionIndex + 1;
|
||||
|
||||
const classes = [
|
||||
baseClass,
|
||||
`${baseClass}__${readOnly ? 'read-only' : ''}`,
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
{!readOnly && (
|
||||
<Button
|
||||
className={`${baseClass}__move-backward ${positionIndex === 0 ? 'first-row' : ''}`}
|
||||
buttonStyle="none"
|
||||
icon="chevron"
|
||||
round
|
||||
onClick={() => moveRow(positionIndex, positionIndex - 1)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{(adjustedIndex && typeof positionIndex === 'number')
|
||||
&& (
|
||||
<div
|
||||
className={`${baseClass}__current-position`}
|
||||
>
|
||||
{adjustedIndex >= 10 ? adjustedIndex : `0${adjustedIndex}`}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!readOnly && (
|
||||
<Button
|
||||
className={`${baseClass}__move-forward ${(positionIndex === rowCount - 1) ? 'last-row' : ''}`}
|
||||
buttonStyle="none"
|
||||
icon="chevron"
|
||||
round
|
||||
onClick={() => moveRow(positionIndex, positionIndex + 1)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PositionPanel;
|
||||
@@ -1,6 +0,0 @@
|
||||
export type Props = {
|
||||
moveRow: (fromIndex: number, toIndex: number) => void
|
||||
positionIndex: number
|
||||
rowCount: number
|
||||
readOnly: boolean
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
//////////////////////
|
||||
// COMPONENT STYLES
|
||||
//////////////////////
|
||||
|
||||
.draggable-section {
|
||||
padding-bottom: base(.5);
|
||||
|
||||
.draggable-section {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
&__content-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin-bottom: $baseline;
|
||||
}
|
||||
|
||||
&__section-header {
|
||||
display: flex;
|
||||
position: sticky;
|
||||
top: $top-header-offset;
|
||||
z-index: 1;
|
||||
padding: base(.75) base(.75);
|
||||
margin-left: - base(.75);
|
||||
margin-right: - base(.75);
|
||||
width: calc(100% + #{base(1.5)});
|
||||
}
|
||||
|
||||
&__render-fields-wrapper {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&.is-hovered>div {
|
||||
>.field-type-gutter {
|
||||
&.actions {
|
||||
|
||||
.field-type-gutter__content {
|
||||
&:hover {
|
||||
z-index: $z-nav;
|
||||
}
|
||||
}
|
||||
|
||||
.field-type-gutter__content-container {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.field-type-gutter__content-container {
|
||||
box-shadow: #{$style-stroke-width-m} 0px 0px 0px var(--theme-elevation-800);
|
||||
}
|
||||
|
||||
.position-panel__move-forward,
|
||||
.position-panel__move-backward {
|
||||
opacity: 1;
|
||||
|
||||
&.first-row,
|
||||
&.last-row {
|
||||
opacity: .15;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.position-panel__current-position {
|
||||
color: var(--theme-elevation-800);
|
||||
}
|
||||
}
|
||||
|
||||
.toggle-collapse {
|
||||
@include color-svg(var(--theme-elevation-0));
|
||||
|
||||
.btn__icon {
|
||||
background-color: var(--theme-elevation-400);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--theme-elevation-800);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label.field-label {
|
||||
line-height: 1;
|
||||
padding-bottom: base(.75)
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
min-width: base(16);
|
||||
|
||||
.position-panel__move-forward,
|
||||
.position-panel__move-backward {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&__section-header {
|
||||
top: $top-header-offset-m;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import AnimateHeight from 'react-animate-height';
|
||||
import { Draggable } from 'react-beautiful-dnd';
|
||||
|
||||
import ActionPanel from './ActionPanel';
|
||||
import SectionTitle from './SectionTitle';
|
||||
import PositionPanel from './PositionPanel';
|
||||
import Button from '../../elements/Button';
|
||||
import { NegativeFieldGutterProvider } from '../FieldTypeGutter/context';
|
||||
import FieldTypeGutter from '../FieldTypeGutter';
|
||||
import RenderFields from '../RenderFields';
|
||||
import { Props } from './types';
|
||||
import HiddenInput from '../field-types/HiddenInput';
|
||||
import { fieldAffectsData } from '../../../../fields/config/types';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'draggable-section';
|
||||
|
||||
const DraggableSection: React.FC<Props> = (props) => {
|
||||
const {
|
||||
moveRow,
|
||||
addRow,
|
||||
removeRow,
|
||||
rowIndex,
|
||||
rowCount,
|
||||
parentPath,
|
||||
fieldSchema,
|
||||
label,
|
||||
blockType,
|
||||
fieldTypes,
|
||||
id,
|
||||
setRowCollapse,
|
||||
isCollapsed,
|
||||
permissions,
|
||||
readOnly,
|
||||
hasMaxRows,
|
||||
} = props;
|
||||
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const classes = [
|
||||
baseClass,
|
||||
isCollapsed ? 'is-collapsed' : 'is-open',
|
||||
(isHovered && !readOnly) && 'is-hovered',
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<Draggable
|
||||
draggableId={id}
|
||||
index={rowIndex}
|
||||
isDragDisabled={readOnly}
|
||||
>
|
||||
{(providedDrag) => (
|
||||
<div
|
||||
ref={providedDrag.innerRef}
|
||||
className={classes}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
onMouseOver={() => setIsHovered(true)}
|
||||
onFocus={() => setIsHovered(true)}
|
||||
{...providedDrag.draggableProps}
|
||||
>
|
||||
|
||||
<div className={`${baseClass}__content-wrapper`}>
|
||||
<FieldTypeGutter
|
||||
variant="left"
|
||||
dragHandleProps={providedDrag.dragHandleProps}
|
||||
>
|
||||
<PositionPanel
|
||||
moveRow={moveRow}
|
||||
rowCount={rowCount}
|
||||
positionIndex={rowIndex}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
</FieldTypeGutter>
|
||||
|
||||
<div className={`${baseClass}__render-fields-wrapper`}>
|
||||
|
||||
<AnimateHeight
|
||||
height={isCollapsed ? 0 : 'auto'}
|
||||
duration={200}
|
||||
>
|
||||
<NegativeFieldGutterProvider allow={false}>
|
||||
<RenderFields
|
||||
readOnly={readOnly}
|
||||
fieldTypes={fieldTypes}
|
||||
key={rowIndex}
|
||||
permissions={permissions?.fields}
|
||||
fieldSchema={fieldSchema.map((field) => ({
|
||||
...field,
|
||||
path: `${parentPath}.${rowIndex}${fieldAffectsData(field) ? `.${field.name}` : ''}`,
|
||||
}))}
|
||||
/>
|
||||
</NegativeFieldGutterProvider>
|
||||
</AnimateHeight>
|
||||
</div>
|
||||
|
||||
<FieldTypeGutter
|
||||
variant="right"
|
||||
className="actions"
|
||||
dragHandleProps={providedDrag.dragHandleProps}
|
||||
>
|
||||
{!readOnly && (
|
||||
<ActionPanel
|
||||
addRow={addRow}
|
||||
removeRow={removeRow}
|
||||
rowIndex={rowIndex}
|
||||
label={label}
|
||||
isHovered={isHovered}
|
||||
hasMaxRows={hasMaxRows}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
</FieldTypeGutter>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Draggable>
|
||||
);
|
||||
};
|
||||
|
||||
export default DraggableSection;
|
||||
@@ -1,25 +0,0 @@
|
||||
import { Field, Block } from '../../../../fields/config/types';
|
||||
import { FieldTypes } from '../field-types';
|
||||
import { FieldPermissions } from '../../../../auth/types';
|
||||
|
||||
export type Props = {
|
||||
moveRow: (fromIndex: number, toIndex: number) => void
|
||||
addRow: (index: number, blockType?: string) => void
|
||||
removeRow: (index: number) => void
|
||||
rowIndex: number
|
||||
rowCount: number
|
||||
parentPath: string
|
||||
fieldSchema: Field[],
|
||||
label?: string
|
||||
blockType?: string
|
||||
fieldTypes: FieldTypes
|
||||
id: string
|
||||
isCollapsed?: boolean
|
||||
setRowCollapse?: (id: string, open: boolean) => void
|
||||
positionPanelVerticalAlignment?: 'top' | 'center' | 'sticky'
|
||||
actionPanelVerticalAlignment?: 'top' | 'center' | 'sticky'
|
||||
permissions: FieldPermissions
|
||||
readOnly: boolean
|
||||
blocks?: Block[]
|
||||
hasMaxRows?: boolean
|
||||
}
|
||||
Reference in New Issue
Block a user