Skip to content

Commit

Permalink
Add subscription wizard and redirect logic
Browse files Browse the repository at this point in the history
  • Loading branch information
marshmalien committed Mar 5, 2021
1 parent 9502efd commit d5f9bb5
Show file tree
Hide file tree
Showing 29 changed files with 2,100 additions and 132 deletions.
4 changes: 4 additions & 0 deletions awx/ui_next/src/api/models/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class Settings extends Base {
return this.http.patch(`${this.baseUrl}all/`, data);
}

updateCategory(category, data) {
return this.http.patch(`${this.baseUrl}${category}/`, data);
}

readCategory(category) {
return this.http.get(`${this.baseUrl}${category}/`);
}
Expand Down
30 changes: 0 additions & 30 deletions awx/ui_next/src/screens/Setting/License/License.jsx

This file was deleted.

16 changes: 0 additions & 16 deletions awx/ui_next/src/screens/Setting/License/License.test.jsx

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion awx/ui_next/src/screens/Setting/License/index.js

This file was deleted.

39 changes: 39 additions & 0 deletions awx/ui_next/src/screens/Setting/Subscription/Subscription.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { Link, Redirect, Route, Switch, useRouteMatch } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { PageSection, Card } from '@patternfly/react-core';
import SubscriptionDetail from './SubscriptionDetail';
import SubscriptionEdit from './SubscriptionEdit';
import ContentError from '../../../components/ContentError';

function Subscription({ i18n }) {
const baseURL = '/settings/subscription';
const baseRoute = useRouteMatch({
path: '/settings/subscription',
exact: true,
});

return (
<PageSection>
<Card>
{baseRoute && <Redirect to={`${baseURL}/details`} />}
<Switch>
<Route path={`${baseURL}/details`}>
<SubscriptionDetail />
</Route>
<Route path={`${baseURL}/edit`}>
<SubscriptionEdit />
</Route>
<Route key="not-found" path={`${baseURL}/*`}>
<ContentError isNotFound>
<Link to={baseURL}>{i18n._(t`View Settings`)}</Link>
</ContentError>
</Route>
</Switch>
</Card>
</PageSection>
);
}

export default withI18n()(Subscription);
51 changes: 51 additions & 0 deletions awx/ui_next/src/screens/Setting/Subscription/Subscription.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { createMemoryHistory } from 'history';
import {
mountWithContexts,
waitForElement,
} from '../../../../testUtils/enzymeHelpers';
import mockAllSettings from '../shared/data.allSettings.json';
import { SettingsAPI, RootAPI } from '../../../api';
import Subscription from './Subscription';

jest.mock('../../../api');
SettingsAPI.readCategory.mockResolvedValue({
data: mockAllSettings,
});
RootAPI.readAssetVariables.mockResolvedValue({
data: {
BRAND_NAME: 'AWX',
PENDO_API_KEY: '',
},
});

describe('<Subscription />', () => {
let wrapper;

afterEach(() => {
wrapper.unmount();
jest.clearAllMocks();
});

test('should redirect to subscription details', async () => {
const history = createMemoryHistory({
initialEntries: ['/settings/subscription'],
});
await act(async () => {
wrapper = mountWithContexts(<Subscription />, {
context: {
router: {
history,
},
config: {
license_info: {
license_type: 'enterprise',
},
},
},
});
});
await waitForElement(wrapper, 'SubscriptionDetail', el => el.length === 1);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t, Trans } from '@lingui/macro';
import { Button, Label } from '@patternfly/react-core';
import {
CaretLeftIcon,
CheckIcon,
ExclamationCircleIcon,
} from '@patternfly/react-icons';
import RoutedTabs from '../../../../components/RoutedTabs';
import { CardBody, CardActionsRow } from '../../../../components/Card';
import { DetailList, Detail } from '../../../../components/DetailList';
import { useConfig } from '../../../../contexts/Config';
import { formatDateStringUTC } from '../../../../util/dates';

function SubscriptionDetail({ i18n }) {
const [{ license_info, version }] = useConfig();
const baseURL = '/settings/subscription';
const tabsArray = [
{
name: (
<>
<CaretLeftIcon />
{i18n._(t`Back to Settings`)}
</>
),
link: '/settings',
id: 99,
},
{
name: i18n._(t`Subscription Details`),
link: `${baseURL}/details`,
id: 0,
},
];

function secondsToDays(seconds) {
let duration = Math.floor(parseInt(seconds, 10) / 86400);
if (duration < 0) {
duration = 0;
}
return duration !== 1
? i18n._(t`${duration} days`)
: i18n._(t`${duration} day`);
}

return (
<>
<RoutedTabs tabsArray={tabsArray} />
<CardBody>
<DetailList>
<Detail
label={i18n._(t`Status`)}
value={
license_info.compliant ? (
<Label variant="outline" color="green" icon={<CheckIcon />}>
{i18n._(t`Compliant`)}
</Label>
) : (
<Label
variant="outline"
color="red"
icon={<ExclamationCircleIcon />}
>
{i18n._(t`Out of compliance`)}
</Label>
)
}
/>
<Detail label={i18n._(t`Version`)} value={version} />
<Detail
label={i18n._(t`Subscription type`)}
value={license_info.license_type}
/>
<Detail
label={i18n._(t`Subscription`)}
value={license_info.subscription_name}
/>
<Detail
label={i18n._(t`Trial`)}
value={license_info.trial ? i18n._(t`True`) : i18n._(t`False`)}
/>
<Detail
label={i18n._(t`Expires on`)}
value={
license_info.license_date &&
formatDateStringUTC(
new Date(license_info.license_date * 1000).toISOString()
)
}
/>
<Detail
label={i18n._(t`Time remaining`)}
value={
license_info.time_remaining &&
secondsToDays(license_info.time_remaining)
}
/>
{license_info.instance_count < 9999999 && (
<Detail
label={i18n._(t`Hosts available`)}
value={license_info.available_instances}
/>
)}
{license_info.instance_count >= 9999999 && (
<Detail
label={i18n._(t`Hosts available`)}
value={i18n._(t`Unlimited`)}
/>
)}
<Detail
label={i18n._(t`Hosts used`)}
value={license_info.current_instances}
/>
<Detail
label={i18n._(t`Hosts remaining`)}
value={license_info.free_instances}
/>
</DetailList>
<br />
<Trans>
If you are ready to upgrade or renew, please{' '}
<Button
component="a"
href="https://www.redhat.com/contact"
variant="link"
target="_blank"
isInline
>
contact us.
</Button>
</Trans>
<CardActionsRow>
<Button
aria-label={i18n._(t`edit`)}
component={Link}
to="/settings/subscription/edit"
>
{i18n._(t`Edit`)}
</Button>
</CardActionsRow>
</CardBody>
</>
);
}

export default withI18n()(SubscriptionDetail);
Loading

0 comments on commit d5f9bb5

Please sign in to comment.