diff --git a/ui/apps/platform/cypress/integration/clusters/delegatedScanning.test.js b/ui/apps/platform/cypress/integration/clusters/delegatedScanning.test.js index d2a1d87d831e1..6c4376fa3e2a6 100644 --- a/ui/apps/platform/cypress/integration/clusters/delegatedScanning.test.js +++ b/ui/apps/platform/cypress/integration/clusters/delegatedScanning.test.js @@ -38,13 +38,13 @@ describe('Delegated Image Scanning', () => { cy.get('.pf-c-breadcrumb__item:contains("Delegated Image Scanning")'); // check the initial state of the delegate config - getInputByLabel('Enable delegated image scanning').should('not.be.checked'); + getInputByLabel('None').should('be.checked'); - cy.get('label:contains("All registries")').should('not.be.exist'); - cy.get('label:contains("Specified registries")').should('not.be.exist'); + cy.get('label:contains("All registries")').should('not.be.checked'); + cy.get('label:contains("Specified registries")').should('not.be.checked'); // Enable delegate scanning with default - getInputByLabel('Enable delegated image scanning').click(); + getInputByLabel('All registries').click(); getInputByLabel('All registries').should('be.checked'); getInputByLabel('Specified registries').should('not.be.checked'); @@ -54,6 +54,9 @@ describe('Delegated Image Scanning', () => { getInputByLabel('All registries').should('not.be.checked'); getInputByLabel('Specified registries').should('be.checked'); + // None shoudl be value for default cluster + cy.get('.cluster-select').should('have.text', 'None').should('have.value', ''); + // choose the first cluster in the list as the default cy.get('.cluster-select').click(); cy.get('.cluster-select .pf-c-select__menu .pf-c-select__menu-item').then( @@ -62,21 +65,22 @@ describe('Delegated Image Scanning', () => { } ); cy.get('.cluster-select .pf-c-select__menu .pf-c-select__menu-item') - .first() - .then(($firstCluster) => { - const firstClusterName = $firstCluster.text(); + .last() + .then(($lastCluster) => { + const lastClusterName = $lastCluster.text(); + cy.log('lastClusterName', lastClusterName); - $firstCluster.click(); + $lastCluster.click(); - cy.get('.cluster-select').should('have.text', firstClusterName); - }); + cy.get('.cluster-select').should('have.text', lastClusterName); - // save the configuration - saveDelegatedRegistryConfig(); + // save the configuration + saveDelegatedRegistryConfig(); - cy.get( - '.pf-c-alert.pf-m-success .pf-c-alert__title:contains("Delegated scanning configuration saved successfully")' - ); + cy.get( + '.pf-c-alert.pf-m-success .pf-c-alert__title:contains("Delegated scanning configuration saved successfully")' + ); + }); }); describe('when user does not have permission to see page', () => { diff --git a/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/DelegatedRegistriesTable.tsx b/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/DelegatedRegistriesTable.tsx index df19aae616088..1554e786467b2 100644 --- a/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/DelegatedRegistriesTable.tsx +++ b/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/DelegatedRegistriesTable.tsx @@ -3,19 +3,19 @@ /* eslint-disable react/no-array-index-key */ // TODO: remove lint override after @typescript-eslint deps can be resolved to ^5.2.x /* eslint-disable react/prop-types */ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import { Button, Select, SelectOption, TextInput } from '@patternfly/react-core'; import { TableComposable, Tbody, - TbodyProps, + // TbodyProps, Td, Th, Thead, Tr, - TrProps, + // TrProps, } from '@patternfly/react-table'; -import styles from '@patternfly/react-styles/css/components/Table/table'; +// import styles from '@patternfly/react-styles/css/components/Table/table'; import MinusCircleIcon from '@patternfly/react-icons/dist/esm/icons/minus-circle-icon'; import { @@ -35,24 +35,24 @@ type DelegatedRegistriesTableProps = { }; function DelegatedRegistriesTable({ + // TODO: remove lint override after @typescript-eslint deps can be resolved to ^5.2.x + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + // updateRegistriesOrder, registries, clusters, selectedClusterId, handlePathChange, handleClusterChange, deleteRow, - // TODO: remove lint override after @typescript-eslint deps can be resolved to ^5.2.x - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - updateRegistriesOrder, }: DelegatedRegistriesTableProps) { - const [draggedItemId, setDraggedItemId] = React.useState(null); - const [draggingToItemIndex, setDraggingToItemIndex] = React.useState(null); - const [isDragging, setIsDragging] = React.useState(false); + // const [draggedItemId, setDraggedItemId] = React.useState(null); + // const [draggingToItemIndex, setDraggingToItemIndex] = React.useState(null); + // const [isDragging, setIsDragging] = React.useState(false); - const initialOrderIds = registries.map((reg) => reg.uuid as string); - const [itemOrder, setItemOrder] = React.useState(initialOrderIds); - const [tempItemOrder, setTempItemOrder] = React.useState([]); + // const initialOrderIds = registries.map((reg) => reg.uuid as string); + // const [itemOrder, setItemOrder] = React.useState(initialOrderIds); + // const [tempItemOrder, setTempItemOrder] = React.useState([]); const [openRow, setRowOpen] = useState(-1); function toggleSelect(rowToToggle: number) { @@ -63,10 +63,10 @@ function DelegatedRegistriesTable({ setRowOpen(-1); } - useEffect(() => { - const orderIds = registries.map((reg) => reg.uuid as string); - setItemOrder(orderIds); - }, [registries]); + // useEffect(() => { + // const orderIds = registries.map((reg) => reg.uuid as string); + // setItemOrder(orderIds); + // }, [registries]); const clusterSelectOptions: JSX.Element[] = clusters.map((cluster) => { const optionLabel = @@ -78,150 +78,153 @@ function DelegatedRegistriesTable({ ); }); + // TODO (https://issues.redhat.com/browse/ROX-19275): + // Temporarily disabling reordering because of buggy behavior in PF drag-and-drop table variant // Start PatternFly template for drag and drop const bodyRef = React.useRef(); - const onDragStart: TrProps['onDragStart'] = (evt) => { - evt.dataTransfer.effectAllowed = 'move'; - evt.dataTransfer.setData('text/plain', evt.currentTarget.id); - // eslint-disable-next-line @typescript-eslint/no-shadow - const draggedItemId = evt.currentTarget.id; + // const onDragStart: TrProps['onDragStart'] = (evt) => { + // evt.dataTransfer.effectAllowed = 'move'; + // evt.dataTransfer.setData('text/plain', evt.currentTarget.id); + // // eslint-disable-next-line @typescript-eslint/no-shadow + // const draggedItemId = evt.currentTarget.id; - evt.currentTarget.classList.add(styles.modifiers.ghostRow); - evt.currentTarget.setAttribute('aria-pressed', 'true'); + // evt.currentTarget.classList.add(styles.modifiers.ghostRow); + // evt.currentTarget.setAttribute('aria-pressed', 'true'); - setDraggedItemId(draggedItemId); - setIsDragging(true); - }; + // setDraggedItemId(draggedItemId); + // setIsDragging(true); + // }; - const moveItem = (arr: string[], i1: string, toIndex: number) => { - const fromIndex = arr.indexOf(i1); - if (fromIndex === toIndex) { - return arr; - } - const temp = arr.splice(fromIndex, 1); - arr.splice(toIndex, 0, temp[0]); + // const moveItem = (arr: string[], i1: string, toIndex: number) => { + // const fromIndex = arr.indexOf(i1); + // if (fromIndex === toIndex) { + // return arr; + // } + // const temp = arr.splice(fromIndex, 1); + // arr.splice(toIndex, 0, temp[0]); - return arr; - }; + // return arr; + // }; - const move = (itemOrder: string[]) => { - const ulNode = bodyRef.current; - if (ulNode?.children) { - const nodes = Array.from(ulNode.children); - if (nodes.map((node) => node.id).every((id, i) => id === itemOrder[i])) { - return; - } - while (ulNode?.firstChild) { - if (ulNode.lastChild) { - ulNode.removeChild(ulNode.lastChild); - } - } + // const move = (itemOrder: string[]) => { + // const ulNode = bodyRef.current; + // if (ulNode?.children) { + // const nodes = Array.from(ulNode.children); + // if (nodes.map((node) => node.id).every((id, i) => id === itemOrder[i])) { + // return; + // } + // while (ulNode?.firstChild) { + // if (ulNode.lastChild) { + // ulNode.removeChild(ulNode.lastChild); + // } + // } - itemOrder.forEach((id) => { - if (nodes.find((n) => n.id === id)) { - ulNode.appendChild(nodes.find((n) => n.id === id) as Element); - } - }); - } - }; + // itemOrder.forEach((id) => { + // if (nodes.find((n) => n.id === id)) { + // ulNode.appendChild(nodes.find((n) => n.id === id) as Element); + // } + // }); + // } + // }; - const onDragCancel = () => { - if (bodyRef?.current?.children) { - Array.from(bodyRef.current.children).forEach((el) => { - el.classList.remove(styles.modifiers.ghostRow); - el.setAttribute('aria-pressed', 'false'); - }); - setDraggedItemId(null); - setDraggingToItemIndex(null); - setIsDragging(false); - } - }; + // const onDragCancel = () => { + // if (bodyRef?.current?.children) { + // Array.from(bodyRef.current.children).forEach((el) => { + // el.classList.remove(styles.modifiers.ghostRow); + // el.setAttribute('aria-pressed', 'false'); + // }); + // setDraggedItemId(null); + // setDraggingToItemIndex(null); + // setIsDragging(false); + // } + // }; - const onDragLeave: TbodyProps['onDragLeave'] = (evt) => { - if (!isValidDrop(evt)) { - move(itemOrder); - setDraggingToItemIndex(null); - } - }; + // const onDragLeave: TbodyProps['onDragLeave'] = (evt) => { + // if (!isValidDrop(evt)) { + // move(itemOrder); + // setDraggingToItemIndex(null); + // } + // }; - function isValidDrop(evt: React.DragEvent) { - if (bodyRef?.current?.getBoundingClientRect()) { - const ulRect = bodyRef.current.getBoundingClientRect(); - return ( - evt.clientX > ulRect.x && - evt.clientX < ulRect.x + ulRect.width && - evt.clientY > ulRect.y && - evt.clientY < ulRect.y + ulRect.height - ); - } - return false; - } + // function isValidDrop(evt: React.DragEvent) { + // if (bodyRef?.current?.getBoundingClientRect()) { + // const ulRect = bodyRef.current.getBoundingClientRect(); + // return ( + // evt.clientX > ulRect.x && + // evt.clientX < ulRect.x + ulRect.width && + // evt.clientY > ulRect.y && + // evt.clientY < ulRect.y + ulRect.height + // ); + // } + // return false; + // } - const onDrop: TrProps['onDrop'] = (evt) => { - if (isValidDrop(evt)) { - setItemOrder(tempItemOrder); + // const onDrop: TrProps['onDrop'] = (evt) => { + // if (isValidDrop(evt)) { + // setItemOrder(tempItemOrder); - // the rest of this block was added to the PF drag and drop paradigm, - // in order to keep the form data in sync with PF's visual drop order - const newRegistries: DelegatedRegistry[] = tempItemOrder.map((tempItem) => { - const newIndex = registries.findIndex((reg) => reg.uuid === tempItem) || 0; - return registries[newIndex]; - }); + // // the rest of this block was added to the PF drag and drop paradigm, + // // in order to keep the form data in sync with PF's visual drop order + // const newRegistries: DelegatedRegistry[] = tempItemOrder.map((tempItem) => { + // const newIndex = registries.findIndex((reg) => reg.uuid === tempItem) || 0; + // return registries[newIndex]; + // }); - updateRegistriesOrder(newRegistries); - } else { - onDragCancel(); - } - }; + // updateRegistriesOrder(newRegistries); + // } else { + // onDragCancel(); + // } + // }; - function onDragOver(evt): TbodyProps['onDragOver'] { - evt.preventDefault(); + // function onDragOver(evt): TbodyProps['onDragOver'] { + // evt.preventDefault(); - const curListItem = (evt.target as HTMLTableSectionElement).closest('tr'); - if ( - !curListItem || - !bodyRef?.current?.contains(curListItem) || - curListItem.id === draggedItemId - ) { - return undefined; - } - const dragId = curListItem.id; - const newDraggingToItemIndex = Array.from(bodyRef.current.children).findIndex( - (item) => item.id === dragId - ); - if (newDraggingToItemIndex !== draggingToItemIndex) { - const tempItemOrder = moveItem( - [...itemOrder], - draggedItemId || '', - newDraggingToItemIndex - ); - move(tempItemOrder); - setDraggingToItemIndex(newDraggingToItemIndex); - setTempItemOrder(tempItemOrder); - } + // const curListItem = (evt.target as HTMLTableSectionElement).closest('tr'); + // if ( + // !curListItem || + // !bodyRef?.current?.contains(curListItem) || + // curListItem.id === draggedItemId + // ) { + // return undefined; + // } + // const dragId = curListItem.id; + // const newDraggingToItemIndex = Array.from(bodyRef.current.children).findIndex( + // (item) => item.id === dragId + // ); + // if (newDraggingToItemIndex !== draggingToItemIndex) { + // const tempItemOrder = moveItem( + // [...itemOrder], + // draggedItemId || '', + // newDraggingToItemIndex + // ); + // move(tempItemOrder); + // setDraggingToItemIndex(newDraggingToItemIndex); + // setTempItemOrder(tempItemOrder); + // } - return undefined; - } + // return undefined; + // } - const onDragEnd: TrProps['onDragEnd'] = (evt) => { - const target = evt.target as HTMLTableRowElement; - target.classList.remove(styles.modifiers.ghostRow); - target.setAttribute('aria-pressed', 'false'); - setDraggedItemId(null); - setDraggingToItemIndex(null); - setIsDragging(false); - }; + // const onDragEnd: TrProps['onDragEnd'] = (evt) => { + // const target = evt.target as HTMLTableRowElement; + // target.classList.remove(styles.modifiers.ghostRow); + // target.setAttribute('aria-pressed', 'false'); + // setDraggedItemId(null); + // setDraggingToItemIndex(null); + // setIsDragging(false); + // }; // End PatternFly template for drag and drop + // end of TODO section (https://issues.redhat.com/browse/ROX-19275): return ( - Order + {/* Order */} Source registry Destination cluster (CLI/API only) @@ -231,60 +234,69 @@ function DelegatedRegistriesTable({ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore ref={bodyRef} - onDragOver={onDragOver} - onDrop={onDragOver} - onDragLeave={onDragLeave} + // onDragOver={onDragOver} + // onDrop={onDragOver} + // onDragLeave={onDragLeave} > - {registries.map((registry, rowIndex) => ( - - - - handlePathChange(rowIndex, value)} - /> - - - - - - - - - ))} + {registries.map((registry, rowIndex) => { + const selectedClusterName = + clusters.find((cluster) => registry.clusterId === cluster.id)?.name ?? + 'None'; + + return ( + + {/* */} + + handlePathChange(rowIndex, value)} + /> + + + + + + + + + ); + })} ); diff --git a/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/DelegatedScanningSettings.tsx b/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/DelegatedScanningSettings.tsx index c026f66b6d4bb..4be52e93daef1 100644 --- a/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/DelegatedScanningSettings.tsx +++ b/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/DelegatedScanningSettings.tsx @@ -1,32 +1,17 @@ import React from 'react'; -import { - Card, - CardBody, - Flex, - FlexItem, - Radio, - Select, - SelectOption, -} from '@patternfly/react-core'; +import { Card, CardBody, Flex, FlexItem, Select, SelectOption } from '@patternfly/react-core'; import FormLabelGroup from 'Components/PatternFly/FormLabelGroup'; -import { - EnabledSelections, - DelegatedRegistryCluster, -} from 'services/DelegatedRegistryConfigService'; +import { DelegatedRegistryCluster } from 'services/DelegatedRegistryConfigService'; import useSelectToggle from 'hooks/patternfly/useSelectToggle'; type DelegatedScanningSettingsProps = { - enabledFor: EnabledSelections; - onChangeEnabledFor: (newEnabledState: EnabledSelections) => void; clusters?: DelegatedRegistryCluster[]; selectedClusterId?: string; setSelectedClusterId: (newClusterId: string) => void; }; function DelegatedScanningSettings({ - enabledFor, - onChangeEnabledFor, clusters = [], selectedClusterId, setSelectedClusterId, @@ -48,45 +33,15 @@ function DelegatedScanningSettings({ setSelectedClusterId(value); }; + const selectedClusterName = + clusters.find((cluster) => selectedClusterId === cluster.id)?.name ?? 'None'; + return ( - - - - { - onChangeEnabledFor('ALL'); - }} - /> - - - { - onChangeEnabledFor('SPECIFIC'); - }} - /> - - - - {clusterSelectOptions} + + None + + <>{clusterSelectOptions} diff --git a/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/ToggleDelegatedScanning.tsx b/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/ToggleDelegatedScanning.tsx index 80a7c6a6b1cb6..97c050b51b7ff 100644 --- a/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/ToggleDelegatedScanning.tsx +++ b/ui/apps/platform/src/Containers/Clusters/DelegateScanning/Components/ToggleDelegatedScanning.tsx @@ -1,24 +1,60 @@ import React from 'react'; -import { Card, CardBody, Checkbox } from '@patternfly/react-core'; +import { Card, CardBody, Flex, FlexItem, Radio } from '@patternfly/react-core'; +import FormLabelGroup from 'Components/PatternFly/FormLabelGroup'; import { DelegatedRegistryConfigEnabledFor } from 'services/DelegatedRegistryConfigService'; type ToggleDelegatedScanningProps = { enabledFor: DelegatedRegistryConfigEnabledFor; - toggleDelegation: () => void; + onChangeEnabledFor: (newEnabledState: DelegatedRegistryConfigEnabledFor) => void; }; -function ToggleDelegatedScanning({ enabledFor, toggleDelegation }: ToggleDelegatedScanningProps) { +function ToggleDelegatedScanning({ enabledFor, onChangeEnabledFor }: ToggleDelegatedScanningProps) { return ( - + + + + { + onChangeEnabledFor('NONE'); + }} + /> + + + { + onChangeEnabledFor('ALL'); + }} + /> + + + { + onChangeEnabledFor('SPECIFIC'); + }} + /> + + + ); diff --git a/ui/apps/platform/src/Containers/Clusters/DelegateScanning/DelegateScanningPage.tsx b/ui/apps/platform/src/Containers/Clusters/DelegateScanning/DelegateScanningPage.tsx index 915d167d516b9..e81277d797a79 100644 --- a/ui/apps/platform/src/Containers/Clusters/DelegateScanning/DelegateScanningPage.tsx +++ b/ui/apps/platform/src/Containers/Clusters/DelegateScanning/DelegateScanningPage.tsx @@ -121,21 +121,6 @@ function DelegateScanningPage() { }); } - function toggleDelegation() { - const newState: DelegatedRegistryConfig = { ...delegatedRegistryConfig }; - - if (delegatedRegistryConfig.enabledFor === 'NONE') { - if (delegatedRegistryConfig.registries.length > 0) { - newState.enabledFor = 'SPECIFIC'; - } else { - newState.enabledFor = 'ALL'; - } - } else { - newState.enabledFor = 'NONE'; - } - setDedicatedRegistryConfig(newState); - } - function onChangeEnabledFor(newEnabledState) { const newState: DelegatedRegistryConfig = { ...delegatedRegistryConfig }; @@ -290,14 +275,12 @@ function DelegateScanningPage() {
{/* TODO: decide who to structure this form, where the `enabledFor` value spans multiple inputs */} {delegatedRegistryConfig.enabledFor !== 'NONE' && ( <> ; - // Note: // In order to make each row of registry/cluster exceptions work // with PatternFly's drag-and-drag Table variant