diff --git a/awx/ui_next/public/index.html b/awx/ui_next/public/index.html
index 564369ef99..301f9bf209 100644
--- a/awx/ui_next/public/index.html
+++ b/awx/ui_next/public/index.html
@@ -37,7 +37,6 @@
name="description"
content="AWX"
/>
-
AWX
diff --git a/awx/ui_next/src/App.jsx b/awx/ui_next/src/App.jsx
index 1ca84a2872..88c91406c0 100644
--- a/awx/ui_next/src/App.jsx
+++ b/awx/ui_next/src/App.jsx
@@ -12,7 +12,6 @@ import { ErrorBoundary } from 'react-error-boundary';
import { I18nProvider } from '@lingui/react';
import { i18n } from '@lingui/core';
import { Card, PageSection } from '@patternfly/react-core';
-
import { ConfigProvider, useAuthorizedPath } from './contexts/Config';
import { SessionProvider, useSession } from './contexts/Session';
import AppContainer from './components/AppContainer';
@@ -20,15 +19,14 @@ import Background from './components/Background';
import ContentError from './components/ContentError';
import NotFound from './screens/NotFound';
import Login from './screens/Login';
-
import { isAuthenticated } from './util/auth';
import { getLanguageWithoutRegionCode } from './util/language';
import { dynamicActivate, locales } from './i18nLoader';
import Metrics from './screens/Metrics';
-
import getRouteConfig from './routeConfig';
import SubscriptionEdit from './screens/Setting/Subscription/SubscriptionEdit';
import { SESSION_REDIRECT_URL } from './constants';
+import { RootAPI } from './api';
function ErrorFallback({ error }) {
return (
@@ -113,10 +111,22 @@ function App() {
// preferred language, default to one that has strings.
language = 'en';
}
+
useEffect(() => {
dynamicActivate(language);
}, [language]);
+ useEffect(() => {
+ async function fetchBrandName() {
+ const {
+ data: { BRAND_NAME },
+ } = await RootAPI.readAssetVariables();
+
+ document.title = BRAND_NAME;
+ }
+ fetchBrandName();
+ }, []);
+
const redirectURL = window.sessionStorage.getItem(SESSION_REDIRECT_URL);
if (redirectURL) {
window.sessionStorage.removeItem(SESSION_REDIRECT_URL);
diff --git a/awx/ui_next/src/App.test.jsx b/awx/ui_next/src/App.test.jsx
index 0e732b1574..805cbdc639 100644
--- a/awx/ui_next/src/App.test.jsx
+++ b/awx/ui_next/src/App.test.jsx
@@ -1,12 +1,21 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { mountWithContexts } from '../testUtils/enzymeHelpers';
+import { RootAPI } from './api';
import * as SessionContext from './contexts/Session';
import App from './App';
jest.mock('./api');
describe('', () => {
+ beforeEach(() => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
+ });
+
test('renders ok', async () => {
const contextValues = {
setAuthRedirectTo: jest.fn(),
diff --git a/awx/ui_next/src/components/About/About.jsx b/awx/ui_next/src/components/About/About.jsx
index f0730742e2..09a3d11e91 100644
--- a/awx/ui_next/src/components/About/About.jsx
+++ b/awx/ui_next/src/components/About/About.jsx
@@ -2,12 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import { t } from '@lingui/macro';
import { AboutModal } from '@patternfly/react-core';
-
-import { BrandName } from '../../variables';
+import useBrandName from '../../util/useBrandName';
function About({ version, isOpen, onClose }) {
+ const brandName = useBrandName();
const createSpeechBubble = () => {
- let text = `${BrandName} ${version}`;
+ let text = `${brandName.current} ${version}`;
let top = '';
let bottom = '';
@@ -31,7 +31,7 @@ function About({ version, isOpen, onClose }) {
({
...jest.requireActual('react-router-dom'),
@@ -40,6 +42,11 @@ const adHocItems = [
describe('', () => {
beforeEach(() => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
InventoriesAPI.readAdHocOptions.mockResolvedValue({
data: {
actions: {
diff --git a/awx/ui_next/src/components/AdHocCommands/AdHocCommandsWizard.test.jsx b/awx/ui_next/src/components/AdHocCommands/AdHocCommandsWizard.test.jsx
index bfa9c154ca..1393a94ebf 100644
--- a/awx/ui_next/src/components/AdHocCommands/AdHocCommandsWizard.test.jsx
+++ b/awx/ui_next/src/components/AdHocCommands/AdHocCommandsWizard.test.jsx
@@ -4,13 +4,14 @@ import {
mountWithContexts,
waitForElement,
} from '../../../testUtils/enzymeHelpers';
-import { CredentialsAPI, ExecutionEnvironmentsAPI } from '../../api';
+import { CredentialsAPI, ExecutionEnvironmentsAPI, RootAPI } from '../../api';
import AdHocCommandsWizard from './AdHocCommandsWizard';
jest.mock('../../api/models/CredentialTypes');
jest.mock('../../api/models/Inventories');
jest.mock('../../api/models/Credentials');
jest.mock('../../api/models/ExecutionEnvironments');
+jest.mock('../../api/models/Root');
const verbosityOptions = [
{ value: '0', key: '0', label: '0 (Normal)' },
@@ -32,6 +33,11 @@ describe('', () => {
let wrapper;
const onLaunch = jest.fn();
beforeEach(async () => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
await act(async () => {
wrapper = mountWithContexts(
}
>
diff --git a/awx/ui_next/src/components/AdHocCommands/AdHocDetailsStep.test.jsx b/awx/ui_next/src/components/AdHocCommands/AdHocDetailsStep.test.jsx
index 406769feeb..e71759f3cd 100644
--- a/awx/ui_next/src/components/AdHocCommands/AdHocDetailsStep.test.jsx
+++ b/awx/ui_next/src/components/AdHocCommands/AdHocDetailsStep.test.jsx
@@ -2,9 +2,11 @@ import React from 'react';
import { act } from 'react-dom/test-utils';
import { Formik } from 'formik';
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
+import { RootAPI } from '../../api';
import DetailsStep from './AdHocDetailsStep';
jest.mock('../../api/models/Credentials');
+jest.mock('../../api/models/Root');
const verbosityOptions = [
{ key: -1, value: '', label: '', isDisabled: false },
@@ -32,6 +34,14 @@ const initialValues = {
describe('', () => {
let wrapper;
+ beforeEach(() => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
+ });
+
test('should mount properly', async () => {
await act(async () => {
wrapper = mountWithContexts(
diff --git a/awx/ui_next/src/index.jsx b/awx/ui_next/src/index.jsx
index 827d708961..fb7fe4450f 100644
--- a/awx/ui_next/src/index.jsx
+++ b/awx/ui_next/src/index.jsx
@@ -3,9 +3,6 @@ import ReactDOM from 'react-dom';
import './setupCSP';
import '@patternfly/react-core/dist/styles/base.css';
import App from './App';
-import { BrandName } from './variables';
-
-document.title = `${BrandName}`;
ReactDOM.render(
diff --git a/awx/ui_next/src/screens/Project/ProjectEdit/ProjectEdit.test.jsx b/awx/ui_next/src/screens/Project/ProjectEdit/ProjectEdit.test.jsx
index 6e7b4b22f1..7e7b141892 100644
--- a/awx/ui_next/src/screens/Project/ProjectEdit/ProjectEdit.test.jsx
+++ b/awx/ui_next/src/screens/Project/ProjectEdit/ProjectEdit.test.jsx
@@ -6,7 +6,7 @@ import {
waitForElement,
} from '../../../../testUtils/enzymeHelpers';
import ProjectEdit from './ProjectEdit';
-import { ProjectsAPI, CredentialTypesAPI } from '../../../api';
+import { ProjectsAPI, CredentialTypesAPI, RootAPI } from '../../../api';
jest.mock('../../../api');
@@ -83,6 +83,11 @@ describe('', () => {
};
beforeEach(async () => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
await ProjectsAPI.readOptions.mockImplementation(
() => projectOptionsResolve
);
diff --git a/awx/ui_next/src/screens/Project/shared/ProjectForm.test.jsx b/awx/ui_next/src/screens/Project/shared/ProjectForm.test.jsx
index 0a34bde6ea..8c99c0b6c7 100644
--- a/awx/ui_next/src/screens/Project/shared/ProjectForm.test.jsx
+++ b/awx/ui_next/src/screens/Project/shared/ProjectForm.test.jsx
@@ -5,7 +5,7 @@ import {
waitForElement,
} from '../../../../testUtils/enzymeHelpers';
import ProjectForm from './ProjectForm';
-import { CredentialTypesAPI, ProjectsAPI } from '../../../api';
+import { CredentialTypesAPI, ProjectsAPI, RootAPI } from '../../../api';
jest.mock('../../../api');
@@ -81,6 +81,11 @@ describe('', () => {
};
beforeEach(async () => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
await ProjectsAPI.readOptions.mockImplementation(
() => projectOptionsResolve
);
diff --git a/awx/ui_next/src/screens/Project/shared/ProjectSubForms/ManualSubForm.jsx b/awx/ui_next/src/screens/Project/shared/ProjectSubForms/ManualSubForm.jsx
index e15e5147d3..0e7185284e 100644
--- a/awx/ui_next/src/screens/Project/shared/ProjectSubForms/ManualSubForm.jsx
+++ b/awx/ui_next/src/screens/Project/shared/ProjectSubForms/ManualSubForm.jsx
@@ -1,6 +1,5 @@
import 'styled-components/macro';
import React from 'react';
-
import { t } from '@lingui/macro';
import { useField } from 'formik';
import { FormGroup, Alert } from '@patternfly/react-core';
@@ -8,18 +7,14 @@ import { required } from '../../../../util/validators';
import AnsibleSelect from '../../../../components/AnsibleSelect';
import FormField from '../../../../components/FormField';
import Popover from '../../../../components/Popover';
-import { BrandName } from '../../../../variables';
-
-// Setting BrandName to a variable here is necessary to get the jest tests
-// passing. Attempting to use BrandName in the template literal results
-// in failing tests.
-const brandName = BrandName;
+import useBrandName from '../../../../util/useBrandName';
const ManualSubForm = ({
localPath,
project_base_dir,
project_local_paths,
}) => {
+ const brandName = useBrandName();
const localPaths = [...new Set([...project_local_paths, localPath])];
const options = [
{
@@ -54,7 +49,7 @@ const ManualSubForm = ({
Either that directory is empty, or all of the contents are already
assigned to other projects. Create a new directory there and make
sure the playbook files can be read by the "awx" system user,
- or have ${brandName} directly retrieve your playbooks from
+ or have ${brandName.current} directly retrieve your playbooks from
source control using the Source Control Type option above.`}
)}
diff --git a/awx/ui_next/src/screens/Setting/SettingList.jsx b/awx/ui_next/src/screens/Setting/SettingList.jsx
index d42eaa2b10..61fe2352a8 100644
--- a/awx/ui_next/src/screens/Setting/SettingList.jsx
+++ b/awx/ui_next/src/screens/Setting/SettingList.jsx
@@ -1,6 +1,5 @@
import React from 'react';
import { Link } from 'react-router-dom';
-
import { t } from '@lingui/macro';
import {
Card as _Card,
@@ -14,14 +13,9 @@ import {
PageSection,
} from '@patternfly/react-core';
import styled from 'styled-components';
-import { BrandName } from '../../variables';
import { useConfig } from '../../contexts/Config';
import ContentLoading from '../../components/ContentLoading/ContentLoading';
-
-// Setting BrandName to a variable here is necessary to get the jest tests
-// passing. Attempting to use BrandName in the template literal results
-// in failing tests.
-const brandName = BrandName;
+import useBrandName from '../../util/useBrandName';
const SplitLayout = styled(PageSection)`
column-count: 1;
@@ -50,10 +44,11 @@ const CardDescription = styled.div`
function SettingList() {
const config = useConfig();
+ const brandName = useBrandName();
const settingRoutes = [
{
header: t`Authentication`,
- description: t`Enable simplified login for your ${brandName} applications`,
+ description: t`Enable simplified login for your ${brandName.current} applications`,
id: 'authentication',
routes: [
{
@@ -88,7 +83,7 @@ function SettingList() {
},
{
header: t`Jobs`,
- description: t`Update settings pertaining to Jobs within ${brandName}`,
+ description: t`Update settings pertaining to Jobs within ${brandName.current}`,
id: 'jobs',
routes: [
{
diff --git a/awx/ui_next/src/screens/Setting/Settings.test.jsx b/awx/ui_next/src/screens/Setting/Settings.test.jsx
index 11a89e5e58..3de824527c 100644
--- a/awx/ui_next/src/screens/Setting/Settings.test.jsx
+++ b/awx/ui_next/src/screens/Setting/Settings.test.jsx
@@ -5,7 +5,7 @@ import {
mountWithContexts,
waitForElement,
} from '../../../testUtils/enzymeHelpers';
-import { SettingsAPI } from '../../api';
+import { SettingsAPI, RootAPI } from '../../api';
import mockAllOptions from './shared/data.allSettingOptions.json';
import Settings from './Settings';
@@ -19,6 +19,11 @@ describe('', () => {
let wrapper;
beforeEach(() => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
SettingsAPI.readAllOptions.mockResolvedValue({
data: mockAllOptions,
});
diff --git a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.test.jsx b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.test.jsx
index 9df1247d0c..517194a8c3 100644
--- a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.test.jsx
+++ b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.test.jsx
@@ -12,6 +12,7 @@ import {
JobTemplatesAPI,
LabelsAPI,
ProjectsAPI,
+ RootAPI,
} from '../../../api';
jest.mock('../../../api');
@@ -67,6 +68,11 @@ describe('', () => {
};
beforeEach(() => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
CredentialsAPI.read.mockResolvedValue({
data: {
results: [],
diff --git a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.test.jsx b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.test.jsx
index b7dfb74864..7eb653e225 100644
--- a/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.test.jsx
+++ b/awx/ui_next/src/screens/Template/JobTemplateEdit/JobTemplateEdit.test.jsx
@@ -14,6 +14,7 @@ import {
InventoriesAPI,
ExecutionEnvironmentsAPI,
InstanceGroupsAPI,
+ RootAPI,
} from '../../../api';
import JobTemplateEdit from './JobTemplateEdit';
import useDebounce from '../../../util/useDebounce';
@@ -27,6 +28,7 @@ jest.mock('../../../api/models/Projects');
jest.mock('../../../api/models/Inventories');
jest.mock('../../../api/models/ExecutionEnvironments');
jest.mock('../../../api/models/InstanceGroups');
+jest.mock('../../../api/models/Root');
const mockJobTemplate = {
allow_callbacks: false,
@@ -203,6 +205,11 @@ const mockExecutionEnvironment = [
describe('', () => {
beforeEach(() => {
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
JobTemplatesAPI.readCredentials.mockResolvedValue({
data: mockRelatedCredentials,
});
diff --git a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
index 877c0cabb3..856dc6516d 100644
--- a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
+++ b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.jsx
@@ -13,11 +13,10 @@ import {
} from '@patternfly/react-core';
import ContentError from '../../../components/ContentError';
import ContentLoading from '../../../components/ContentLoading';
-import { BrandName } from '../../../variables';
import AnsibleSelect from '../../../components/AnsibleSelect';
import { TagMultiSelect } from '../../../components/MultiSelect';
import useRequest from '../../../util/useRequest';
-
+import useBrandName from '../../../util/useBrandName';
import FormActionGroup from '../../../components/FormActionGroup';
import FormField, {
CheckboxField,
@@ -67,6 +66,7 @@ function JobTemplateForm({
Boolean(template.webhook_service)
);
const isMounted = useIsMounted();
+ const brandName = useBrandName();
const [askInventoryOnLaunchField] = useField('ask_inventory_on_launch');
const [jobTypeField, jobTypeMeta, jobTypeHelpers] = useField({
@@ -567,7 +567,7 @@ function JobTemplateForm({
diff --git a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx
index 882aa1de96..81d80ddd1d 100644
--- a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx
+++ b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx
@@ -15,6 +15,7 @@ import {
CredentialsAPI,
CredentialTypesAPI,
InventoriesAPI,
+ RootAPI,
} from '../../../api';
jest.mock('../../../api');
@@ -95,6 +96,11 @@ describe('', () => {
beforeEach(() => {
consoleError = global.console.error;
global.console.error = jest.fn();
+ RootAPI.readAssetVariables.mockResolvedValue({
+ data: {
+ BRAND_NAME: 'AWX',
+ },
+ });
LabelsAPI.read.mockReturnValue({
data: mockData.summary_fields.labels,
});
diff --git a/awx/ui_next/src/util/useBrandName.js b/awx/ui_next/src/util/useBrandName.js
new file mode 100644
index 0000000000..f8d0a80aef
--- /dev/null
+++ b/awx/ui_next/src/util/useBrandName.js
@@ -0,0 +1,19 @@
+import { useEffect, useRef } from 'react';
+import { RootAPI } from '../api';
+
+export default function useBrandName() {
+ const brandName = useRef('');
+
+ useEffect(() => {
+ async function fetchBrandName() {
+ const {
+ data: { BRAND_NAME },
+ } = await RootAPI.readAssetVariables();
+
+ brandName.current = BRAND_NAME;
+ }
+ fetchBrandName();
+ }, []);
+
+ return brandName;
+}
diff --git a/awx/ui_next/src/variables.js b/awx/ui_next/src/variables.js
deleted file mode 100644
index 001c1c5e16..0000000000
--- a/awx/ui_next/src/variables.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export const BrandName = 'AWX';
-export const PendoAPIKey = '';