pl-fe: Allow reordering profile fields
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
9227eef670
commit
b016dbec2b
4 changed files with 40 additions and 3 deletions
|
@ -31,7 +31,10 @@ const spaces = {
|
||||||
8: 'gap-8',
|
8: 'gap-8',
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IHStack extends Pick<React.HTMLAttributes<HTMLDivElement>, 'children' | 'className' | 'onClick' | 'style' | 'title'> {
|
interface IHStack extends Pick<
|
||||||
|
React.HTMLAttributes<HTMLDivElement>,
|
||||||
|
'children' | 'className' | 'draggable' | 'onClick' | 'onDragEnd' | 'onDragEnter' | 'onDragStart' | 'style' | 'title'
|
||||||
|
> {
|
||||||
/** Vertical alignment of children. */
|
/** Vertical alignment of children. */
|
||||||
alignItems?: keyof typeof alignItemsOptions;
|
alignItems?: keyof typeof alignItemsOptions;
|
||||||
/** Horizontal alignment of children. */
|
/** Horizontal alignment of children. */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { useIntl, defineMessages } from 'react-intl';
|
import { useIntl, defineMessages } from 'react-intl';
|
||||||
|
|
||||||
import Button from '../button/button';
|
import Button from '../button/button';
|
||||||
|
@ -39,6 +39,8 @@ interface IStreamfield {
|
||||||
minItems?: number;
|
minItems?: number;
|
||||||
/** Maximum number of allowed inputs. */
|
/** Maximum number of allowed inputs. */
|
||||||
maxItems?: number;
|
maxItems?: number;
|
||||||
|
/** Allow changing order of the items. */
|
||||||
|
draggable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** List of inputs that can be added or removed. */
|
/** List of inputs that can be added or removed. */
|
||||||
|
@ -52,9 +54,29 @@ const Streamfield: React.FC<IStreamfield> = ({
|
||||||
component: Component,
|
component: Component,
|
||||||
maxItems = Infinity,
|
maxItems = Infinity,
|
||||||
minItems = 0,
|
minItems = 0,
|
||||||
|
draggable,
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const dragItem = useRef<number | null>();
|
||||||
|
const dragOverItem = useRef<number | null>();
|
||||||
|
|
||||||
|
const handleDragStart = (i: number) => () => {
|
||||||
|
dragItem.current = i;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragEnter = (i: number) => () => {
|
||||||
|
dragOverItem.current = i;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDragEnd = () => {
|
||||||
|
const newData = [...values];
|
||||||
|
const item = newData.splice(dragItem.current!, 1)[0];
|
||||||
|
newData.splice(dragOverItem.current!, 0, item);
|
||||||
|
|
||||||
|
onChange(newData);
|
||||||
|
};
|
||||||
|
|
||||||
const handleChange = (i: number) => (value: any) => {
|
const handleChange = (i: number) => (value: any) => {
|
||||||
const newData = [...values];
|
const newData = [...values];
|
||||||
newData[i] = value;
|
newData[i] = value;
|
||||||
|
@ -71,7 +93,15 @@ const Streamfield: React.FC<IStreamfield> = ({
|
||||||
{(values.length > 0) && (
|
{(values.length > 0) && (
|
||||||
<Stack space={1}>
|
<Stack space={1}>
|
||||||
{values.map((value, i) => value?._destroy ? null : (
|
{values.map((value, i) => value?._destroy ? null : (
|
||||||
<HStack key={i} space={2} alignItems='center'>
|
<HStack
|
||||||
|
key={i}
|
||||||
|
space={2}
|
||||||
|
alignItems='center'
|
||||||
|
draggable={draggable}
|
||||||
|
onDragStart={handleDragStart(i)}
|
||||||
|
onDragEnter={handleDragEnter(i)}
|
||||||
|
onDragEnd={handleDragEnd}
|
||||||
|
>
|
||||||
<Component
|
<Component
|
||||||
key={i}
|
key={i}
|
||||||
index={i}
|
index={i}
|
||||||
|
|
|
@ -452,6 +452,7 @@ const EditProfile: React.FC = () => {
|
||||||
onRemoveItem={handleRemoveField}
|
onRemoveItem={handleRemoveField}
|
||||||
component={ProfileField}
|
component={ProfileField}
|
||||||
maxItems={maxFields}
|
maxItems={maxFields}
|
||||||
|
draggable
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -288,6 +288,7 @@ const PlFeConfig: React.FC = () => {
|
||||||
onChange={handleStreamItemChange(['promoPanel', 'items'])}
|
onChange={handleStreamItemChange(['promoPanel', 'items'])}
|
||||||
onAddItem={addStreamItem(['promoPanel', 'items'], templates.promoPanel)}
|
onAddItem={addStreamItem(['promoPanel', 'items'], templates.promoPanel)}
|
||||||
onRemoveItem={deleteStreamItem(['promoPanel', 'items'])}
|
onRemoveItem={deleteStreamItem(['promoPanel', 'items'])}
|
||||||
|
draggable
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Streamfield
|
<Streamfield
|
||||||
|
@ -298,6 +299,7 @@ const PlFeConfig: React.FC = () => {
|
||||||
onChange={handleStreamItemChange(['navlinks', 'homeFooter'])}
|
onChange={handleStreamItemChange(['navlinks', 'homeFooter'])}
|
||||||
onAddItem={addStreamItem(['navlinks', 'homeFooter'], templates.footerItem)}
|
onAddItem={addStreamItem(['navlinks', 'homeFooter'], templates.footerItem)}
|
||||||
onRemoveItem={deleteStreamItem(['navlinks', 'homeFooter'])}
|
onRemoveItem={deleteStreamItem(['navlinks', 'homeFooter'])}
|
||||||
|
draggable
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormGroup labelText={intl.formatMessage(messages.copyrightFooterLabel)}>
|
<FormGroup labelText={intl.formatMessage(messages.copyrightFooterLabel)}>
|
||||||
|
@ -347,6 +349,7 @@ const PlFeConfig: React.FC = () => {
|
||||||
onChange={handleStreamItemChange(['cryptoAddresses'])}
|
onChange={handleStreamItemChange(['cryptoAddresses'])}
|
||||||
onAddItem={addStreamItem(['cryptoAddresses'], templates.cryptoAddress)}
|
onAddItem={addStreamItem(['cryptoAddresses'], templates.cryptoAddress)}
|
||||||
onRemoveItem={deleteStreamItem(['cryptoAddresses'])}
|
onRemoveItem={deleteStreamItem(['cryptoAddresses'])}
|
||||||
|
draggable
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormGroup labelText={intl.formatMessage(messages.cryptoDonatePanelLimitLabel)}>
|
<FormGroup labelText={intl.formatMessage(messages.cryptoDonatePanelLimitLabel)}>
|
||||||
|
|
Loading…
Reference in a new issue