mirror of
https://github.com/ansible/awx.git
synced 2026-05-13 04:17:36 -02:30
Add order selected list to instance group lookups
This commit is contained in:
committed by
Shane McDonald
parent
f1273d5810
commit
162ea776fd
@@ -1,3 +1,12 @@
|
|||||||
|
function isEqual(array1, array2) {
|
||||||
|
return (
|
||||||
|
array1.length === array2.length &&
|
||||||
|
array1.every((element, index) => {
|
||||||
|
return element.id === array2[index].id;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const InstanceGroupsMixin = parent =>
|
const InstanceGroupsMixin = parent =>
|
||||||
class extends parent {
|
class extends parent {
|
||||||
readInstanceGroups(resourceId, params) {
|
readInstanceGroups(resourceId, params) {
|
||||||
@@ -18,6 +27,19 @@ const InstanceGroupsMixin = parent =>
|
|||||||
disassociate: true,
|
disassociate: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async orderInstanceGroups(resourceId, current, original) {
|
||||||
|
/* eslint-disable no-await-in-loop, no-restricted-syntax */
|
||||||
|
if (!isEqual(current, original)) {
|
||||||
|
for (const group of original) {
|
||||||
|
await this.disassociateInstanceGroup(resourceId, group.id);
|
||||||
|
}
|
||||||
|
for (const group of current) {
|
||||||
|
await this.associateInstanceGroup(resourceId, group.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* eslint-enable no-await-in-loop, no-restricted-syntax */
|
||||||
};
|
};
|
||||||
|
|
||||||
export default InstanceGroupsMixin;
|
export default InstanceGroupsMixin;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect } from 'react';
|
|||||||
import { arrayOf, string, func, bool } from 'prop-types';
|
import { arrayOf, string, func, bool } from 'prop-types';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import { t } from '@lingui/macro';
|
import { t, Trans } from '@lingui/macro';
|
||||||
import { FormGroup } from '@patternfly/react-core';
|
import { FormGroup } from '@patternfly/react-core';
|
||||||
import { InstanceGroupsAPI } from '../../api';
|
import { InstanceGroupsAPI } from '../../api';
|
||||||
import { InstanceGroup } from '../../types';
|
import { InstanceGroup } from '../../types';
|
||||||
@@ -82,6 +82,18 @@ function InstanceGroupsLookup({
|
|||||||
multiple
|
multiple
|
||||||
required={required}
|
required={required}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
modalDescription={
|
||||||
|
<>
|
||||||
|
<b>
|
||||||
|
<Trans>Selected</Trans>
|
||||||
|
</b>
|
||||||
|
<br />
|
||||||
|
<Trans>
|
||||||
|
Note: The order in which these are selected sets the execution
|
||||||
|
precedence.
|
||||||
|
</Trans>
|
||||||
|
</>
|
||||||
|
}
|
||||||
renderOptionsList={({ state, dispatch, canDelete }) => (
|
renderOptionsList={({ state, dispatch, canDelete }) => (
|
||||||
<OptionsList
|
<OptionsList
|
||||||
value={state.selectedItems}
|
value={state.selectedItems}
|
||||||
@@ -113,6 +125,10 @@ function InstanceGroupsLookup({
|
|||||||
readOnly={!canDelete}
|
readOnly={!canDelete}
|
||||||
selectItem={item => dispatch({ type: 'SELECT_ITEM', item })}
|
selectItem={item => dispatch({ type: 'SELECT_ITEM', item })}
|
||||||
deselectItem={item => dispatch({ type: 'DESELECT_ITEM', item })}
|
deselectItem={item => dispatch({ type: 'DESELECT_ITEM', item })}
|
||||||
|
sortSelectedItems={selectedItems =>
|
||||||
|
dispatch({ type: 'SET_SELECTED_ITEMS', selectedItems })
|
||||||
|
}
|
||||||
|
isSelectedDraggable
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -23,12 +23,11 @@ function InventoryAdd() {
|
|||||||
organization: organization.id,
|
organization: organization.id,
|
||||||
...remainingValues,
|
...remainingValues,
|
||||||
});
|
});
|
||||||
if (instanceGroups) {
|
/* eslint-disable no-await-in-loop, no-restricted-syntax */
|
||||||
const associatePromises = instanceGroups.map(async ig =>
|
for (const group of instanceGroups) {
|
||||||
InventoriesAPI.associateInstanceGroup(inventoryId, ig.id)
|
await InventoriesAPI.associateInstanceGroup(inventoryId, group.id);
|
||||||
);
|
|
||||||
await Promise.all(associatePromises);
|
|
||||||
}
|
}
|
||||||
|
/* eslint-enable no-await-in-loop, no-restricted-syntax */
|
||||||
const url = history.location.pathname.startsWith(
|
const url = history.location.pathname.startsWith(
|
||||||
'/inventories/smart_inventory'
|
'/inventories/smart_inventory'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { CardBody } from '../../../components/Card';
|
|||||||
import { InventoriesAPI } from '../../../api';
|
import { InventoriesAPI } from '../../../api';
|
||||||
import ContentLoading from '../../../components/ContentLoading';
|
import ContentLoading from '../../../components/ContentLoading';
|
||||||
import InventoryForm from '../shared/InventoryForm';
|
import InventoryForm from '../shared/InventoryForm';
|
||||||
import { getAddedAndRemoved } from '../../../util/lists';
|
|
||||||
import useIsMounted from '../../../util/useIsMounted';
|
import useIsMounted from '../../../util/useIsMounted';
|
||||||
|
|
||||||
function InventoryEdit({ inventory }) {
|
function InventoryEdit({ inventory }) {
|
||||||
@@ -54,20 +53,12 @@ function InventoryEdit({ inventory }) {
|
|||||||
organization: organization.id,
|
organization: organization.id,
|
||||||
...remainingValues,
|
...remainingValues,
|
||||||
});
|
});
|
||||||
if (instanceGroups) {
|
await InventoriesAPI.orderInstanceGroups(
|
||||||
const { added, removed } = getAddedAndRemoved(
|
inventory.id,
|
||||||
associatedInstanceGroups,
|
instanceGroups,
|
||||||
instanceGroups
|
associatedInstanceGroups
|
||||||
);
|
);
|
||||||
|
|
||||||
const associatePromises = added.map(async ig =>
|
|
||||||
InventoriesAPI.associateInstanceGroup(inventory.id, ig.id)
|
|
||||||
);
|
|
||||||
const disassociatePromises = removed.map(async ig =>
|
|
||||||
InventoriesAPI.disassociateInstanceGroup(inventory.id, ig.id)
|
|
||||||
);
|
|
||||||
await Promise.all([...associatePromises, ...disassociatePromises]);
|
|
||||||
}
|
|
||||||
const url =
|
const url =
|
||||||
history.location.pathname.search('smart') > -1
|
history.location.pathname.search('smart') > -1
|
||||||
? `/inventories/smart_inventory/${inventory.id}/details`
|
? `/inventories/smart_inventory/${inventory.id}/details`
|
||||||
|
|||||||
@@ -106,17 +106,10 @@ describe('<InventoryEdit />', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
await sleep(0);
|
await sleep(0);
|
||||||
instanceGroups.map(IG =>
|
expect(InventoriesAPI.orderInstanceGroups).toHaveBeenCalledWith(
|
||||||
expect(InventoriesAPI.associateInstanceGroup).toHaveBeenCalledWith(
|
mockInventory.id,
|
||||||
1,
|
instanceGroups,
|
||||||
IG.id
|
associatedInstanceGroups
|
||||||
)
|
|
||||||
);
|
|
||||||
associatedInstanceGroups.map(async aIG =>
|
|
||||||
expect(InventoriesAPI.disassociateInstanceGroup).toHaveBeenCalledWith(
|
|
||||||
1,
|
|
||||||
aIG.id
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ function SmartInventoryAdd() {
|
|||||||
data: { id: invId },
|
data: { id: invId },
|
||||||
} = await InventoriesAPI.create(values);
|
} = await InventoriesAPI.create(values);
|
||||||
|
|
||||||
await Promise.all(
|
/* eslint-disable no-await-in-loop, no-restricted-syntax */
|
||||||
groupsToAssociate.map(({ id }) =>
|
for (const group of groupsToAssociate) {
|
||||||
InventoriesAPI.associateInstanceGroup(invId, id)
|
await InventoriesAPI.associateInstanceGroup(invId, group.id);
|
||||||
)
|
}
|
||||||
);
|
/* eslint-enable no-await-in-loop, no-restricted-syntax */
|
||||||
return invId;
|
return invId;
|
||||||
}, [])
|
}, [])
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React, { useCallback, useEffect } from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { Inventory } from '../../../types';
|
import { Inventory } from '../../../types';
|
||||||
import { getAddedAndRemoved } from '../../../util/lists';
|
|
||||||
import useRequest from '../../../util/useRequest';
|
import useRequest from '../../../util/useRequest';
|
||||||
import { InventoriesAPI } from '../../../api';
|
import { InventoriesAPI } from '../../../api';
|
||||||
import { CardBody } from '../../../components/Card';
|
import { CardBody } from '../../../components/Card';
|
||||||
@@ -17,7 +16,7 @@ function SmartInventoryEdit({ inventory }) {
|
|||||||
error: contentError,
|
error: contentError,
|
||||||
isLoading: hasContentLoading,
|
isLoading: hasContentLoading,
|
||||||
request: fetchInstanceGroups,
|
request: fetchInstanceGroups,
|
||||||
result: instanceGroups,
|
result: initialInstanceGroups,
|
||||||
} = useRequest(
|
} = useRequest(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
const {
|
const {
|
||||||
@@ -40,15 +39,10 @@ function SmartInventoryEdit({ inventory }) {
|
|||||||
useCallback(
|
useCallback(
|
||||||
async (values, groupsToAssociate, groupsToDisassociate) => {
|
async (values, groupsToAssociate, groupsToDisassociate) => {
|
||||||
const { data } = await InventoriesAPI.update(inventory.id, values);
|
const { data } = await InventoriesAPI.update(inventory.id, values);
|
||||||
await Promise.all(
|
await InventoriesAPI.orderInstanceGroups(
|
||||||
groupsToAssociate.map(id =>
|
inventory.id,
|
||||||
InventoriesAPI.associateInstanceGroup(inventory.id, id)
|
groupsToAssociate,
|
||||||
)
|
groupsToDisassociate
|
||||||
);
|
|
||||||
await Promise.all(
|
|
||||||
groupsToDisassociate.map(id =>
|
|
||||||
InventoriesAPI.disassociateInstanceGroup(inventory.id, id)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
@@ -68,20 +62,13 @@ function SmartInventoryEdit({ inventory }) {
|
|||||||
const handleSubmit = async form => {
|
const handleSubmit = async form => {
|
||||||
const { instance_groups, organization, ...remainingForm } = form;
|
const { instance_groups, organization, ...remainingForm } = form;
|
||||||
|
|
||||||
const { added, removed } = getAddedAndRemoved(
|
|
||||||
instanceGroups,
|
|
||||||
instance_groups
|
|
||||||
);
|
|
||||||
const addedIds = added.map(({ id }) => id);
|
|
||||||
const removedIds = removed.map(({ id }) => id);
|
|
||||||
|
|
||||||
await submitRequest(
|
await submitRequest(
|
||||||
{
|
{
|
||||||
organization: organization?.id,
|
organization: organization?.id,
|
||||||
...remainingForm,
|
...remainingForm,
|
||||||
},
|
},
|
||||||
addedIds,
|
instance_groups,
|
||||||
removedIds
|
initialInstanceGroups
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,7 +91,7 @@ function SmartInventoryEdit({ inventory }) {
|
|||||||
<CardBody>
|
<CardBody>
|
||||||
<SmartInventoryForm
|
<SmartInventoryForm
|
||||||
inventory={inventory}
|
inventory={inventory}
|
||||||
instanceGroups={instanceGroups}
|
instanceGroups={initialInstanceGroups}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
submitError={submitError}
|
submitError={submitError}
|
||||||
|
|||||||
@@ -104,8 +104,7 @@ describe('<SmartInventoryEdit />', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
expect(InventoriesAPI.update).toHaveBeenCalledTimes(1);
|
expect(InventoriesAPI.update).toHaveBeenCalledTimes(1);
|
||||||
expect(InventoriesAPI.associateInstanceGroup).toHaveBeenCalledTimes(1);
|
expect(InventoriesAPI.orderInstanceGroups).toHaveBeenCalledTimes(1);
|
||||||
expect(InventoriesAPI.disassociateInstanceGroup).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('successful form submission should trigger redirect to details', async () => {
|
test('successful form submission should trigger redirect to details', async () => {
|
||||||
|
|||||||
@@ -41,13 +41,11 @@ function OrganizationAdd() {
|
|||||||
...values,
|
...values,
|
||||||
default_environment: values.default_environment?.id,
|
default_environment: values.default_environment?.id,
|
||||||
});
|
});
|
||||||
await Promise.all(
|
|
||||||
groupsToAssociate.map(id =>
|
|
||||||
OrganizationsAPI.associateInstanceGroup(response.id, id)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
/* eslint-disable no-await-in-loop, no-restricted-syntax */
|
/* eslint-disable no-await-in-loop, no-restricted-syntax */
|
||||||
// Resolve Promises sequentially to maintain order and avoid race condition
|
// Resolve Promises sequentially to maintain order and avoid race condition
|
||||||
|
for (const group of groupsToAssociate) {
|
||||||
|
await OrganizationsAPI.associateInstanceGroup(response.id, group.id);
|
||||||
|
}
|
||||||
for (const credential of values.galaxy_credentials) {
|
for (const credential of values.galaxy_credentials) {
|
||||||
await OrganizationsAPI.associateGalaxyCredential(
|
await OrganizationsAPI.associateGalaxyCredential(
|
||||||
response.id,
|
response.id,
|
||||||
|
|||||||
@@ -95,6 +95,12 @@ describe('<OrganizationAdd />', () => {
|
|||||||
description: 'new description',
|
description: 'new description',
|
||||||
galaxy_credentials: [],
|
galaxy_credentials: [],
|
||||||
};
|
};
|
||||||
|
const mockInstanceGroups = [
|
||||||
|
{
|
||||||
|
name: 'mock ig',
|
||||||
|
id: 3,
|
||||||
|
},
|
||||||
|
];
|
||||||
OrganizationsAPI.create.mockResolvedValueOnce({
|
OrganizationsAPI.create.mockResolvedValueOnce({
|
||||||
data: {
|
data: {
|
||||||
id: 5,
|
id: 5,
|
||||||
@@ -109,7 +115,10 @@ describe('<OrganizationAdd />', () => {
|
|||||||
wrapper = mountWithContexts(<OrganizationAdd />);
|
wrapper = mountWithContexts(<OrganizationAdd />);
|
||||||
});
|
});
|
||||||
await waitForElement(wrapper, 'button[aria-label="Save"]');
|
await waitForElement(wrapper, 'button[aria-label="Save"]');
|
||||||
await wrapper.find('OrganizationForm').prop('onSubmit')(orgData, [3]);
|
await wrapper.find('OrganizationForm').prop('onSubmit')(
|
||||||
|
orgData,
|
||||||
|
mockInstanceGroups
|
||||||
|
);
|
||||||
expect(OrganizationsAPI.associateInstanceGroup).toHaveBeenCalledWith(5, 3);
|
expect(OrganizationsAPI.associateInstanceGroup).toHaveBeenCalledWith(5, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -26,16 +26,12 @@ function OrganizationEdit({ organization }) {
|
|||||||
...values,
|
...values,
|
||||||
default_environment: values.default_environment?.id || null,
|
default_environment: values.default_environment?.id || null,
|
||||||
});
|
});
|
||||||
await Promise.all(
|
await OrganizationsAPI.orderInstanceGroups(
|
||||||
groupsToAssociate.map(id =>
|
organization.id,
|
||||||
OrganizationsAPI.associateInstanceGroup(organization.id, id)
|
groupsToAssociate,
|
||||||
)
|
groupsToDisassociate
|
||||||
);
|
|
||||||
await Promise.all(
|
|
||||||
groupsToDisassociate.map(id =>
|
|
||||||
OrganizationsAPI.disassociateInstanceGroup(organization.id, id)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/* eslint-disable no-await-in-loop, no-restricted-syntax */
|
/* eslint-disable no-await-in-loop, no-restricted-syntax */
|
||||||
// Resolve Promises sequentially to avoid race condition
|
// Resolve Promises sequentially to avoid race condition
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -54,18 +54,34 @@ describe('<OrganizationEdit />', () => {
|
|||||||
name: 'new name',
|
name: 'new name',
|
||||||
description: 'new description',
|
description: 'new description',
|
||||||
};
|
};
|
||||||
|
const newInstanceGroups = [
|
||||||
|
{
|
||||||
|
name: 'mock three',
|
||||||
|
id: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'mock four',
|
||||||
|
id: 4,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const oldInstanceGroups = [
|
||||||
|
{
|
||||||
|
name: 'mock two',
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('OrganizationForm').invoke('onSubmit')(
|
wrapper.find('OrganizationForm').invoke('onSubmit')(
|
||||||
updatedOrgData,
|
updatedOrgData,
|
||||||
[3, 4],
|
newInstanceGroups,
|
||||||
[2]
|
oldInstanceGroups
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
expect(OrganizationsAPI.associateInstanceGroup).toHaveBeenCalledWith(1, 3);
|
expect(OrganizationsAPI.orderInstanceGroups).toHaveBeenCalledWith(
|
||||||
expect(OrganizationsAPI.associateInstanceGroup).toHaveBeenCalledWith(1, 4);
|
mockData.id,
|
||||||
expect(OrganizationsAPI.disassociateInstanceGroup).toHaveBeenCalledWith(
|
newInstanceGroups,
|
||||||
1,
|
oldInstanceGroups
|
||||||
2
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
InstanceGroupsLookup,
|
InstanceGroupsLookup,
|
||||||
ExecutionEnvironmentLookup,
|
ExecutionEnvironmentLookup,
|
||||||
} from '../../../components/Lookup';
|
} from '../../../components/Lookup';
|
||||||
import { getAddedAndRemoved } from '../../../util/lists';
|
|
||||||
import { required, minMaxValue } from '../../../util/validators';
|
import { required, minMaxValue } from '../../../util/validators';
|
||||||
import { FormColumnLayout } from '../../../components/FormLayout';
|
import { FormColumnLayout } from '../../../components/FormLayout';
|
||||||
import CredentialLookup from '../../../components/Lookup/CredentialLookup';
|
import CredentialLookup from '../../../components/Lookup/CredentialLookup';
|
||||||
@@ -143,19 +142,13 @@ function OrganizationForm({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = values => {
|
const handleSubmit = values => {
|
||||||
const { added, removed } = getAddedAndRemoved(
|
|
||||||
initialInstanceGroups,
|
|
||||||
instanceGroups
|
|
||||||
);
|
|
||||||
const addedIds = added.map(({ id }) => id);
|
|
||||||
const removedIds = removed.map(({ id }) => id);
|
|
||||||
if (
|
if (
|
||||||
typeof values.max_hosts !== 'number' ||
|
typeof values.max_hosts !== 'number' ||
|
||||||
values.max_hosts === 'undefined'
|
values.max_hosts === 'undefined'
|
||||||
) {
|
) {
|
||||||
values.max_hosts = 0;
|
values.max_hosts = 0;
|
||||||
}
|
}
|
||||||
onSubmit(values, addedIds, removedIds);
|
onSubmit(values, instanceGroups, initialInstanceGroups);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -258,7 +258,14 @@ describe('<OrganizationForm />', () => {
|
|||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('button[aria-label="Save"]').simulate('click');
|
wrapper.find('button[aria-label="Save"]').simulate('click');
|
||||||
});
|
});
|
||||||
expect(onSubmit).toHaveBeenCalledWith(mockDataForm, [3], [2]);
|
expect(onSubmit).toHaveBeenCalledWith(
|
||||||
|
mockDataForm,
|
||||||
|
[
|
||||||
|
{ name: 'One', id: 1 },
|
||||||
|
{ name: 'Three', id: 3 },
|
||||||
|
],
|
||||||
|
mockInstanceGroups
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('onSubmit does not get called if max_hosts value is out of range', async () => {
|
test('onSubmit does not get called if max_hosts value is out of range', async () => {
|
||||||
@@ -332,8 +339,8 @@ describe('<OrganizationForm />', () => {
|
|||||||
max_hosts: 0,
|
max_hosts: 0,
|
||||||
default_environment: null,
|
default_environment: null,
|
||||||
},
|
},
|
||||||
[],
|
mockInstanceGroups,
|
||||||
[]
|
mockInstanceGroups
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -63,11 +63,12 @@ function JobTemplateAdd() {
|
|||||||
return Promise.all([...associationPromises]);
|
return Promise.all([...associationPromises]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitInstanceGroups(templateId, addedGroups = []) {
|
async function submitInstanceGroups(templateId, addedGroups = []) {
|
||||||
const associatePromises = addedGroups.map(group =>
|
/* eslint-disable no-await-in-loop, no-restricted-syntax */
|
||||||
JobTemplatesAPI.associateInstanceGroup(templateId, group.id)
|
for (const group of addedGroups) {
|
||||||
);
|
await JobTemplatesAPI.associateInstanceGroup(templateId, group.id);
|
||||||
return Promise.all(associatePromises);
|
}
|
||||||
|
/* eslint-enable no-await-in-loop, no-restricted-syntax */
|
||||||
}
|
}
|
||||||
|
|
||||||
function submitCredentials(templateId, credentials = []) {
|
function submitCredentials(templateId, credentials = []) {
|
||||||
|
|||||||
@@ -61,8 +61,12 @@ function JobTemplateEdit({ template, reloadTemplate }) {
|
|||||||
await JobTemplatesAPI.update(template.id, remainingValues);
|
await JobTemplatesAPI.update(template.id, remainingValues);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
submitLabels(labels, template?.organization),
|
submitLabels(labels, template?.organization),
|
||||||
submitInstanceGroups(instanceGroups, initialInstanceGroups),
|
|
||||||
submitCredentials(credentials),
|
submitCredentials(credentials),
|
||||||
|
JobTemplatesAPI.orderInstanceGroups(
|
||||||
|
template.id,
|
||||||
|
instanceGroups,
|
||||||
|
initialInstanceGroups
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
reloadTemplate();
|
reloadTemplate();
|
||||||
history.push(detailsUrl);
|
history.push(detailsUrl);
|
||||||
@@ -93,17 +97,6 @@ function JobTemplateEdit({ template, reloadTemplate }) {
|
|||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitInstanceGroups = async (groups, initialGroups) => {
|
|
||||||
const { added, removed } = getAddedAndRemoved(initialGroups, groups);
|
|
||||||
const disassociatePromises = await removed.map(group =>
|
|
||||||
JobTemplatesAPI.disassociateInstanceGroup(template.id, group.id)
|
|
||||||
);
|
|
||||||
const associatePromises = await added.map(group =>
|
|
||||||
JobTemplatesAPI.associateInstanceGroup(template.id, group.id)
|
|
||||||
);
|
|
||||||
return Promise.all([...disassociatePromises, ...associatePromises]);
|
|
||||||
};
|
|
||||||
|
|
||||||
const submitCredentials = async newCredentials => {
|
const submitCredentials = async newCredentials => {
|
||||||
const { added, removed } = getAddedAndRemoved(
|
const { added, removed } = getAddedAndRemoved(
|
||||||
template.summary_fields.credentials,
|
template.summary_fields.credentials,
|
||||||
|
|||||||
Reference in New Issue
Block a user