1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-31 23:51:09 +03:00

improves isLoading state and removes unnecessary RBAC

This commit is contained in:
Alex Corey 2020-04-30 17:25:14 -04:00
parent 77fd2d677a
commit 1ea924aa13
6 changed files with 32 additions and 145 deletions

View File

@ -6,15 +6,10 @@ class InventorySources extends LaunchUpdateMixin(Base) {
super(http);
this.baseUrl = '/api/v2/inventory_sources/';
this.allowSyncStart = this.allowSyncStart.bind(this);
this.startSyncSource = this.startSyncSource.bind(this);
this.createSyncStart = this.createSyncStart.bind(this);
}
allowSyncStart(sourceId) {
return this.http.get(`${this.baseUrl}${sourceId}/update/`);
}
startSyncSource(sourceId, extraVars) {
createSyncStart(sourceId, extraVars) {
return this.http.post(`${this.baseUrl}${sourceId}/update/`, {
extra_vars: extraVars,
});

View File

@ -5,15 +5,10 @@ class InventoryUpdates extends LaunchUpdateMixin(Base) {
constructor(http) {
super(http);
this.baseUrl = '/api/v2/inventory_updates/';
this.allowSyncCancel = this.allowSyncCancel.bind(this);
this.cancelSyncSource = this.cancelSyncSource.bind(this);
this.createSyncCancel = this.createSyncCancel.bind(this);
}
allowSyncCancel(sourceId) {
return this.http.get(`${this.baseUrl}${sourceId}/cancel/`);
}
cancelSyncSource(sourceId) {
createSyncCancel(sourceId) {
return this.http.post(`${this.baseUrl}${sourceId}/cancel/`);
}
}

View File

@ -25,10 +25,7 @@ function InventorySourceListItem({
detailUrl,
label,
}) {
const [isCancelSyncLoading, setIsCancelSyncLoading] = useState(false);
const [isStartSyncLoading, setIsStartSyncLoading] = useState(false);
const isDisabled = isCancelSyncLoading || isStartSyncLoading;
const [isSyncLoading, setIsSyncLoading] = useState(false);
const generateLastJobTooltip = job => {
return (
@ -53,7 +50,7 @@ function InventorySourceListItem({
<DataListItem aria-labelledby={`check-action-${source.id}`}>
<DataListItemRow>
<DataListCheck
isDisabled={isDisabled}
isDisabled={isSyncLoading}
id={`select-source-${source.id}`}
checked={isSelected}
onChange={onSelect}
@ -99,12 +96,9 @@ function InventorySourceListItem({
>
{source.summary_fields.user_capabilities.start && (
<InventorySourceSyncButton
onCancelSyncLoading={isLoading =>
setIsCancelSyncLoading(isLoading)
}
onStartSyncLoading={isLoading =>
setIsStartSyncLoading(isLoading)
}
onSyncLoading={isLoading => {
setIsSyncLoading(isLoading);
}}
source={source}
/>
)}
@ -113,7 +107,7 @@ function InventorySourceListItem({
aria-label={i18n._(t`Edit Source`)}
variant="plain"
component={Link}
isDisabled={isDisabled}
isDisabled={isSyncLoading}
to={`${detailUrl}/edit`}
>
<PencilAltIcon />

View File

@ -106,6 +106,7 @@ describe('<InventorySourceListItem />', () => {
);
expect(wrapper.find('StatusIcon').length).toBe(0);
});
test('should not render sync buttons', async () => {
const onSelect = jest.fn();
wrapper = mountWithContexts(

View File

@ -9,12 +9,7 @@ import AlertModal from '@components/AlertModal/AlertModal';
import ErrorDetail from '@components/ErrorDetail/ErrorDetail';
import { InventoryUpdatesAPI, InventorySourcesAPI } from '@api';
function InventorySourceSyncButton({
onCancelSyncLoading,
onStartSyncLoading,
source,
i18n,
}) {
function InventorySourceSyncButton({ onSyncLoading, source, i18n }) {
const [updateStatus, setUpdateStatus] = useState(source.status);
const {
@ -23,25 +18,14 @@ function InventorySourceSyncButton({
request: startSyncProcess,
} = useRequest(
useCallback(async () => {
let syncStatus;
const {
data: { can_update },
} = await InventorySourcesAPI.allowSyncStart(source.id);
if (can_update) {
syncStatus = await InventorySourcesAPI.startSyncSource(source.id);
} else {
throw new Error(
i18n._(
t`You do not have permission to start this inventory source sync`
)
);
}
data: { status },
} = await InventorySourcesAPI.createSyncStart(source.id);
setUpdateStatus(syncStatus.data.status);
setUpdateStatus(status);
return syncStatus.data.status;
}, [source.id, i18n]),
return status;
}, [source.id]),
{}
);
@ -58,29 +42,15 @@ function InventorySourceSyncButton({
},
},
} = await InventorySourcesAPI.readDetail(source.id);
const {
data: { can_cancel },
} = await InventoryUpdatesAPI.allowSyncCancel(id);
if (can_cancel) {
await InventoryUpdatesAPI.cancelSyncSource(id);
setUpdateStatus(null);
} else {
throw new Error(
i18n._(
t`You do not have permission to cancel this inventory source sync`
)
);
}
}, [source.id, i18n])
await InventoryUpdatesAPI.createSyncCancel(id);
setUpdateStatus(null);
}, [source.id])
);
useEffect(() => onStartSyncLoading(startSyncLoading), [
onStartSyncLoading,
useEffect(() => onSyncLoading(startSyncLoading || cancelSyncLoading), [
onSyncLoading,
startSyncLoading,
]);
useEffect(() => onCancelSyncLoading(cancelSyncLoading), [
onCancelSyncLoading,
cancelSyncLoading,
]);
@ -131,8 +101,7 @@ function InventorySourceSyncButton({
}
InventorySourceSyncButton.propTypes = {
onCancelSyncLoading: PropTypes.func.isRequired,
onStartSyncLoading: PropTypes.func.isRequired,
onSyncLoading: PropTypes.func.isRequired,
source: PropTypes.shape({}),
};

View File

@ -8,8 +8,7 @@ jest.mock('@api/models/InventoryUpdates');
jest.mock('@api/models/InventorySources');
const source = { id: 1, name: 'Foo', source: 'Source Bar' };
const onCancelSyncLoading = jest.fn();
const onStartSyncLoading = jest.fn();
const onSyncLoading = jest.fn();
describe('<InventorySourceSyncButton />', () => {
let wrapper;
@ -17,8 +16,7 @@ describe('<InventorySourceSyncButton />', () => {
wrapper = mountWithContexts(
<InventorySourceSyncButton
source={source}
onCancelSyncLoading={onCancelSyncLoading}
onStartSyncLoading={onStartSyncLoading}
onSyncLoading={onSyncLoading}
/>
);
});
@ -41,26 +39,21 @@ describe('<InventorySourceSyncButton />', () => {
wrapper = mountWithContexts(
<InventorySourceSyncButton
source={{ status: 'pending', ...source }}
onCancelSyncLoading={onCancelSyncLoading}
onStartSyncLoading={onStartSyncLoading}
onSyncLoading={onSyncLoading}
/>
);
expect(wrapper.find('MinusCircleIcon').length).toBe(1);
});
test('should start sync properly', async () => {
InventorySourcesAPI.allowSyncStart.mockResolvedValue({
data: { can_update: true },
});
InventorySourcesAPI.startSyncSource.mockResolvedValue({
InventorySourcesAPI.createSyncStart.mockResolvedValue({
data: { status: 'pending' },
});
await act(async () =>
wrapper.find('Button[aria-label="Start sync source"]').simulate('click')
);
expect(InventorySourcesAPI.allowSyncStart).toBeCalledWith(1);
expect(InventorySourcesAPI.startSyncSource).toBeCalledWith(1);
expect(InventorySourcesAPI.createSyncStart).toBeCalledWith(1);
wrapper.update();
expect(wrapper.find('Button[aria-label="Cancel sync source"]').length).toBe(
1
@ -70,18 +63,14 @@ describe('<InventorySourceSyncButton />', () => {
InventorySourcesAPI.readDetail.mockResolvedValue({
data: { summary_fields: { current_update: { id: 120 } } },
});
InventoryUpdatesAPI.allowSyncCancel.mockResolvedValue({
data: { can_cancel: true },
});
InventoryUpdatesAPI.cancelSyncSource.mockResolvedValue({
InventoryUpdatesAPI.createSyncCancel.mockResolvedValue({
data: { status: '' },
});
wrapper = mountWithContexts(
<InventorySourceSyncButton
source={{ status: 'pending', ...source }}
onCancelSyncLoading={onCancelSyncLoading}
onStartSyncLoading={onStartSyncLoading}
onSyncLoading={onSyncLoading}
/>
);
expect(wrapper.find('Button[aria-label="Cancel sync source"]').length).toBe(
@ -93,8 +82,7 @@ describe('<InventorySourceSyncButton />', () => {
);
expect(InventorySourcesAPI.readDetail).toBeCalledWith(1);
expect(InventoryUpdatesAPI.allowSyncCancel).toBeCalledWith(120);
expect(InventoryUpdatesAPI.cancelSyncSource).toBeCalledWith(120);
expect(InventoryUpdatesAPI.createSyncCancel).toBeCalledWith(120);
wrapper.update();
@ -102,59 +90,4 @@ describe('<InventorySourceSyncButton />', () => {
1
);
});
test('Should prevent user from starting sync', async () => {
InventorySourcesAPI.allowSyncStart.mockResolvedValue({
data: { can_update: false },
});
InventorySourcesAPI.startSyncSource.mockResolvedValue({
data: { status: 'pending' },
});
await act(async () =>
wrapper.find('Button[aria-label="Start sync source"]').simulate('click')
);
expect(InventorySourcesAPI.allowSyncStart).toBeCalledWith(1);
expect(InventorySourcesAPI.startSyncSource).not.toBeCalledWith();
wrapper.update();
expect(wrapper.find('AlertModal').length).toBe(1);
expect(wrapper.find('Button[aria-label="Start sync source"]').length).toBe(
1
);
});
test('should prevent user from canceling sync', async () => {
InventorySourcesAPI.readDetail.mockResolvedValue({
data: { summary_fields: { current_update: { id: 120 } } },
});
InventoryUpdatesAPI.allowSyncCancel.mockResolvedValue({
data: { can_cancel: false },
});
InventoryUpdatesAPI.cancelSyncSource.mockResolvedValue({
data: { status: '' },
});
wrapper = mountWithContexts(
<InventorySourceSyncButton
source={{ status: 'pending', ...source }}
onCancelSyncLoading={onCancelSyncLoading}
onStartSyncLoading={onStartSyncLoading}
/>
);
expect(wrapper.find('Button[aria-label="Cancel sync source"]').length).toBe(
1
);
await act(async () =>
wrapper.find('Button[aria-label="Cancel sync source"]').simulate('click')
);
expect(InventorySourcesAPI.readDetail).toBeCalledWith(1);
expect(InventoryUpdatesAPI.allowSyncCancel).toBeCalledWith(120);
expect(InventoryUpdatesAPI.cancelSyncSource).not.toBeCalledWith(120);
wrapper.update();
expect(wrapper.find('AlertModal').length).toBe(1);
expect(wrapper.find('Button[aria-label="Cancel sync source"]').length).toBe(
1
);
});
});