mirror of
https://github.com/ansible/awx.git
synced 2026-03-19 09:57:33 -02:30
Merge pull request #7108 from nixocio/ui_issue_7105
Make consistent usage of `useRequest` to delete items Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import 'styled-components/macro';
|
import 'styled-components/macro';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import { Link, useHistory, useLocation } from 'react-router-dom';
|
import { Link, useHistory, useLocation } from 'react-router-dom';
|
||||||
import { RRule, rrulestr } from 'rrule';
|
import { RRule, rrulestr } from 'rrule';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@@ -16,7 +16,7 @@ import { DetailList, Detail, UserDateDetail } from '../../DetailList';
|
|||||||
import ScheduleOccurrences from '../ScheduleOccurrences';
|
import ScheduleOccurrences from '../ScheduleOccurrences';
|
||||||
import ScheduleToggle from '../ScheduleToggle';
|
import ScheduleToggle from '../ScheduleToggle';
|
||||||
import { formatDateString } from '../../../util/dates';
|
import { formatDateString } from '../../../util/dates';
|
||||||
import useRequest from '../../../util/useRequest';
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
import { SchedulesAPI } from '../../../api';
|
import { SchedulesAPI } from '../../../api';
|
||||||
import DeleteButton from '../../DeleteButton';
|
import DeleteButton from '../../DeleteButton';
|
||||||
import ErrorDetail from '../../ErrorDetail';
|
import ErrorDetail from '../../ErrorDetail';
|
||||||
@@ -48,27 +48,27 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
timezone,
|
timezone,
|
||||||
} = schedule;
|
} = schedule;
|
||||||
|
|
||||||
const [deletionError, setDeletionError] = useState(null);
|
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(false);
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
const pathRoot = pathname.substr(0, pathname.indexOf('schedules'));
|
const pathRoot = pathname.substr(0, pathname.indexOf('schedules'));
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const {
|
||||||
setHasContentLoading(true);
|
request: deleteSchedule,
|
||||||
try {
|
isLoading: isDeleteLoading,
|
||||||
|
error: deleteError,
|
||||||
|
} = useRequest(
|
||||||
|
useCallback(async () => {
|
||||||
await SchedulesAPI.destroy(id);
|
await SchedulesAPI.destroy(id);
|
||||||
history.push(`${pathRoot}schedules`);
|
history.push(`${pathRoot}schedules`);
|
||||||
} catch (error) {
|
}, [id, history, pathRoot])
|
||||||
setDeletionError(error);
|
);
|
||||||
}
|
|
||||||
setHasContentLoading(false);
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
result: [credentials, preview],
|
result: [credentials, preview],
|
||||||
isLoading,
|
isLoading,
|
||||||
error,
|
error: readContentError,
|
||||||
request: fetchCredentialsAndPreview,
|
request: fetchCredentialsAndPreview,
|
||||||
} = useRequest(
|
} = useRequest(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
@@ -102,12 +102,12 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
(job_tags && job_tags.length > 0) ||
|
(job_tags && job_tags.length > 0) ||
|
||||||
(skip_tags && skip_tags.length > 0);
|
(skip_tags && skip_tags.length > 0);
|
||||||
|
|
||||||
if (isLoading || hasContentLoading) {
|
if (isLoading) {
|
||||||
return <ContentLoading />;
|
return <ContentLoading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (readContentError) {
|
||||||
return <ContentError error={error} />;
|
return <ContentError error={readContentError} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -237,21 +237,22 @@ function ScheduleDetail({ schedule, i18n }) {
|
|||||||
<DeleteButton
|
<DeleteButton
|
||||||
name={name}
|
name={name}
|
||||||
modalTitle={i18n._(t`Delete Schedule`)}
|
modalTitle={i18n._(t`Delete Schedule`)}
|
||||||
onConfirm={handleDelete}
|
onConfirm={deleteSchedule}
|
||||||
|
isDisabled={isDeleteLoading}
|
||||||
>
|
>
|
||||||
{i18n._(t`Delete`)}
|
{i18n._(t`Delete`)}
|
||||||
</DeleteButton>
|
</DeleteButton>
|
||||||
)}
|
)}
|
||||||
</CardActionsRow>
|
</CardActionsRow>
|
||||||
{deletionError && (
|
{error && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={error}
|
||||||
variant="danger"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={dismissError}
|
||||||
>
|
>
|
||||||
{i18n._(t`Failed to delete schedule.`)}
|
{i18n._(t`Failed to delete schedule.`)}
|
||||||
<ErrorDetail error={deletionError} />
|
<ErrorDetail error={error} />
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
import ErrorDetail from '../../../components/ErrorDetail';
|
import ErrorDetail from '../../../components/ErrorDetail';
|
||||||
import { CredentialsAPI, CredentialTypesAPI } from '../../../api';
|
import { CredentialsAPI, CredentialTypesAPI } from '../../../api';
|
||||||
import { Credential } from '../../../types';
|
import { Credential } from '../../../types';
|
||||||
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
|
|
||||||
function CredentialDetail({ i18n, credential }) {
|
function CredentialDetail({ i18n, credential }) {
|
||||||
const {
|
const {
|
||||||
@@ -39,7 +40,6 @@ function CredentialDetail({ i18n, credential }) {
|
|||||||
const [fields, setFields] = useState([]);
|
const [fields, setFields] = useState([]);
|
||||||
const [managedByTower, setManagedByTower] = useState([]);
|
const [managedByTower, setManagedByTower] = useState([]);
|
||||||
const [contentError, setContentError] = useState(null);
|
const [contentError, setContentError] = useState(null);
|
||||||
const [deletionError, setDeletionError] = useState(null);
|
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(true);
|
const [hasContentLoading, setHasContentLoading] = useState(true);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
@@ -62,17 +62,18 @@ function CredentialDetail({ i18n, credential }) {
|
|||||||
})();
|
})();
|
||||||
}, [credential_type]);
|
}, [credential_type]);
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const {
|
||||||
setHasContentLoading(true);
|
request: deleteCredential,
|
||||||
|
isLoading,
|
||||||
try {
|
error: deleteError,
|
||||||
|
} = useRequest(
|
||||||
|
useCallback(async () => {
|
||||||
await CredentialsAPI.destroy(credentialId);
|
await CredentialsAPI.destroy(credentialId);
|
||||||
history.push('/credentials');
|
history.push('/credentials');
|
||||||
} catch (error) {
|
}, [credentialId, history])
|
||||||
setDeletionError(error);
|
);
|
||||||
}
|
|
||||||
setHasContentLoading(false);
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
};
|
|
||||||
|
|
||||||
const renderDetail = ({ id, label, type }) => {
|
const renderDetail = ({ id, label, type }) => {
|
||||||
let detail;
|
let detail;
|
||||||
@@ -161,21 +162,22 @@ function CredentialDetail({ i18n, credential }) {
|
|||||||
<DeleteButton
|
<DeleteButton
|
||||||
name={name}
|
name={name}
|
||||||
modalTitle={i18n._(t`Delete Credential`)}
|
modalTitle={i18n._(t`Delete Credential`)}
|
||||||
onConfirm={handleDelete}
|
onConfirm={deleteCredential}
|
||||||
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
{i18n._(t`Delete`)}
|
{i18n._(t`Delete`)}
|
||||||
</DeleteButton>
|
</DeleteButton>
|
||||||
)}
|
)}
|
||||||
</CardActionsRow>
|
</CardActionsRow>
|
||||||
{deletionError && (
|
{error && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={error}
|
||||||
variant="error"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={dismissError}
|
||||||
>
|
>
|
||||||
{i18n._(t`Failed to delete credential.`)}
|
{i18n._(t`Failed to delete credential.`)}
|
||||||
<ErrorDetail error={deletionError} />
|
<ErrorDetail error={error} />
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import { Link, useHistory, useRouteMatch } from 'react-router-dom';
|
import { Link, useHistory, useRouteMatch } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
@@ -16,6 +16,7 @@ import ContentError from '../../../components/ContentError';
|
|||||||
import ContentLoading from '../../../components/ContentLoading';
|
import ContentLoading from '../../../components/ContentLoading';
|
||||||
import DeleteButton from '../../../components/DeleteButton';
|
import DeleteButton from '../../../components/DeleteButton';
|
||||||
import ErrorDetail from '../../../components/ErrorDetail';
|
import ErrorDetail from '../../../components/ErrorDetail';
|
||||||
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
|
|
||||||
function OrganizationDetail({ i18n, organization }) {
|
function OrganizationDetail({ i18n, organization }) {
|
||||||
const {
|
const {
|
||||||
@@ -31,7 +32,6 @@ function OrganizationDetail({ i18n, organization }) {
|
|||||||
summary_fields,
|
summary_fields,
|
||||||
} = organization;
|
} = organization;
|
||||||
const [contentError, setContentError] = useState(null);
|
const [contentError, setContentError] = useState(null);
|
||||||
const [deletionError, setDeletionError] = useState(null);
|
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(true);
|
const [hasContentLoading, setHasContentLoading] = useState(true);
|
||||||
const [instanceGroups, setInstanceGroups] = useState([]);
|
const [instanceGroups, setInstanceGroups] = useState([]);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -53,16 +53,18 @@ function OrganizationDetail({ i18n, organization }) {
|
|||||||
})();
|
})();
|
||||||
}, [id]);
|
}, [id]);
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const {
|
||||||
setHasContentLoading(true);
|
request: deleteOrganization,
|
||||||
try {
|
isLoading,
|
||||||
|
error: deleteError,
|
||||||
|
} = useRequest(
|
||||||
|
useCallback(async () => {
|
||||||
await OrganizationsAPI.destroy(id);
|
await OrganizationsAPI.destroy(id);
|
||||||
history.push(`/organizations`);
|
history.push(`/organizations`);
|
||||||
} catch (error) {
|
}, [id, history])
|
||||||
setDeletionError(error);
|
);
|
||||||
}
|
|
||||||
setHasContentLoading(false);
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
};
|
|
||||||
|
|
||||||
if (hasContentLoading) {
|
if (hasContentLoading) {
|
||||||
return <ContentLoading />;
|
return <ContentLoading />;
|
||||||
@@ -127,22 +129,23 @@ function OrganizationDetail({ i18n, organization }) {
|
|||||||
<DeleteButton
|
<DeleteButton
|
||||||
name={name}
|
name={name}
|
||||||
modalTitle={i18n._(t`Delete Organization`)}
|
modalTitle={i18n._(t`Delete Organization`)}
|
||||||
onConfirm={handleDelete}
|
onConfirm={deleteOrganization}
|
||||||
|
isDisabled={isLoading}
|
||||||
>
|
>
|
||||||
{i18n._(t`Delete`)}
|
{i18n._(t`Delete`)}
|
||||||
</DeleteButton>
|
</DeleteButton>
|
||||||
)}
|
)}
|
||||||
</CardActionsRow>
|
</CardActionsRow>
|
||||||
{/* Update delete modal to show dependencies https://github.com/ansible/awx/issues/5546 */}
|
{/* Update delete modal to show dependencies https://github.com/ansible/awx/issues/5546 */}
|
||||||
{deletionError && (
|
{error && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={error}
|
||||||
variant="error"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={dismissError}
|
||||||
>
|
>
|
||||||
{i18n._(t`Failed to delete organization.`)}
|
{i18n._(t`Failed to delete organization.`)}
|
||||||
<ErrorDetail error={deletionError} />
|
<ErrorDetail error={error} />
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
@@ -8,7 +8,6 @@ import { Config } from '../../../contexts/Config';
|
|||||||
|
|
||||||
import AlertModal from '../../../components/AlertModal';
|
import AlertModal from '../../../components/AlertModal';
|
||||||
import { CardBody, CardActionsRow } from '../../../components/Card';
|
import { CardBody, CardActionsRow } from '../../../components/Card';
|
||||||
import ContentLoading from '../../../components/ContentLoading';
|
|
||||||
import DeleteButton from '../../../components/DeleteButton';
|
import DeleteButton from '../../../components/DeleteButton';
|
||||||
import {
|
import {
|
||||||
DetailList,
|
DetailList,
|
||||||
@@ -19,6 +18,7 @@ import ErrorDetail from '../../../components/ErrorDetail';
|
|||||||
import CredentialChip from '../../../components/CredentialChip';
|
import CredentialChip from '../../../components/CredentialChip';
|
||||||
import { ProjectsAPI } from '../../../api';
|
import { ProjectsAPI } from '../../../api';
|
||||||
import { toTitleCase } from '../../../util/strings';
|
import { toTitleCase } from '../../../util/strings';
|
||||||
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
|
|
||||||
function ProjectDetail({ project, i18n }) {
|
function ProjectDetail({ project, i18n }) {
|
||||||
const {
|
const {
|
||||||
@@ -40,20 +40,16 @@ function ProjectDetail({ project, i18n }) {
|
|||||||
scm_url,
|
scm_url,
|
||||||
summary_fields,
|
summary_fields,
|
||||||
} = project;
|
} = project;
|
||||||
const [deletionError, setDeletionError] = useState(null);
|
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(false);
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const { request: deleteProject, isLoading, error: deleteError } = useRequest(
|
||||||
setHasContentLoading(true);
|
useCallback(async () => {
|
||||||
try {
|
|
||||||
await ProjectsAPI.destroy(id);
|
await ProjectsAPI.destroy(id);
|
||||||
history.push(`/projects`);
|
history.push(`/projects`);
|
||||||
} catch (error) {
|
}, [id, history])
|
||||||
setDeletionError(error);
|
);
|
||||||
}
|
|
||||||
setHasContentLoading(false);
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
};
|
|
||||||
|
|
||||||
let optionsList = '';
|
let optionsList = '';
|
||||||
if (
|
if (
|
||||||
@@ -78,10 +74,6 @@ function ProjectDetail({ project, i18n }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasContentLoading) {
|
|
||||||
return <ContentLoading />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<DetailList gutter="sm">
|
<DetailList gutter="sm">
|
||||||
@@ -171,22 +163,23 @@ function ProjectDetail({ project, i18n }) {
|
|||||||
<DeleteButton
|
<DeleteButton
|
||||||
name={name}
|
name={name}
|
||||||
modalTitle={i18n._(t`Delete Project`)}
|
modalTitle={i18n._(t`Delete Project`)}
|
||||||
onConfirm={handleDelete}
|
onConfirm={deleteProject}
|
||||||
|
isDisabled={isLoading}
|
||||||
>
|
>
|
||||||
{i18n._(t`Delete`)}
|
{i18n._(t`Delete`)}
|
||||||
</DeleteButton>
|
</DeleteButton>
|
||||||
)}
|
)}
|
||||||
</CardActionsRow>
|
</CardActionsRow>
|
||||||
{/* Update delete modal to show dependencies https://github.com/ansible/awx/issues/5546 */}
|
{/* Update delete modal to show dependencies https://github.com/ansible/awx/issues/5546 */}
|
||||||
{deletionError && (
|
{error && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={error}
|
||||||
variant="error"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={dismissError}
|
||||||
>
|
>
|
||||||
{i18n._(t`Failed to delete project.`)}
|
{i18n._(t`Failed to delete project.`)}
|
||||||
<ErrorDetail error={deletionError} />
|
<ErrorDetail error={error} />
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Link, useHistory, useParams } from 'react-router-dom';
|
import { Link, useHistory, useParams } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
@@ -6,34 +6,26 @@ import { Button } from '@patternfly/react-core';
|
|||||||
|
|
||||||
import AlertModal from '../../../components/AlertModal';
|
import AlertModal from '../../../components/AlertModal';
|
||||||
import { CardBody, CardActionsRow } from '../../../components/Card';
|
import { CardBody, CardActionsRow } from '../../../components/Card';
|
||||||
import ContentLoading from '../../../components/ContentLoading';
|
|
||||||
import DeleteButton from '../../../components/DeleteButton';
|
import DeleteButton from '../../../components/DeleteButton';
|
||||||
import { DetailList, Detail } from '../../../components/DetailList';
|
import { DetailList, Detail } from '../../../components/DetailList';
|
||||||
import ErrorDetail from '../../../components/ErrorDetail';
|
import ErrorDetail from '../../../components/ErrorDetail';
|
||||||
import { formatDateString } from '../../../util/dates';
|
import { formatDateString } from '../../../util/dates';
|
||||||
import { TeamsAPI } from '../../../api';
|
import { TeamsAPI } from '../../../api';
|
||||||
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
|
|
||||||
function TeamDetail({ team, i18n }) {
|
function TeamDetail({ team, i18n }) {
|
||||||
const { name, description, created, modified, summary_fields } = team;
|
const { name, description, created, modified, summary_fields } = team;
|
||||||
const [deletionError, setDeletionError] = useState(null);
|
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(false);
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const { request: deleteTeam, isLoading, error: deleteError } = useRequest(
|
||||||
setHasContentLoading(true);
|
useCallback(async () => {
|
||||||
try {
|
|
||||||
await TeamsAPI.destroy(id);
|
await TeamsAPI.destroy(id);
|
||||||
history.push(`/teams`);
|
history.push(`/teams`);
|
||||||
} catch (error) {
|
}, [id, history])
|
||||||
setDeletionError(error);
|
);
|
||||||
}
|
|
||||||
setHasContentLoading(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (hasContentLoading) {
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
return <ContentLoading />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardBody>
|
<CardBody>
|
||||||
@@ -74,21 +66,22 @@ function TeamDetail({ team, i18n }) {
|
|||||||
<DeleteButton
|
<DeleteButton
|
||||||
name={name}
|
name={name}
|
||||||
modalTitle={i18n._(t`Delete Team`)}
|
modalTitle={i18n._(t`Delete Team`)}
|
||||||
onConfirm={handleDelete}
|
onConfirm={deleteTeam}
|
||||||
|
isDisabled={isLoading}
|
||||||
>
|
>
|
||||||
{i18n._(t`Delete`)}
|
{i18n._(t`Delete`)}
|
||||||
</DeleteButton>
|
</DeleteButton>
|
||||||
)}
|
)}
|
||||||
</CardActionsRow>
|
</CardActionsRow>
|
||||||
{deletionError && (
|
{error && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={error}
|
||||||
variant="error"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={dismissError}
|
||||||
>
|
>
|
||||||
{i18n._(t`Failed to delete team.`)}
|
{i18n._(t`Failed to delete team.`)}
|
||||||
<ErrorDetail error={deletionError} />
|
<ErrorDetail error={error} />
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
@@ -6,12 +6,12 @@ import { t } from '@lingui/macro';
|
|||||||
import { Button } from '@patternfly/react-core';
|
import { Button } from '@patternfly/react-core';
|
||||||
import AlertModal from '../../../components/AlertModal';
|
import AlertModal from '../../../components/AlertModal';
|
||||||
import { CardBody, CardActionsRow } from '../../../components/Card';
|
import { CardBody, CardActionsRow } from '../../../components/Card';
|
||||||
import ContentLoading from '../../../components/ContentLoading';
|
|
||||||
import DeleteButton from '../../../components/DeleteButton';
|
import DeleteButton from '../../../components/DeleteButton';
|
||||||
import { DetailList, Detail } from '../../../components/DetailList';
|
import { DetailList, Detail } from '../../../components/DetailList';
|
||||||
import ErrorDetail from '../../../components/ErrorDetail';
|
import ErrorDetail from '../../../components/ErrorDetail';
|
||||||
import { formatDateString } from '../../../util/dates';
|
import { formatDateString } from '../../../util/dates';
|
||||||
import { UsersAPI } from '../../../api';
|
import { UsersAPI } from '../../../api';
|
||||||
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
|
|
||||||
function UserDetail({ user, i18n }) {
|
function UserDetail({ user, i18n }) {
|
||||||
const {
|
const {
|
||||||
@@ -26,20 +26,16 @@ function UserDetail({ user, i18n }) {
|
|||||||
is_system_auditor,
|
is_system_auditor,
|
||||||
summary_fields,
|
summary_fields,
|
||||||
} = user;
|
} = user;
|
||||||
const [deletionError, setDeletionError] = useState(null);
|
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(false);
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const handleDelete = async () => {
|
const { request: deleteUser, isLoading, error: deleteError } = useRequest(
|
||||||
setHasContentLoading(true);
|
useCallback(async () => {
|
||||||
try {
|
|
||||||
await UsersAPI.destroy(id);
|
await UsersAPI.destroy(id);
|
||||||
history.push(`/users`);
|
history.push(`/users`);
|
||||||
} catch (error) {
|
}, [id, history])
|
||||||
setDeletionError(error);
|
);
|
||||||
}
|
|
||||||
setHasContentLoading(false);
|
const { error, dismissError } = useDismissableError(deleteError);
|
||||||
};
|
|
||||||
|
|
||||||
let user_type;
|
let user_type;
|
||||||
if (is_superuser) {
|
if (is_superuser) {
|
||||||
@@ -50,10 +46,6 @@ function UserDetail({ user, i18n }) {
|
|||||||
user_type = i18n._(t`Normal User`);
|
user_type = i18n._(t`Normal User`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasContentLoading) {
|
|
||||||
return <ContentLoading />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<DetailList>
|
<DetailList>
|
||||||
@@ -90,21 +82,22 @@ function UserDetail({ user, i18n }) {
|
|||||||
<DeleteButton
|
<DeleteButton
|
||||||
name={username}
|
name={username}
|
||||||
modalTitle={i18n._(t`Delete User`)}
|
modalTitle={i18n._(t`Delete User`)}
|
||||||
onConfirm={handleDelete}
|
onConfirm={deleteUser}
|
||||||
|
isDisabled={isLoading}
|
||||||
>
|
>
|
||||||
{i18n._(t`Delete`)}
|
{i18n._(t`Delete`)}
|
||||||
</DeleteButton>
|
</DeleteButton>
|
||||||
)}
|
)}
|
||||||
</CardActionsRow>
|
</CardActionsRow>
|
||||||
{deletionError && (
|
{error && (
|
||||||
<AlertModal
|
<AlertModal
|
||||||
isOpen={deletionError}
|
isOpen={error}
|
||||||
variant="error"
|
variant="error"
|
||||||
title={i18n._(t`Error!`)}
|
title={i18n._(t`Error!`)}
|
||||||
onClose={() => setDeletionError(null)}
|
onClose={dismissError}
|
||||||
>
|
>
|
||||||
{i18n._(t`Failed to delete user.`)}
|
{i18n._(t`Failed to delete user.`)}
|
||||||
<ErrorDetail error={deletionError} />
|
<ErrorDetail error={error} />
|
||||||
</AlertModal>
|
</AlertModal>
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user