+
diff --git a/src/components/hub-select.tsx b/src/components/hub-select.tsx
new file mode 100644
index 0000000000..725587d886
--- /dev/null
+++ b/src/components/hub-select.tsx
@@ -0,0 +1,50 @@
+import {
+ MenuToggle,
+ type MenuToggleElement,
+ Select,
+ SelectOption,
+} from '@patternfly/react-core';
+import React, { type Ref, useState } from 'react';
+
+// single select component - render options object in order, onSelect(option key), selected=option key
+export const HubSelect = ({
+ onSelect,
+ options,
+ selected,
+}: {
+ onSelect: (value) => void;
+ options: Record;
+ selected: string;
+}) => {
+ const [isOpen, setOpen] = useState(false);
+
+ const toggle = (toggleRef: Ref) => (
+ setOpen(!isOpen)}
+ ref={toggleRef}
+ >
+ {options[selected]}
+
+ );
+
+ return (
+
+ );
+};
diff --git a/src/components/index.ts b/src/components/index.ts
index 3b07723c0b..67ca5d622e 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -49,6 +49,7 @@ export { HubAboutModal } from './hub-about-modal';
export { HubCopyButton } from './hub-copy-button';
export { HubListToolbar } from './hub-list-toolbar';
export { HubPagination } from './hub-pagination';
+export { HubSelect } from './hub-select';
export { ImportConsole } from './import-console';
export { ImportList } from './import-list';
export { ImportModal } from './import-modal';
diff --git a/src/components/typeahead.tsx b/src/components/typeahead.tsx
index f854f1ea49..4798fc17b9 100644
--- a/src/components/typeahead.tsx
+++ b/src/components/typeahead.tsx
@@ -1,121 +1,192 @@
import { t } from '@lingui/macro';
import {
+ Button,
+ MenuToggle,
+ type MenuToggleElement,
Select,
+ SelectList,
SelectOption,
- SelectVariant,
-} from '@patternfly/react-core/deprecated';
-import React, { type CSSProperties, Component, type ReactElement } from 'react';
+ TextInputGroup,
+ TextInputGroupMain,
+ TextInputGroupUtilities,
+} from '@patternfly/react-core';
+import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
+import React, {
+ type CSSProperties,
+ type ReactElement,
+ type Ref,
+ useState,
+} from 'react';
+import { Chip, ChipGroup } from 'src/components';
interface IProps {
- results: { name: string; id: number | string }[];
+ isDisabled?: boolean;
loadResults: (filter: string) => void;
- onSelect: (event, selection, isPlaceholder) => void;
-
- selections?: { name: string; id: number | string }[];
+ menuAppendTo?: 'parent' | 'inline';
multiple?: boolean;
- placeholderText?: string;
onClear?: () => void;
-
- isDisabled?: boolean;
- endLink?: {
- href: string;
- name: string;
- };
- menuAppendTo?: 'parent' | 'inline';
- toggleIcon?: ReactElement;
+ onSelect: (event, selection, isPlaceholder) => void;
+ placeholderText?: string;
+ results: { name: string; id: number | string }[];
+ selections?: { name: string; id: number | string }[];
style?: CSSProperties;
+ toggleIcon?: ReactElement;
}
-interface IState {
- isOpen: boolean;
-}
-
-export class Typeahead extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- isOpen: false,
- };
- }
-
- render() {
- let selected = null;
- if (this.props.selections) {
- selected = this.props.selections.map((group) => group.name);
- }
-
- const { isOpen } = this.state;
- const variant = this.props.multiple
- ? SelectVariant.typeaheadMulti
- : SelectVariant.typeahead;
+export const Typeahead = ({
+ isDisabled,
+ loadResults,
+ menuAppendTo,
+ multiple,
+ onClear,
+ onSelect,
+ placeholderText,
+ results,
+ selections,
+ style,
+ toggleIcon,
+}: IProps) => {
+ const [isOpen, setOpen] = useState(false);
+ const selected = selections?.map((group) => group.name) || null;
+
+ const toggle = (toggleRef: Ref) => {
+ const isEmpty = multiple ? !selected.length : !inputValue;
return (
-
+
+
+ {multiple ? (
+
+ {selected.map((selection, index) => (
+ {
+ ev.stopPropagation();
+ onSelect(selection);
+ }}
+ >
+ {selection}
+
+ ))}
+
+ ) : null}
+
+
+ {!isEmpty ? (
+
+ ) : null}
+
+
+
);
- }
-
- private onClear = () => {
- this.props.loadResults('');
- if (this.props.onClear) {
- this.props.onClear();
- }
- };
-
- private getOptions() {
- const options = this.props.results.map(({ id, name }) => (
-
- ));
-
- if (options.length === 0) {
- options.push(
- ,
- );
- }
-
- return options;
- }
-
- private onFilter = (evt) => {
- if (evt !== null) {
- const textInput = evt.target.value;
- this.props.loadResults(textInput);
- }
- return this.getOptions();
- };
-
- private onToggle = (isOpen) => {
- this.setState({
- isOpen,
- });
};
- private onSelect = (event, selection, isPlaceholder) => {
- this.props.onSelect(event, selection, isPlaceholder);
-
- if (!this.props.multiple) {
- this.setState(
- {
- isOpen: false,
- },
- () => this.props.loadResults(''),
- );
- }
- };
-}
+ return (
+
+ );
+
+ return (
+
+ );
+};
diff --git a/src/containers/ansible-role/imports.tsx b/src/containers/ansible-role/imports.tsx
index 4104cc2fca..f9f3139ba5 100644
--- a/src/containers/ansible-role/imports.tsx
+++ b/src/containers/ansible-role/imports.tsx
@@ -158,7 +158,7 @@ class AnsibleRoleImports extends Component {
{
});
cy.galaxykit('-i task wait all');
range(1, max).forEach((i) => {
- cy.galaxykit(`-i repository create`, 'repo' + i, '--pipeline=approved');
+ cy.galaxykit('-i repository create', 'repo' + i, '--pipeline=approved');
cy.galaxykit('-i distribution create', 'repo' + i);
});
cy.galaxykit('-i task wait all');
diff --git a/test/cypress/e2e/approval-modal/approval-multiple-repos.js b/test/cypress/e2e/approval-modal/approval-multiple-repos.js
index c4af2548f3..6db400a8de 100644
--- a/test/cypress/e2e/approval-modal/approval-multiple-repos.js
+++ b/test/cypress/e2e/approval-modal/approval-multiple-repos.js
@@ -41,7 +41,7 @@ function rejectItem(repo) {
cy.visit(`${uiPrefix}approval-dashboard`);
cy.contains('Clear all filters').click();
cy.contains(
- `[data-cy="ApprovalRow-rejected-namespace-collection1"]`,
+ '[data-cy="ApprovalRow-rejected-namespace-collection1"]',
'Rejected',
);
}
@@ -82,7 +82,7 @@ describe('Approval Dashboard process with multiple repos', () => {
});
cy.galaxykit('-i task wait all');
range(1, max).forEach((i) => {
- cy.galaxykit(`-i repository create`, 'repo' + i, '--pipeline=approved');
+ cy.galaxykit('-i repository create', 'repo' + i, '--pipeline=approved');
cy.galaxykit('-i distribution create', 'repo' + i);
});
cy.galaxykit('-i task wait all');
diff --git a/test/cypress/e2e/collections/collection.js b/test/cypress/e2e/collections/collection.js
index c19a984a63..3042414cde 100644
--- a/test/cypress/e2e/collections/collection.js
+++ b/test/cypress/e2e/collections/collection.js
@@ -175,13 +175,13 @@ describe('collection tests', () => {
cy.visit(
`${uiPrefix}repo/repo2/test_namespace/test_repo_collection_version2/?version=1.0.0`,
);
- cy.contains(`We couldn't find the page you're looking for!`);
+ cy.contains("We couldn't find the page you're looking for!");
cy.visit(
`${uiPrefix}repo/published/test_namespace/test_repo_collection_version2/?version=1.0.0`,
);
cy.contains('test_repo_collection_version2');
- cy.contains(`We couldn't find the page you're looking for!`).should(
+ cy.contains("We couldn't find the page you're looking for!").should(
'not.exist',
);
diff --git a/test/cypress/e2e/namespaces/group-roles.js b/test/cypress/e2e/namespaces/group-roles.js
index 683399df2c..cdcb931b36 100644
--- a/test/cypress/e2e/namespaces/group-roles.js
+++ b/test/cypress/e2e/namespaces/group-roles.js
@@ -175,7 +175,7 @@ describe('Group Roles Tests', () => {
it('should show group empty state', () => {
cy.galaxykit('-i group create', 'empty_group');
cy.menuGo('User Access > Groups');
- cy.get(`[data-cy="GroupList-row-empty_group"] a`).click();
+ cy.get('[data-cy="GroupList-row-empty_group"] a').click();
cy.contains('There are currently no roles assigned to this group.');
});
});
diff --git a/test/cypress/e2e/namespaces/rbac-access.js b/test/cypress/e2e/namespaces/rbac-access.js
index ec1539ed41..1d03b47b9d 100644
--- a/test/cypress/e2e/namespaces/rbac-access.js
+++ b/test/cypress/e2e/namespaces/rbac-access.js
@@ -8,7 +8,7 @@ describe('Namespace Access tab', () => {
cy.deleteTestGroups();
cy.galaxykit(`-i namespace create rbac_access_${num}`);
- cy.galaxykit('-i group create', `access_group`);
+ cy.galaxykit('-i group create', 'access_group');
});
beforeEach(() => {
@@ -49,7 +49,7 @@ describe('Execution Environment Access tab', () => {
'library/alpine',
`rbac_access_${num}_registry`,
);
- cy.galaxykit('-i group create', `access_group`);
+ cy.galaxykit('-i group create', 'access_group');
});
beforeEach(() => {
diff --git a/test/cypress/e2e/namespaces/rbac-create.js b/test/cypress/e2e/namespaces/rbac-create.js
index be6a47f853..e2fb42b6a8 100644
--- a/test/cypress/e2e/namespaces/rbac-create.js
+++ b/test/cypress/e2e/namespaces/rbac-create.js
@@ -33,7 +33,7 @@ describe('add and delete roles', () => {
cy.get('#role_name').clear().type('test');
helperText('role_name').should(
'have.text',
- `This field must start with 'galaxy.'.`,
+ "This field must start with 'galaxy.'.",
);
cy.get('#role_name').clear();
diff --git a/test/cypress/e2e/namespaces/rbac.js b/test/cypress/e2e/namespaces/rbac.js
index 97ba185a3e..18730f6d07 100644
--- a/test/cypress/e2e/namespaces/rbac.js
+++ b/test/cypress/e2e/namespaces/rbac.js
@@ -17,9 +17,9 @@ describe('RBAC test for user without permissions', () => {
cy.galaxykit(
'-i container create',
- `testcontainer`,
+ 'testcontainer',
'library/alpine',
- `docker`,
+ 'docker',
);
cy.galaxykit('-i user create', userName, userPassword);
@@ -222,9 +222,9 @@ describe('RBAC test for user with permissions', () => {
'https://registry.hub.docker.com/',
);
cy.addRemoteContainer({
- name: `testcontainer`,
+ name: 'testcontainer',
upstream_name: 'library/alpine',
- registry: `docker`,
+ registry: 'docker',
include_tags: 'latest',
});
diff --git a/test/cypress/e2e/namespaces/user-dashboard.js b/test/cypress/e2e/namespaces/user-dashboard.js
index 25712e70c1..dec7159db0 100644
--- a/test/cypress/e2e/namespaces/user-dashboard.js
+++ b/test/cypress/e2e/namespaces/user-dashboard.js
@@ -4,9 +4,9 @@ describe('Hub User Management Tests', () => {
cy.login();
cy.menuGo('User Access > Users');
- const actionsSelector = `[data-cy="UserList-row-admin"] [aria-label="Actions"]`;
- cy.get(actionsSelector).click();
- cy.containsnear(actionsSelector, 'Delete').click();
+ const kebab = '[data-cy="UserList-row-admin"] [aria-label="Actions"]';
+ cy.get(kebab).click();
+ cy.containsnear(kebab, 'Delete').click();
cy.get('button').contains('Delete').should('be.disabled');
cy.get('button').contains('Cancel').click();
});
diff --git a/test/cypress/e2e/repo/container-signing.js b/test/cypress/e2e/repo/container-signing.js
index ce451a2b24..1fcb3351e7 100644
--- a/test/cypress/e2e/repo/container-signing.js
+++ b/test/cypress/e2e/repo/container-signing.js
@@ -19,7 +19,7 @@ describe('Container Signing', () => {
cy.galaxykit(
'registry create',
- `docker`,
+ 'docker',
'https://registry.hub.docker.com/',
);