diff --git a/ui/.scripts/generate-version.cjs b/ui/.scripts/generate-version.cjs
index d9261b04f2..4fa4bc2e34 100755
--- a/ui/.scripts/generate-version.cjs
+++ b/ui/.scripts/generate-version.cjs
@@ -1,7 +1,13 @@
#! /usr/bin/env node
+var shell = require("shelljs");
const fs = require("fs");
const packageJson = require('../package.json');
+console.info("-------------------------------------------------------");
+console.info("Getting current git SHA");
+const gitSHA = shell.exec("git rev-parse HEAD", { silent: true }).stdout.trim();
+console.info(` SHA: ${gitSHA}`);
+console.info("-------------------------------------------------------");
console.info("-------------------------------------------------------");
console.info("Generating version.js");
@@ -14,6 +20,7 @@ const VERSION_OUTPUT_PATH="./ui-app/dist/version.js";
const info = {
name: "Apicurio Registry",
version: packageJson.version,
+ digest: gitSHA,
builtOn: new Date(),
url: "https://www.apicur.io/registry/"
};
diff --git a/ui/ui-app/config/version.js b/ui/ui-app/config/version.js
index 57566edb83..e3f5fa00b6 100644
--- a/ui/ui-app/config/version.js
+++ b/ui/ui-app/config/version.js
@@ -2,6 +2,6 @@ var ApicurioInfo = {
name: "Apicurio Registry",
version: "DEV",
digest: "DEV",
- builtOn: new Date(),
- url: "http://www.apicur.io/"
+ builtOn: new Date().toString(),
+ url: "http://www.apicur.io/registry"
};
diff --git a/ui/ui-app/public/apicurio_registry_icon_reverse.svg b/ui/ui-app/public/apicurio_registry_icon_reverse.svg
new file mode 100644
index 0000000000..8b71dfadbf
--- /dev/null
+++ b/ui/ui-app/public/apicurio_registry_icon_reverse.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/ui/ui-app/src/app/components/common/IfAuth.tsx b/ui/ui-app/src/app/components/auth/IfAuth.tsx
similarity index 97%
rename from ui/ui-app/src/app/components/common/IfAuth.tsx
rename to ui/ui-app/src/app/components/auth/IfAuth.tsx
index cd8b7ae706..4cce23c3fb 100644
--- a/ui/ui-app/src/app/components/common/IfAuth.tsx
+++ b/ui/ui-app/src/app/components/auth/IfAuth.tsx
@@ -1,5 +1,5 @@
import React, { FunctionComponent } from "react";
-import { Services } from "@services/services";
+import { Services } from "@services/services.ts";
import { AuthService } from "@services/auth";
/**
diff --git a/ui/ui-app/src/app/components/auth/index.ts b/ui/ui-app/src/app/components/auth/index.ts
index c1d98f3156..19af110ed9 100644
--- a/ui/ui-app/src/app/components/auth/index.ts
+++ b/ui/ui-app/src/app/components/auth/index.ts
@@ -1 +1,2 @@
export * from "./ApplicationAuth.tsx";
+export * from "./IfAuth.tsx";
diff --git a/ui/ui-app/src/app/components/common/index.ts b/ui/ui-app/src/app/components/common/index.ts
index c2b7e6fe04..d3c98f6c36 100644
--- a/ui/ui-app/src/app/components/common/index.ts
+++ b/ui/ui-app/src/app/components/common/index.ts
@@ -1,6 +1,5 @@
export * from "./ArtifactTypeIcon.tsx";
export * from "./If.tsx";
-export * from "./IfAuth.tsx";
export * from "./IfFeature.tsx";
export * from "./IfNotEmpty.tsx";
export * from "./UrlUpload.tsx";
diff --git a/ui/ui-app/src/app/components/header/AppAboutModal.tsx b/ui/ui-app/src/app/components/header/AppAboutModal.tsx
new file mode 100644
index 0000000000..b7ded7b1a1
--- /dev/null
+++ b/ui/ui-app/src/app/components/header/AppAboutModal.tsx
@@ -0,0 +1,42 @@
+import { FunctionComponent } from "react";
+import { AboutModal, TextContent, TextList, TextListItem } from "@patternfly/react-core";
+import { VersionType } from "@services/version";
+import { Services } from "@services/services.ts";
+
+
+export type AppAboutModalProps = {
+ isOpen: boolean;
+ onClose: () => void;
+};
+
+
+export const AppAboutModal: FunctionComponent = (props: AppAboutModalProps) => {
+ const version: VersionType = Services.getVersionService().getVersion();
+
+ return (
+
+
+
+ Project
+ { version.name }
+
+ Version
+ { version.version }
+
+ Built on
+ { "" + version.builtOn }
+
+ Digest
+ { version.digest }
+
+
+
+ );
+};
diff --git a/ui/ui-app/src/app/components/header/AppHeader.css b/ui/ui-app/src/app/components/header/AppHeader.css
deleted file mode 100644
index 16e13d1b04..0000000000
--- a/ui/ui-app/src/app/components/header/AppHeader.css
+++ /dev/null
@@ -1,8 +0,0 @@
-.header-toolbar {
-}
-
-.app-logo {
- display: flex;
- width: 350px;
- height: 46px;
-}
diff --git a/ui/ui-app/src/app/components/header/AppHeader.tsx b/ui/ui-app/src/app/components/header/AppHeader.tsx
index 92509cf472..069c6edede 100644
--- a/ui/ui-app/src/app/components/header/AppHeader.tsx
+++ b/ui/ui-app/src/app/components/header/AppHeader.tsx
@@ -1,13 +1,8 @@
-import React, { FunctionComponent } from "react";
-import "./AppHeader.css";
-import { AvatarDropdown, IfAuth } from "@app/components";
-import {
- PageHeader,
- PageHeaderTools,
- PageHeaderToolsGroup,
- PageHeaderToolsItem
-} from "@patternfly/react-core/deprecated";
+import { FunctionComponent } from "react";
+import { Brand, Masthead, MastheadBrand, MastheadContent, MastheadMain } from "@patternfly/react-core";
import { AppNavigation, useAppNavigation } from "@hooks/useAppNavigation.ts";
+import { Link } from "react-router-dom";
+import { AppHeaderToolbar } from "@app/components";
export type AppHeaderProps = {
@@ -18,30 +13,16 @@ export type AppHeaderProps = {
export const AppHeader: FunctionComponent = () => {
const appNavigation: AppNavigation = useAppNavigation();
- const logoProps = {
- href: appNavigation.createLink("/")
- };
-
- const logo: React.ReactNode = (
-
-
-
- );
-
- const headerActions: React.ReactElement = (
-
-
-
-
-
-
-
-
-
- );
-
return (
-
+
+
+ }>
+
+
+
+
+
+
+
);
-
};
diff --git a/ui/ui-app/src/app/components/header/AppHeaderToolbar.tsx b/ui/ui-app/src/app/components/header/AppHeaderToolbar.tsx
new file mode 100644
index 0000000000..1bbfa8d03e
--- /dev/null
+++ b/ui/ui-app/src/app/components/header/AppHeaderToolbar.tsx
@@ -0,0 +1,38 @@
+import { FunctionComponent, useState } from "react";
+import { Button, Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem } from "@patternfly/react-core";
+import { QuestionCircleIcon } from "@patternfly/react-icons";
+import { AvatarDropdown, IfAuth } from "@app/components";
+import { AppAboutModal } from "@app/components/header/AppAboutModal.tsx";
+
+
+export type AppHeaderToolbarProps = {
+ // No properties.
+};
+
+
+export const AppHeaderToolbar: FunctionComponent = () => {
+ const [isAboutModalOpen, setIsAboutModalOpen] = useState(false);
+
+ return (
+ <>
+ setIsAboutModalOpen(false)} />
+
+ >
+ );
+
+};
diff --git a/ui/ui-app/src/app/components/header/AvatarDropdown.css b/ui/ui-app/src/app/components/header/AvatarDropdown.css
deleted file mode 100644
index 4d5e05969c..0000000000
--- a/ui/ui-app/src/app/components/header/AvatarDropdown.css
+++ /dev/null
@@ -1,15 +0,0 @@
-#avatar-dropdown {
- margin-left: 15px;
-}
-
-#avatar-dropdown .pf-c-dropdown__toggle-icon {
- margin-left: 5px;
-}
-
-#avatar-dropdown .avatar-logout-link {
- color: rgb(21, 21, 21);
-}
-#avatar-dropdown .avatar-logout-link:hover {
- border-bottom: none;
- text-decoration: none;
-}
diff --git a/ui/ui-app/src/app/components/header/AvatarDropdown.tsx b/ui/ui-app/src/app/components/header/AvatarDropdown.tsx
index 4891d1c299..efe9c2502c 100644
--- a/ui/ui-app/src/app/components/header/AvatarDropdown.tsx
+++ b/ui/ui-app/src/app/components/header/AvatarDropdown.tsx
@@ -1,13 +1,5 @@
import React, { FunctionComponent, useState } from "react";
-import "./AvatarDropdown.css";
-import {
- Avatar,
- Dropdown,
- DropdownItem,
- DropdownList,
- MenuToggle,
- MenuToggleElement
-} from "@patternfly/react-core";
+import { Avatar, Dropdown, DropdownItem, DropdownList, MenuToggle, MenuToggleElement } from "@patternfly/react-core";
import { Services } from "@services/services.ts";
@@ -27,23 +19,26 @@ export const AvatarDropdown: FunctionComponent = () => {
setIsOpen(!isOpen);
};
+ const icon = (
+
+ );
+
return (
setIsOpen(isOpen)}
- popperProps={{
- position: "right"
- }}
toggle={(toggleRef: React.Ref) => (
-
+ {
+ Services.getUsersService().currentUser().displayName || "User"
+ }
)}
shouldFocusToggleOnSelect
diff --git a/ui/ui-app/src/app/components/header/index.ts b/ui/ui-app/src/app/components/header/index.ts
index d7a03c3ff1..a26a71d70e 100644
--- a/ui/ui-app/src/app/components/header/index.ts
+++ b/ui/ui-app/src/app/components/header/index.ts
@@ -1,3 +1,4 @@
export * from "./AvatarDropdown";
-export * from "./AppHeader.tsx";
-export * from "./RootPageHeader.tsx";
+export * from "./AppHeader";
+export * from "./AppHeaderToolbar";
+export * from "./RootPageHeader";
diff --git a/ui/ui-app/src/services/index.ts b/ui/ui-app/src/services/index.ts
index a10b83788a..40272990e6 100644
--- a/ui/ui-app/src/services/index.ts
+++ b/ui/ui-app/src/services/index.ts
@@ -8,3 +8,4 @@ export * from "./logger";
export * from "./services";
export * from "./users";
export * from "./url";
+export * from "./version";
diff --git a/ui/ui-app/src/services/services.ts b/ui/ui-app/src/services/services.ts
index 53a2e3ec32..b2047f782e 100644
--- a/ui/ui-app/src/services/services.ts
+++ b/ui/ui-app/src/services/services.ts
@@ -7,6 +7,7 @@ import { DownloaderService } from "./downloader";
import { AuthService } from "./auth";
import { UsersService } from "./users";
import { AlertsService } from "./alerts";
+import { VersionService } from "@services/version";
// TODO convert all of the services into React hooks
@@ -25,6 +26,10 @@ export class Services {
return Services.all.config;
}
+ public static getVersionService(): VersionService {
+ return Services.all.version;
+ }
+
public static getDownloaderService(): DownloaderService {
return Services.all.downloader;
}
@@ -53,6 +58,7 @@ export class Services {
groups: new GroupsService(),
users: new UsersService(),
config: new ConfigService(),
+ version: new VersionService(),
downloader: new DownloaderService(),
admin: new AdminService(),
logger: new LoggerService(),
diff --git a/ui/ui-app/src/services/version/index.ts b/ui/ui-app/src/services/version/index.ts
new file mode 100644
index 0000000000..aa28cc599e
--- /dev/null
+++ b/ui/ui-app/src/services/version/index.ts
@@ -0,0 +1,2 @@
+export * from "./version.service.ts";
+export * from "./version.type.ts";
diff --git a/ui/ui-app/src/services/version/version.service.ts b/ui/ui-app/src/services/version/version.service.ts
new file mode 100644
index 0000000000..cef142a268
--- /dev/null
+++ b/ui/ui-app/src/services/version/version.service.ts
@@ -0,0 +1,50 @@
+import { VersionType } from "@services/version/version.type.ts";
+import { Service } from "@services/baseService.ts";
+
+const DEFAULT_VERSION: VersionType = {
+ name: "Apicurio Registry",
+ version: "DEV",
+ digest: "DEV",
+ builtOn: new Date().toString(),
+ url: "http://www.apicur.io/"
+};
+
+
+export function getVersion(): VersionType {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ if (ApicurioInfo) { return ApicurioInfo as VersionType; }
+
+ const gw: any = window as any;
+ if (gw["ApicurioInfo"]) {
+ return gw["ApicurioInfo"] as VersionType;
+ }
+
+ return DEFAULT_VERSION;
+}
+
+
+/**
+ * A simple configuration service. Reads information from a global "ApicurioRegistryConfig" variable
+ * that is typically included via JSONP.
+ */
+export class VersionService implements Service {
+ private version: VersionType;
+
+ constructor() {
+ this.version = getVersion();
+ }
+
+ public init(): void {
+ // Nothing to init (done in c'tor)
+ }
+
+ public updateConfig(version: VersionType): void {
+ this.version = version;
+ }
+
+ public getVersion(): VersionType {
+ return this.version;
+ }
+
+}
diff --git a/ui/ui-app/src/services/version/version.type.ts b/ui/ui-app/src/services/version/version.type.ts
new file mode 100644
index 0000000000..fe4163c800
--- /dev/null
+++ b/ui/ui-app/src/services/version/version.type.ts
@@ -0,0 +1,8 @@
+
+export interface VersionType {
+ name: string;
+ version: string;
+ digest: string;
+ builtOn: string;
+ url: string;
+}