Skip to content

Commit

Permalink
Update connection type field action "Move to section heading" (#3118)
Browse files Browse the repository at this point in the history
* Rename delete to remove

* Add move to section modal

* Use SimpleSelect and hide parent section option
  • Loading branch information
emilys314 authored Aug 27, 2024
1 parent e6b8708 commit 4a0626e
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ class CreateConnectionTypePage {
findSubmitButton() {
return cy.findByTestId('submit-button');
}

shouldHaveTableRowNames(rowNames: string[]) {
rowNames.map((name, index) =>
this.getFieldsTableRow(index).findName().should('contain.text', name),
);
}
}

class ConnectionTypesTableToolbar extends TableToolbar {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,14 @@ describe('edit', () => {
disableConnectionTypes: false,
}),
);
});

it('Drag and drop field rows in table', () => {
cy.interceptOdh(
'GET /api/connection-types/:name',
{ path: { name: 'existing' } },
toConnectionTypeConfigMap(existing),
);
});

it('Drag and drop field rows in table', () => {
createConnectionTypePage.visitEditPage('existing');

createConnectionTypePage.getFieldsTableRow(0).findName().should('contain.text', 'header1');
Expand All @@ -162,4 +162,79 @@ describe('edit', () => {
createConnectionTypePage.getFieldsTableRow(1).findName().should('contain.text', 'field1');
createConnectionTypePage.getFieldsTableRow(2).findName().should('contain.text', 'header1');
});

it('Move field to section modal', () => {
cy.interceptOdh(
'GET /api/connection-types/:name',
{ path: { name: 'existing' } },
mockConnectionTypeConfigMap({
fields: [
{
type: 'short-text',
name: 'field1',
envVar: 'short-text-1',
properties: {},
},
{
type: 'section',
name: 'header1',
},
{
type: 'short-text',
name: 'field2',
envVar: 'short-text-2',
properties: {},
},
{
type: 'section',
name: 'header2',
},
{
type: 'short-text',
name: 'field3',
envVar: 'short-text-3',
properties: {},
},
],
}),
);
createConnectionTypePage.visitEditPage('existing');
createConnectionTypePage.shouldHaveTableRowNames([
'field1',
'header1',
'field2',
'header2',
'field3',
]);

createConnectionTypePage
.getFieldsTableRow(4)
.findKebabAction('Move to section heading')
.click();
// move to default which is the first section
cy.findByTestId('section-heading-select').should('be.disabled');
cy.findByTestId('modal-submit-button').click();
createConnectionTypePage.shouldHaveTableRowNames([
'field1',
'header1',
'field3',
'field2',
'header2',
]);

createConnectionTypePage
.getFieldsTableRow(0)
.findKebabAction('Move to section heading')
.click();
cy.findByTestId('section-heading-select').click();
cy.findByTestId('section-heading-select').findSelectOption('header2').click();
cy.findByTestId('modal-submit-button').click();
createConnectionTypePage.shouldHaveTableRowNames([
'header1',
'field3',
'field2',
'header2',
'field1',
]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import * as React from 'react';
import { Form, FormGroup, Modal } from '@patternfly/react-core';
import { ConnectionTypeField, ConnectionTypeFieldType } from '~/concepts/connectionTypes/types';
import DashboardModalFooter from '~/concepts/dashboard/DashboardModalFooter';
import SimpleSelect, { SimpleSelectOption } from '~/components/SimpleSelect';

type Props = {
row: { field: ConnectionTypeField; index: number };
fields?: ConnectionTypeField[];
onClose: () => void;
onSubmit: (field: ConnectionTypeField, index: number) => void;
};

export const ConnectionTypeMoveFieldToSectionModal: React.FC<Props> = ({
row,
fields: fields,
onClose,
onSubmit,
}) => {
const options = React.useMemo(() => {
const parentSectionIndex = fields?.findLastIndex(
(r, i) => r.type === ConnectionTypeFieldType.Section && i < row.index,
);

const temp: SimpleSelectOption[] = [];
for (let i = 0; fields && i < fields.length; i++) {
if (fields[i].type === ConnectionTypeFieldType.Section && i !== parentSectionIndex) {
temp.push({ label: fields[i].name, key: String(i) });
}
}

return temp;
}, [fields, row]);

const [selectedSection, setSelectedSection] = React.useState<SimpleSelectOption | undefined>(
options[0],
);

return (
<Modal
isOpen
title="Move to section"
onClose={onClose}
variant="medium"
footer={
<DashboardModalFooter
submitLabel="Move"
onCancel={onClose}
onSubmit={() => {
if (selectedSection) {
onSubmit(row.field, Number(selectedSection.key));
onClose();
}
}}
isSubmitDisabled={!selectedSection}
alertTitle=""
/>
}
>
Select the section heading that <b>{row.field.name}</b> will be moved to.
<Form>
<FormGroup fieldId="sectionHeading" label="Section heading" isRequired>
<SimpleSelect
id="sectionHeading"
dataTestId="section-heading-select"
options={options}
value={selectedSection?.key}
onChange={(key) => setSelectedSection(options.find((s) => s.key === key))}
isFullWidth
isDisabled={options.length === 1}
/>
</FormGroup>
</Form>
</Modal>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ConnectionTypeField, ConnectionTypeFieldType } from '~/concepts/connect
import useDraggableTableControlled from '~/utilities/useDraggableTableControlled';
import ConnectionTypeFieldModal from './ConnectionTypeFieldModal';
import ManageConnectionTypeFieldsTableRow from './ManageConnectionTypeFieldsTableRow';
import { ConnectionTypeMoveFieldToSectionModal } from './ConnectionTypeFieldMoveModal';

type EmptyFieldsTableProps = {
onAddSection: () => void;
Expand Down Expand Up @@ -63,6 +64,10 @@ const ManageConnectionTypeFieldsTable: React.FC<Props> = ({ fields, onFieldsChan
const [modalField, setModalField] = React.useState<
{ field?: ConnectionTypeField; index?: number; isEdit?: boolean } | undefined
>();
const [moveToSectionModalField, setMoveToSectionModalField] = React.useState<{
field: ConnectionTypeField;
index: number;
}>();

const { tableProps, rowsToRender } = useDraggableTableControlled<ConnectionTypeField>(
fields,
Expand Down Expand Up @@ -90,15 +95,17 @@ const ManageConnectionTypeFieldsTable: React.FC<Props> = ({ fields, onFieldsChan
<ManageConnectionTypeFieldsTableRow
key={index}
row={row}
rowIndex={index}
columns={columns}
fields={fields}
onEdit={() => {
setModalField({
field: row,
isEdit: true,
index,
});
}}
onDelete={() => onFieldsChange(fields.filter((f, i) => i !== index))}
onRemove={() => onFieldsChange(fields.filter((f, i) => i !== index))}
onDuplicate={(field) => {
setModalField({
field: structuredClone(field),
Expand All @@ -114,6 +121,9 @@ const ManageConnectionTypeFieldsTable: React.FC<Props> = ({ fields, onFieldsChan
setModalField({});
}
}}
onMoveToSection={() => {
setMoveToSectionModalField({ field: row, index });
}}
onChange={(updatedField) => {
onFieldsChange([
...fields.slice(0, index),
Expand Down Expand Up @@ -181,6 +191,20 @@ const ManageConnectionTypeFieldsTable: React.FC<Props> = ({ fields, onFieldsChan
}}
/>
) : undefined}
{moveToSectionModalField && (
<ConnectionTypeMoveFieldToSectionModal
row={moveToSectionModalField}
fields={fields}
onClose={() => setMoveToSectionModalField(undefined)}
onSubmit={(field, sectionIndex) => {
const temp = fields.toSpliced(moveToSectionModalField.index, 1);
const newFieldIndex =
moveToSectionModalField.index < sectionIndex ? sectionIndex : sectionIndex + 1;
onFieldsChange(temp.toSpliced(newFieldIndex, 0, field));
setMoveToSectionModalField(undefined);
}}
/>
)}
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,39 @@ import TruncatedText from '~/components/TruncatedText';

type Props = {
row: ConnectionTypeField;
rowIndex: number;
columns: ThProps[];
fields: ConnectionTypeField[];
onEdit: () => void;
onDelete: () => void;
onRemove: () => void;
onDuplicate: (field: ConnectionTypeField) => void;
onAddField: (parentSection: SectionField) => void;
onMoveToSection: () => void;
onChange: (updatedField: ConnectionTypeField) => void;
} & RowProps;

const ManageConnectionTypeFieldsTableRow: React.FC<Props> = ({
row,
rowIndex,
columns,
fields,
onEdit,
onDelete,
onRemove,
onDuplicate,
onAddField,
onMoveToSection,
onChange,
...props
}) => {
const showMoveToSection = React.useMemo(() => {
const parentSection = fields.findLast(
(f, i) => f.type === ConnectionTypeFieldType.Section && i < rowIndex,
);
const numSections = fields.filter((f) => f.type === ConnectionTypeFieldType.Section).length;
const potentialSectionsToMoveTo = parentSection ? numSections - 1 : numSections;
return potentialSectionsToMoveTo > 0;
}, [fields, rowIndex]);

if (row.type === ConnectionTypeFieldType.Section) {
return (
<Tr draggable isStriped data-testid="row" {...props}>
Expand Down Expand Up @@ -65,8 +80,8 @@ const ManageConnectionTypeFieldsTableRow: React.FC<Props> = ({
onClick: () => onDuplicate({ ...row, name: `Duplicate of ${row.name}` }),
},
{
title: 'Delete',
onClick: () => onDelete(),
title: 'Remove',
onClick: () => onRemove(),
},
]}
/>
Expand Down Expand Up @@ -118,9 +133,17 @@ const ManageConnectionTypeFieldsTableRow: React.FC<Props> = ({
title: 'Duplicate',
onClick: () => onDuplicate(row),
},
...(showMoveToSection
? [
{
title: 'Move to section heading',
onClick: () => onMoveToSection(),
},
]
: []),
{
title: 'Delete',
onClick: () => onDelete(),
title: 'Remove',
onClick: () => onRemove(),
},
]}
/>
Expand Down

0 comments on commit 4a0626e

Please sign in to comment.