mirror of
https://github.com/ansible/awx.git
synced 2026-05-19 14:57:39 -02:30
add AlertModal component and update styling of delete confirmations
This commit is contained in:
91
src/app.scss
91
src/app.scss
@@ -6,6 +6,7 @@
|
|||||||
//
|
//
|
||||||
// masthead overrides
|
// masthead overrides
|
||||||
//
|
//
|
||||||
|
|
||||||
.pf-c-page__header-brand {
|
.pf-c-page__header-brand {
|
||||||
max-width: 255px;
|
max-width: 255px;
|
||||||
}
|
}
|
||||||
@@ -114,8 +115,9 @@
|
|||||||
|
|
||||||
//
|
//
|
||||||
// switch overrides
|
// switch overrides
|
||||||
//
|
|
||||||
// https://github.com/patternfly/patternfly-next/issues/915
|
// https://github.com/patternfly/patternfly-next/issues/915
|
||||||
|
//
|
||||||
|
|
||||||
.pf-c-switch {
|
.pf-c-switch {
|
||||||
.pf-c-switch__label::before {
|
.pf-c-switch__label::before {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -145,6 +147,7 @@
|
|||||||
|
|
||||||
.awx-c-modal.pf-c-modal-box {
|
.awx-c-modal.pf-c-modal-box {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding: 24px;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
|
|
||||||
.pf-c-modal-box__body {
|
.pf-c-modal-box__body {
|
||||||
@@ -231,13 +234,21 @@
|
|||||||
border-bottom: 1px solid #d7d7d7;
|
border-bottom: 1px solid #d7d7d7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.at-c-listCardBody {
|
||||||
|
--pf-c-card__footer--PaddingX: 0;
|
||||||
|
--pf-c-card__footer--PaddingY: 0;
|
||||||
|
--pf-c-card__body--PaddingX: 0;
|
||||||
|
--pf-c-card__body--PaddingY: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.awx-c-card {
|
.awx-c-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
// PF Alert notification component overrides
|
// PF Alert notification component overrides
|
||||||
|
//
|
||||||
|
|
||||||
.pf-c-alert__title {
|
.pf-c-alert__title {
|
||||||
--pf-c-alert__title--PaddingTop: 20px;
|
--pf-c-alert__title--PaddingTop: 20px;
|
||||||
--pf-c-alert__title--PaddingRight: 20px;
|
--pf-c-alert__title--PaddingRight: 20px;
|
||||||
@@ -272,17 +283,6 @@
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.orgListAlert-actionBtn{
|
|
||||||
margin:0 10px;
|
|
||||||
}
|
|
||||||
.orgListDetete-progressBar{
|
|
||||||
padding-right: 32px;
|
|
||||||
}
|
|
||||||
.orgListDelete-progressBar-noShow{
|
|
||||||
display: none;
|
|
||||||
padding-right: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.awx-c-form-action-group {
|
.awx-c-form-action-group {
|
||||||
float: right;
|
float: right;
|
||||||
display: block;
|
display: block;
|
||||||
@@ -293,3 +293,66 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// AlertModal styles
|
||||||
|
//
|
||||||
|
|
||||||
|
.at-c-alertModal.pf-c-modal-box {
|
||||||
|
border: 0;
|
||||||
|
border-left: 56px solid black;
|
||||||
|
|
||||||
|
.at-c-alertModal__icon {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 23px;
|
||||||
|
top: 28px;
|
||||||
|
left: -39px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.at-c-alertModal--warning.pf-c-modal-box {
|
||||||
|
border-color: var(--pf-global--warning-color--100);
|
||||||
|
|
||||||
|
.pf-c-title {
|
||||||
|
color: var(--pf-global--warning-color--200);
|
||||||
|
}
|
||||||
|
|
||||||
|
.at-c-alertModal__icon {
|
||||||
|
color: var(--pf-global--warning-color--200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.at-c-alertModal--danger.pf-c-modal-box {
|
||||||
|
border-color: var(--pf-global--danger-color--100);
|
||||||
|
|
||||||
|
.pf-c-title {
|
||||||
|
color: var(--pf-global--danger-color--200);
|
||||||
|
}
|
||||||
|
|
||||||
|
.at-c-alertModal__icon {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.at-c-alertModal--info.pf-c-modal-box {
|
||||||
|
border-color: var(--pf-global--info-color--100);
|
||||||
|
|
||||||
|
.pf-c-title {
|
||||||
|
color: var(--pf-global--info-color--200);
|
||||||
|
}
|
||||||
|
|
||||||
|
.at-c-alertModal__icon {
|
||||||
|
color: var(--pf-global--info-color--200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.at-c-alertModal--success.pf-c-modal-box {
|
||||||
|
border-color: var(--pf-global--success-color--100);
|
||||||
|
|
||||||
|
.pf-c-title {
|
||||||
|
color: var(--pf-global--success-color--200);
|
||||||
|
}
|
||||||
|
|
||||||
|
.at-c-alertModal__icon {
|
||||||
|
color: var(--pf-global--success-color--200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
28
src/components/AlertModal.jsx
Normal file
28
src/components/AlertModal.jsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Modal
|
||||||
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
|
import { ExclamationTriangleIcon, ExclamationCircleIcon, InfoCircleIcon, CheckCircleIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
|
const getIcon = (variant) => {
|
||||||
|
let icon;
|
||||||
|
if (variant === 'warning') {
|
||||||
|
icon = (<ExclamationTriangleIcon className="at-c-alertModal__icon" />);
|
||||||
|
} else if (variant === 'danger') {
|
||||||
|
icon = (<ExclamationCircleIcon className="at-c-alertModal__icon" />);
|
||||||
|
} if (variant === 'info') {
|
||||||
|
icon = (<InfoCircleIcon className="at-c-alertModal__icon" />);
|
||||||
|
} if (variant === 'success') {
|
||||||
|
icon = (<CheckCircleIcon className="at-c-alertModal__icon" />);
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ({ variant, children, ...props }) => (
|
||||||
|
<Modal className={`awx-c-modal${variant && ` at-c-alertModal at-c-alertModal--${variant}`}`} {...props}>
|
||||||
|
{children}
|
||||||
|
{getIcon(variant)}
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
DataList, DataListItem, DataListCell, Text,
|
DataList, DataListItem, DataListCell, Text,
|
||||||
TextContent, TextVariants, Chip, Alert, AlertActionCloseButton, Button
|
TextContent, TextVariants, Chip, Button
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
import { I18n, i18nMark } from '@lingui/react';
|
import { I18n, i18nMark } from '@lingui/react';
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
Link
|
Link
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
|
import AlertModal from '../../../components/AlertModal';
|
||||||
import Pagination from '../../../components/Pagination';
|
import Pagination from '../../../components/Pagination';
|
||||||
import DataListToolbar from '../../../components/DataListToolbar';
|
import DataListToolbar from '../../../components/DataListToolbar';
|
||||||
|
|
||||||
@@ -333,17 +334,18 @@ class OrganizationAccessList extends React.Component {
|
|||||||
showExpandCollapse
|
showExpandCollapse
|
||||||
/>
|
/>
|
||||||
{showWarning && (
|
{showWarning && (
|
||||||
<Alert
|
<AlertModal
|
||||||
variant="danger"
|
variant="danger"
|
||||||
title={warningTitle}
|
title={warningTitle}
|
||||||
action={<AlertActionCloseButton onClose={this.hideWarning} />}
|
isOpen={showWarning}
|
||||||
|
onClose={this.hideWarning}
|
||||||
|
actions={[
|
||||||
|
<Button variant="danger" aria-label="confirm-delete" onClick={this.confirmDelete}>Delete</Button>,
|
||||||
|
<Button variant="secondary" onClick={this.hideWarning}>Cancel</Button>
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
{warningMsg}
|
{warningMsg}
|
||||||
<span className="awx-c-form-action-group">
|
</AlertModal>
|
||||||
<Button variant="danger" aria-label="confirm-delete" onClick={this.confirmDelete}>Delete</Button>
|
|
||||||
<Button variant="secondary" onClick={this.hideWarning}>Cancel</Button>
|
|
||||||
</span>
|
|
||||||
</Alert>
|
|
||||||
)}
|
)}
|
||||||
<DataList aria-label={i18n._(t`Access List`)}>
|
<DataList aria-label={i18n._(t`Access List`)}>
|
||||||
{results.map(result => (
|
{results.map(result => (
|
||||||
|
|||||||
@@ -5,26 +5,26 @@ import React, {
|
|||||||
import {
|
import {
|
||||||
withRouter
|
withRouter
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
import { I18n, i18nMark } from '@lingui/react';
|
import { I18n, i18nMark } from '@lingui/react';
|
||||||
import { Trans, t } from '@lingui/macro';
|
import { Trans, t } from '@lingui/macro';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
EmptyState,
|
EmptyState,
|
||||||
EmptyStateIcon,
|
EmptyStateIcon,
|
||||||
EmptyStateBody,
|
EmptyStateBody,
|
||||||
Modal,
|
|
||||||
PageSection,
|
PageSection,
|
||||||
PageSectionVariants,
|
PageSectionVariants,
|
||||||
Title,
|
Title,
|
||||||
Button,
|
Button
|
||||||
Progress,
|
|
||||||
ProgressVariant
|
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
import { CubesIcon } from '@patternfly/react-icons';
|
import { CubesIcon } from '@patternfly/react-icons';
|
||||||
import DataListToolbar from '../../../components/DataListToolbar';
|
import DataListToolbar from '../../../components/DataListToolbar';
|
||||||
import OrganizationListItem from '../components/OrganizationListItem';
|
import OrganizationListItem from '../components/OrganizationListItem';
|
||||||
import Pagination from '../../../components/Pagination';
|
import Pagination from '../../../components/Pagination';
|
||||||
|
import AlertModal from '../../../components/AlertModal';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
encodeQueryString,
|
encodeQueryString,
|
||||||
@@ -61,8 +61,6 @@ class OrganizationsList extends Component {
|
|||||||
selected: [],
|
selected: [],
|
||||||
isModalOpen: false,
|
isModalOpen: false,
|
||||||
orgsToDelete: [],
|
orgsToDelete: [],
|
||||||
orgsDeleted: [],
|
|
||||||
deleteSuccess: false,
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -145,10 +143,7 @@ class OrganizationsList extends Component {
|
|||||||
handleClearOrgsToDelete () {
|
handleClearOrgsToDelete () {
|
||||||
this.setState({
|
this.setState({
|
||||||
isModalOpen: false,
|
isModalOpen: false,
|
||||||
orgsDeleted: [],
|
orgsToDelete: []
|
||||||
deleteSuccess: false,
|
|
||||||
orgsToDelete: [],
|
|
||||||
deleteStarted: false
|
|
||||||
});
|
});
|
||||||
this.onSelectAll();
|
this.onSelectAll();
|
||||||
}
|
}
|
||||||
@@ -175,23 +170,13 @@ class OrganizationsList extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async handleOrgDelete (event) {
|
async handleOrgDelete (event) {
|
||||||
const { orgsToDelete, orgsDeleted } = this.state;
|
const { orgsToDelete } = this.state;
|
||||||
const { api } = this.props;
|
const { api } = this.props;
|
||||||
this.setState({ deleteStarted: true });
|
|
||||||
|
|
||||||
orgsToDelete.forEach(async (org) => {
|
orgsToDelete.forEach(async (org) => {
|
||||||
try {
|
await api.destroyOrganization(org.id);
|
||||||
const res = await api.destroyOrganization(org.id);
|
|
||||||
this.setState({
|
|
||||||
orgsDeleted: orgsDeleted.concat(res)
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
this.setState({ deleteSuccess: false });
|
|
||||||
} finally {
|
|
||||||
this.setState({ deleteSuccess: true });
|
|
||||||
const queryParams = this.getQueryParams();
|
const queryParams = this.getQueryParams();
|
||||||
this.fetchOrganizations(queryParams);
|
this.fetchOrganizations(queryParams);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
@@ -261,12 +246,9 @@ class OrganizationsList extends Component {
|
|||||||
const {
|
const {
|
||||||
count,
|
count,
|
||||||
error,
|
error,
|
||||||
deleteSuccess,
|
|
||||||
deleteStarted,
|
|
||||||
loading,
|
loading,
|
||||||
noInitialResults,
|
noInitialResults,
|
||||||
orgsToDelete,
|
orgsToDelete,
|
||||||
orgsDeleted,
|
|
||||||
page,
|
page,
|
||||||
pageCount,
|
pageCount,
|
||||||
page_size,
|
page_size,
|
||||||
@@ -283,13 +265,15 @@ class OrganizationsList extends Component {
|
|||||||
<PageSection variant={medium}>
|
<PageSection variant={medium}>
|
||||||
<Card>
|
<Card>
|
||||||
{ isModalOpen && (
|
{ isModalOpen && (
|
||||||
<Modal
|
<AlertModal
|
||||||
className="orgListAlert"
|
variant="danger"
|
||||||
title={warningTitle}
|
title={warningTitle}
|
||||||
isOpen={isModalOpen}
|
isOpen={isModalOpen}
|
||||||
style={{ width: '1000px' }}
|
|
||||||
variant="danger"
|
|
||||||
onClose={this.handleClearOrgsToDelete}
|
onClose={this.handleClearOrgsToDelete}
|
||||||
|
actions={[
|
||||||
|
<Button variant="danger" aria-label="confirm-delete" onClick={this.handleOrgDelete}>Delete</Button>,
|
||||||
|
<Button variant="secondary" aria-label="cancel-delete" onClick={this.handleClearOrgsToDelete}>Cancel</Button>
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
{warningMsg}
|
{warningMsg}
|
||||||
<br />
|
<br />
|
||||||
@@ -301,24 +285,8 @@ class OrganizationsList extends Component {
|
|||||||
<br />
|
<br />
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
<div className={deleteStarted ? 'orgListDetete-progressBar' : 'orgListDelete-progressBar-noShow'}>
|
|
||||||
<Progress
|
|
||||||
value={deleteSuccess ? 100 : 67}
|
|
||||||
variant={deleteStarted ? ProgressVariant.success : ProgressVariant.danger}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<br />
|
<br />
|
||||||
<div className="awx-c-form-action-group">
|
</AlertModal>
|
||||||
{orgsDeleted.length
|
|
||||||
? <Button className="orgListAlert-actionBtn" keys="cancel" variant="primary" aria-label="close-delete" onClick={this.handleClearOrgsToDelete}>Close</Button>
|
|
||||||
: (
|
|
||||||
<span>
|
|
||||||
<Button className="orgListAlert-actionBtn" keys="cancel" variant="secondary" aria-label="cancel-delete" onClick={this.handleClearOrgsToDelete}>Cancel</Button>
|
|
||||||
<Button className="orgListAlert-actionBtn" keys="cancel" variant="danger" aria-label="confirm-delete" onClick={this.handleOrgDelete}>Delete</Button>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
)}
|
)}
|
||||||
{noInitialResults && (
|
{noInitialResults && (
|
||||||
<EmptyState>
|
<EmptyState>
|
||||||
|
|||||||
Reference in New Issue
Block a user