From a37c93c209392e6da143a1b9922001b18cc32e76 Mon Sep 17 00:00:00 2001 From: Eric Wittmann Date: Fri, 27 Aug 2021 10:53:38 -0400 Subject: [PATCH 1/2] Updates to the UI based on UX designs. Fixes #1762 --- ui/src/app/components/header/index.ts | 3 +- ui/src/app/components/header/pageheader.css | 0 ui/src/app/components/header/pageheader.tsx | 89 +++++++++++++++++++ .../pages/artifactVersion/artifactVersion.css | 6 +- .../pages/artifactVersion/artifactVersion.tsx | 21 +++-- .../components/pageheader/pageheader.css | 5 +- .../components/pageheader/pageheader.tsx | 7 +- .../artifactVersion/components/tabs/info.tsx | 18 +++- ui/src/app/pages/artifacts/artifacts.css | 6 +- ui/src/app/pages/artifacts/artifacts.tsx | 9 +- .../app/pages/artifacts/components/index.ts | 1 - .../artifacts/components/pageheader/index.ts | 18 ---- .../components/pageheader/pageheader.css | 6 -- .../components/pageheader/pageheader.tsx | 83 ----------------- .../artifacts/components/toolbar/toolbar.tsx | 11 ++- ui/src/app/pages/roles/components/index.ts | 1 - .../roles/components/pageheader/index.ts | 18 ---- .../components/pageheader/pageheader.tsx | 65 -------------- ui/src/app/pages/roles/roles.tsx | 18 +--- ui/src/app/pages/rules/components/index.ts | 1 - .../rules/components/pageheader/index.ts | 18 ---- .../components/pageheader/pageheader.tsx | 65 -------------- ui/src/app/pages/rules/rules.tsx | 8 +- ui/src/services/config/config.service.ts | 4 + 24 files changed, 161 insertions(+), 320 deletions(-) create mode 100644 ui/src/app/components/header/pageheader.css create mode 100644 ui/src/app/components/header/pageheader.tsx delete mode 100644 ui/src/app/pages/artifacts/components/pageheader/index.ts delete mode 100644 ui/src/app/pages/artifacts/components/pageheader/pageheader.css delete mode 100644 ui/src/app/pages/artifacts/components/pageheader/pageheader.tsx delete mode 100644 ui/src/app/pages/roles/components/pageheader/index.ts delete mode 100644 ui/src/app/pages/roles/components/pageheader/pageheader.tsx delete mode 100644 ui/src/app/pages/rules/components/pageheader/index.ts delete mode 100644 ui/src/app/pages/rules/components/pageheader/pageheader.tsx diff --git a/ui/src/app/components/header/index.ts b/ui/src/app/components/header/index.ts index d8eb13b5dd..021c5ed777 100644 --- a/ui/src/app/components/header/index.ts +++ b/ui/src/app/components/header/index.ts @@ -15,4 +15,5 @@ * limitations under the License. */ -export * from "./header"; \ No newline at end of file +export * from "./header"; +export * from "./pageheader"; diff --git a/ui/src/app/components/header/pageheader.css b/ui/src/app/components/header/pageheader.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ui/src/app/components/header/pageheader.tsx b/ui/src/app/components/header/pageheader.tsx new file mode 100644 index 0000000000..7270e46b1a --- /dev/null +++ b/ui/src/app/components/header/pageheader.tsx @@ -0,0 +1,89 @@ +/** + * @license + * Copyright 2021 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from "react"; +import {Tab, Tabs, TabTitleText} from '@patternfly/react-core'; +import "./pageheader.css"; +import {PureComponent, PureComponentProps, PureComponentState} from "../baseComponent"; +import {IfAuth, IfFeature} from "../common"; +import {Services} from "../../../services"; + + +/** + * Properties + */ +// tslint:disable-next-line:no-empty-interface +export interface RootPageHeaderProps extends PureComponentProps { + tabKey: number; +} + +/** + * State + */ +// tslint:disable-next-line:no-empty-interface +export interface RootPageHeaderState extends PureComponentState { +} + + +/** + * Models the page header for the Artifacts page. + */ +export class RootPageHeader extends PureComponent { + + constructor(props: Readonly) { + super(props); + } + + public render(): React.ReactElement { + let tabs: any[] = [ + Artifacts} />, + Global Rules} /> + ]; + if (Services.getConfigService().featureRoleManagement()) { + tabs.push( + Permissions} /> + ); + } + return ( +
+ + + +
+ ); + } + + protected initializeState(): RootPageHeaderState { + return {}; + } + + private handleTabClick = (event: React.MouseEvent, eventKey: number | string): void => { + if (eventKey != this.props.tabKey) { + if (eventKey == 0) { + // navigate to artifacts + this.navigateTo(this.linkTo("/artifacts"))(); + } + if (eventKey == 1) { + // navigate to global rules + this.navigateTo(this.linkTo("/rules"))(); + } + if (eventKey == 2) { + // navigate to permissions page + this.navigateTo(this.linkTo("/roles"))(); + } + } + } +} diff --git a/ui/src/app/pages/artifactVersion/artifactVersion.css b/ui/src/app/pages/artifactVersion/artifactVersion.css index b394217ccd..621fe19dc7 100644 --- a/ui/src/app/pages/artifactVersion/artifactVersion.css +++ b/ui/src/app/pages/artifactVersion/artifactVersion.css @@ -11,4 +11,8 @@ div.artifact-page-tabs > ul > li.pf-c-tabs__item.pf-m-current > button.pf-c-tabs flex-grow: 1; display: flex; flex-direction: column; -} \ No newline at end of file +} + +#artifact-page-tabs > ul > li:first-child { + margin-left: 20px; +} diff --git a/ui/src/app/pages/artifactVersion/artifactVersion.tsx b/ui/src/app/pages/artifactVersion/artifactVersion.tsx index b60a760f78..11554b6bab 100644 --- a/ui/src/app/pages/artifactVersion/artifactVersion.tsx +++ b/ui/src/app/pages/artifactVersion/artifactVersion.tsx @@ -17,14 +17,12 @@ import React from "react"; import "./artifactVersion.css"; import { - Breadcrumb, BreadcrumbItem, + Breadcrumb, + BreadcrumbItem, Button, - Flex, - FlexItem, Modal, PageSection, PageSectionVariants, - Spinner, Tab, Tabs } from '@patternfly/react-core'; @@ -140,8 +138,9 @@ export class ArtifactVersionPage extends PageComponent - - + void; @@ -66,7 +67,7 @@ export class ArtifactVersionPageHeader extends PureComponent - Artifact Details + { this.props.title } @@ -74,8 +75,8 @@ export class ArtifactVersionPageHeader extends PureComponent - - + + diff --git a/ui/src/app/pages/artifactVersion/components/tabs/info.tsx b/ui/src/app/pages/artifactVersion/components/tabs/info.tsx index 5f01c85115..2b28290bc7 100644 --- a/ui/src/app/pages/artifactVersion/components/tabs/info.tsx +++ b/ui/src/app/pages/artifactVersion/components/tabs/info.tsx @@ -69,7 +69,7 @@ export class InfoTabContent extends PureComponent - {this.nameOrId()} + Version Metadata @@ -83,8 +83,11 @@ export class InfoTabContent extends PureComponent -
{this.description()}
+
+ Name + {this.props.artifact.name} +
Group @@ -107,7 +110,16 @@ export class InfoTabContent extends PureComponentModified
+
+ Global ID + {this.props.artifact.globalId} +
+
+ Content ID + {this.props.artifact.contentId} +
+
{this.description()}
{ this.labels().map( label => @@ -120,7 +132,7 @@ export class InfoTabContent extends PureComponent Download + variant="secondary"> Download
diff --git a/ui/src/app/pages/artifacts/artifacts.css b/ui/src/app/pages/artifacts/artifacts.css index 580a78b118..5c94fa51e8 100644 --- a/ui/src/app/pages/artifacts/artifacts.css +++ b/ui/src/app/pages/artifacts/artifacts.css @@ -1,8 +1,4 @@ -.ps_artifacts-header { - border-bottom: 1px solid #ddd; -} - .upload-artifact-modal .pf-c-modal-box__body { overflow-x: initial; overflow-y: visible; -} \ No newline at end of file +} diff --git a/ui/src/app/pages/artifacts/artifacts.tsx b/ui/src/app/pages/artifacts/artifacts.tsx index 53ff24fd9d..cb07fe5767 100644 --- a/ui/src/app/pages/artifacts/artifacts.tsx +++ b/ui/src/app/pages/artifacts/artifacts.tsx @@ -17,8 +17,7 @@ import React from "react"; import "./artifacts.css"; -import {Button, Flex, FlexItem, Modal, PageSection, PageSectionVariants, Spinner} from '@patternfly/react-core'; -import {ArtifactsPageHeader} from "./components/pageheader"; +import {Button, Modal, PageSection, PageSectionVariants} from '@patternfly/react-core'; import {ArtifactList} from "./components/artifactList"; import {PageComponent, PageProps, PageState} from "../basePage"; import {ArtifactsPageToolbar} from "./components/toolbar"; @@ -29,6 +28,7 @@ import {If} from "../../components/common/if"; import {ArtifactsSearchResults, CreateArtifactData, GetArtifactsCriteria, Paging, Services} from "../../../services"; import {SearchedArtifact} from "../../../models"; import {PleaseWaitModal} from "../../components/modals/pleaseWaitModal"; +import {RootPageHeader} from "../../components"; /** @@ -66,8 +66,8 @@ export class ArtifactsPage extends PageComponent - - + + @@ -75,6 +75,7 @@ export class ArtifactsPage extends PageComponent diff --git a/ui/src/app/pages/artifacts/components/index.ts b/ui/src/app/pages/artifacts/components/index.ts index f3f5186775..e8a20b1af8 100644 --- a/ui/src/app/pages/artifacts/components/index.ts +++ b/ui/src/app/pages/artifacts/components/index.ts @@ -17,6 +17,5 @@ export * from "./artifactList"; export * from "./empty"; -export * from "./pageheader"; export * from "./toolbar"; export * from "./uploadForm"; diff --git a/ui/src/app/pages/artifacts/components/pageheader/index.ts b/ui/src/app/pages/artifacts/components/pageheader/index.ts deleted file mode 100644 index 3fab6bc897..0000000000 --- a/ui/src/app/pages/artifacts/components/pageheader/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @license - * Copyright 2020 JBoss Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export * from "./pageheader" \ No newline at end of file diff --git a/ui/src/app/pages/artifacts/components/pageheader/pageheader.css b/ui/src/app/pages/artifacts/components/pageheader/pageheader.css deleted file mode 100644 index 5a1c6d2f7c..0000000000 --- a/ui/src/app/pages/artifacts/components/pageheader/pageheader.css +++ /dev/null @@ -1,6 +0,0 @@ -.btn-header-global-rules { - margin-left: 15px; -} -.btn-header-upload-artifact { - margin-left: 15px; -} diff --git a/ui/src/app/pages/artifacts/components/pageheader/pageheader.tsx b/ui/src/app/pages/artifacts/components/pageheader/pageheader.tsx deleted file mode 100644 index ce51180726..0000000000 --- a/ui/src/app/pages/artifacts/components/pageheader/pageheader.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @license - * Copyright 2020 JBoss Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import React from "react"; -import {Button, Flex, FlexItem, Text, TextContent, TextVariants} from '@patternfly/react-core'; -import {IfAuth, PureComponent, PureComponentProps, PureComponentState} from "../../../../components"; -import {IfFeature} from "../../../../components/common/ifFeature"; -import {Link} from "react-router-dom"; -import "./pageheader.css"; - - -/** - * Properties - */ -// tslint:disable-next-line:no-empty-interface -export interface ArtifactsPageHeaderProps extends PureComponentProps { - onUploadArtifact: () => void; -} - -/** - * State - */ -// tslint:disable-next-line:no-empty-interface -export interface ArtifactsPageHeaderState extends PureComponentState { -} - - -/** - * Models the page header for the Artifacts page. - */ -export class ArtifactsPageHeader extends PureComponent { - - constructor(props: Readonly) { - super(props); - } - - public render(): React.ReactElement { - return ( - - - - Artifacts - - - - - - - Manage access - - Manage global rules - - - - - - - - - - ); - } - - protected initializeState(): ArtifactsPageHeaderState { - return {}; - } -} diff --git a/ui/src/app/pages/artifacts/components/toolbar/toolbar.tsx b/ui/src/app/pages/artifacts/components/toolbar/toolbar.tsx index 98b21b3daf..b758bf92df 100644 --- a/ui/src/app/pages/artifacts/components/toolbar/toolbar.tsx +++ b/ui/src/app/pages/artifacts/components/toolbar/toolbar.tsx @@ -31,7 +31,7 @@ import { ToolbarItem } from '@patternfly/react-core'; import {SearchIcon, SortAlphaDownAltIcon, SortAlphaDownIcon} from "@patternfly/react-icons"; -import {PureComponent, PureComponentProps, PureComponentState} from "../../../../components"; +import {IfAuth, IfFeature, PureComponent, PureComponentProps, PureComponentState} from "../../../../components"; import {OnPerPageSelect, OnSetPage} from "@patternfly/react-core/dist/js/components/Pagination/Pagination"; import {ArtifactsSearchResults, GetArtifactsCriteria, Paging, Services} from "../../../../../services"; @@ -44,6 +44,7 @@ export interface ArtifactsPageToolbarProps extends PureComponentProps { paging: Paging; onPerPageSelect: OnPerPageSelect; onSetPage: OnSetPage; + onUploadArtifact: () => void; } /** @@ -105,6 +106,14 @@ export class ArtifactsPageToolbar extends PureComponent + + + + + + + { - - constructor(props: Readonly) { - super(props); - } - - public render(): React.ReactElement { - return ( - - - - Role Mappings - - - - Back to artifacts - - - ); - } - - protected initializeState(): RolesPageHeaderState { - return {}; - } -} diff --git a/ui/src/app/pages/roles/roles.tsx b/ui/src/app/pages/roles/roles.tsx index 7d03567601..9dd198c2d9 100644 --- a/ui/src/app/pages/roles/roles.tsx +++ b/ui/src/app/pages/roles/roles.tsx @@ -17,22 +17,12 @@ import React from "react"; import "./roles.css"; -import { - Button, - Flex, - FlexItem, - Modal, - PageSection, - PageSectionVariants, - Spinner, - TextContent -} from '@patternfly/react-core'; +import {Button, Flex, FlexItem, PageSection, PageSectionVariants, TextContent} from '@patternfly/react-core'; import {PageComponent, PageProps, PageState} from "../basePage"; -import {RolesPageHeader} from "./components/pageheader"; import {RoleMapping} from "../../../models"; import {Services} from "../../../services"; import {GrantAccessModal, RoleList, RoleMappingsEmptyState} from "./components"; -import {PleaseWaitModal} from "../../components"; +import {PleaseWaitModal, RootPageHeader} from "../../components"; /** @@ -66,8 +56,8 @@ export class RolesPage extends PageComponent { public renderPage(): React.ReactElement { return ( - - + + diff --git a/ui/src/app/pages/rules/components/index.ts b/ui/src/app/pages/rules/components/index.ts index c0183f1988..23950df202 100644 --- a/ui/src/app/pages/rules/components/index.ts +++ b/ui/src/app/pages/rules/components/index.ts @@ -15,4 +15,3 @@ * limitations under the License. */ -export * from "./pageheader"; diff --git a/ui/src/app/pages/rules/components/pageheader/index.ts b/ui/src/app/pages/rules/components/pageheader/index.ts deleted file mode 100644 index ab1672a669..0000000000 --- a/ui/src/app/pages/rules/components/pageheader/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @license - * Copyright 2020 JBoss Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export * from "./pageheader"; \ No newline at end of file diff --git a/ui/src/app/pages/rules/components/pageheader/pageheader.tsx b/ui/src/app/pages/rules/components/pageheader/pageheader.tsx deleted file mode 100644 index a1a05c0966..0000000000 --- a/ui/src/app/pages/rules/components/pageheader/pageheader.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @license - * Copyright 2020 JBoss Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import React from "react"; -import {Flex, FlexItem, Text, TextContent, TextVariants} from '@patternfly/react-core'; -import {PureComponent, PureComponentProps, PureComponentState} from "../../../../components"; -import {Link} from "react-router-dom"; - - -/** - * Properties - */ -// tslint:disable-next-line:no-empty-interface -export interface RulesPageHeaderProps extends PureComponentProps { -} - -/** - * State - */ -// tslint:disable-next-line:no-empty-interface -export interface RulesPageHeaderState extends PureComponentState { -} - - -/** - * Models the page header for the Artifacts page. - */ -export class RulesPageHeader extends PureComponent { - - constructor(props: Readonly) { - super(props); - } - - public render(): React.ReactElement { - return ( - - - - Global Rules - - - - Back to artifacts - - - ); - } - - protected initializeState(): RulesPageHeaderState { - return {}; - } -} diff --git a/ui/src/app/pages/rules/rules.tsx b/ui/src/app/pages/rules/rules.tsx index 9bb07bb2d1..18fb98b0ec 100644 --- a/ui/src/app/pages/rules/rules.tsx +++ b/ui/src/app/pages/rules/rules.tsx @@ -17,12 +17,12 @@ import React from "react"; import "./rules.css"; -import {Flex, FlexItem, PageSection, PageSectionVariants, Spinner, TextContent} from '@patternfly/react-core'; +import {PageSection, PageSectionVariants, TextContent} from '@patternfly/react-core'; import {PageComponent, PageProps, PageState} from "../basePage"; -import {RulesPageHeader} from "./components/pageheader"; import {RuleList} from "../../components/ruleList"; import {Rule} from "../../../models"; import {Services} from "../../../services"; +import {RootPageHeader} from "../../components"; /** @@ -53,8 +53,8 @@ export class RulesPage extends PageComponent { public renderPage(): React.ReactElement { return ( - - + + diff --git a/ui/src/services/config/config.service.ts b/ui/src/services/config/config.service.ts index f05c4eb0d6..5eea7cccf0 100644 --- a/ui/src/services/config/config.service.ts +++ b/ui/src/services/config/config.service.ts @@ -116,6 +116,10 @@ export class ConfigService implements Service { return this.features().breadcrumbs || false; } + public featureRoleManagement(): boolean { + return this.features().roleManagement || false; + } + public authType(): string { if (!this.config.auth || !this.config.auth.type) { return ""; From 2d16157fd47844a64ad5b24136e98383f7864037 Mon Sep 17 00:00:00 2001 From: Fabian Martinez Date: Fri, 3 Sep 2021 16:04:00 +0200 Subject: [PATCH 2/2] fix selenium tests --- .../apicurio/tests/ui/RegistryUITester.java | 6 +++++- .../tests/ui/pages/ArtifactsListPage.java | 20 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/integration-tests/testsuite/src/test/java/io/apicurio/tests/ui/RegistryUITester.java b/integration-tests/testsuite/src/test/java/io/apicurio/tests/ui/RegistryUITester.java index 839ecc8ba4..9377558b51 100644 --- a/integration-tests/testsuite/src/test/java/io/apicurio/tests/ui/RegistryUITester.java +++ b/integration-tests/testsuite/src/test/java/io/apicurio/tests/ui/RegistryUITester.java @@ -90,7 +90,11 @@ public String uploadArtifact(String groupId, String artifactId, ArtifactType typ } public UploadArtifactDialog openUploadArtifactDialog() { - selenium.clickOnItem(artifactsListPage.getUploadArtifactOpenDialogButton()); + var btn = artifactsListPage.getEmptyUploadArtifactOpenDialogButton(); + if (btn == null) { + btn = artifactsListPage.getTopUploadArtifactOpenDialogButton(); + } + selenium.clickOnItem(btn); return artifactsListPage.getUploadArtifactDialogPage(); } diff --git a/integration-tests/testsuite/src/test/java/io/apicurio/tests/ui/pages/ArtifactsListPage.java b/integration-tests/testsuite/src/test/java/io/apicurio/tests/ui/pages/ArtifactsListPage.java index 8742b1f632..b1076487cc 100644 --- a/integration-tests/testsuite/src/test/java/io/apicurio/tests/ui/pages/ArtifactsListPage.java +++ b/integration-tests/testsuite/src/test/java/io/apicurio/tests/ui/pages/ArtifactsListPage.java @@ -45,10 +45,26 @@ public ArtifactsListPage(SeleniumProvider selenium) { public void verifyIsOpen() throws Exception { selenium.getDriverWait().withTimeout(Duration.ofSeconds(30)).until(ExpectedConditions.and( ExpectedConditions.urlContains("/ui/artifacts"))); - assertNotNull(selenium.getWebElement(() -> getUploadArtifactOpenDialogButton())); + assertNotNull(selenium.getWebElement(() -> getArtifactsTab())); } - public WebElement getUploadArtifactOpenDialogButton() { + public WebElement getArtifactsTab() { + var tabs = selenium.getDriver().findElements(By.className("pf-c-tabs__item-text")); + if (tabs == null) { + return null; + } + return tabs.stream().filter(we -> we.getText().equals("Artifacts")).findFirst().orElse(null); + } + + public WebElement getEmptyUploadArtifactOpenDialogButton() { + try { + return selenium.getDriver().findElement(byDataTestId("empty-btn-upload")); + } catch (NoSuchElementException e) { + return null; + } + } + + public WebElement getTopUploadArtifactOpenDialogButton() { return selenium.getDriver().findElement(byDataTestId("btn-header-upload-artifact")); }