mirror of
https://github.com/ansible/awx.git
synced 2026-03-02 09:18:48 -03:30
Merge pull request #5751 from keithjgrant/5502-inventory-group-refresh
Inventory details refresh Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { string, number } from 'prop-types';
|
import { string, number } from 'prop-types';
|
||||||
import { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core';
|
import { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core';
|
||||||
import { DetailName, DetailValue } from '@components/DetailList';
|
import { DetailName, DetailValue } from '@components/DetailList';
|
||||||
@@ -7,11 +7,30 @@ import CodeMirrorInput from './CodeMirrorInput';
|
|||||||
import YamlJsonToggle from './YamlJsonToggle';
|
import YamlJsonToggle from './YamlJsonToggle';
|
||||||
import { JSON_MODE, YAML_MODE } from './constants';
|
import { JSON_MODE, YAML_MODE } from './constants';
|
||||||
|
|
||||||
|
function getValueAsMode(value, mode) {
|
||||||
|
if (!value) {
|
||||||
|
if (mode === JSON_MODE) {
|
||||||
|
return '{}';
|
||||||
|
}
|
||||||
|
return '---';
|
||||||
|
}
|
||||||
|
const modeMatches = isJson(value) === (mode === JSON_MODE);
|
||||||
|
if (modeMatches) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return mode === YAML_MODE ? jsonToYaml(value) : yamlToJson(value);
|
||||||
|
}
|
||||||
|
|
||||||
function VariablesDetail({ value, label, rows }) {
|
function VariablesDetail({ value, label, rows }) {
|
||||||
const [mode, setMode] = useState(isJson(value) ? JSON_MODE : YAML_MODE);
|
const [mode, setMode] = useState(isJson(value) ? JSON_MODE : YAML_MODE);
|
||||||
const [currentValue, setCurrentValue] = useState(value);
|
const [currentValue, setCurrentValue] = useState(value || '---');
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentValue(getValueAsMode(value, mode));
|
||||||
|
/* eslint-disable-next-line react-hooks/exhaustive-deps */
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DetailName
|
<DetailName
|
||||||
@@ -35,11 +54,7 @@ function VariablesDetail({ value, label, rows }) {
|
|||||||
mode={mode}
|
mode={mode}
|
||||||
onChange={newMode => {
|
onChange={newMode => {
|
||||||
try {
|
try {
|
||||||
const newVal =
|
setCurrentValue(getValueAsMode(currentValue, newMode));
|
||||||
newMode === YAML_MODE
|
|
||||||
? jsonToYaml(currentValue)
|
|
||||||
: yamlToJson(currentValue);
|
|
||||||
setCurrentValue(newVal);
|
|
||||||
setMode(newMode);
|
setMode(newMode);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err);
|
setError(err);
|
||||||
@@ -56,7 +71,7 @@ function VariablesDetail({ value, label, rows }) {
|
|||||||
>
|
>
|
||||||
<CodeMirrorInput
|
<CodeMirrorInput
|
||||||
mode={mode}
|
mode={mode}
|
||||||
value={currentValue || '---'} // When github issue https://github.com/ansible/awx/issues/5502 gets resolved this line of code should be revisited and refactored if possible.
|
value={currentValue}
|
||||||
readOnly
|
readOnly
|
||||||
rows={rows}
|
rows={rows}
|
||||||
css="margin-top: 10px"
|
css="margin-top: 10px"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { act } from 'react-dom/test-utils';
|
||||||
|
import { shallow, mount } from 'enzyme';
|
||||||
import VariablesDetail from './VariablesDetail';
|
import VariablesDetail from './VariablesDetail';
|
||||||
|
|
||||||
jest.mock('@api');
|
jest.mock('@api');
|
||||||
@@ -40,9 +41,42 @@ describe('<VariablesDetail>', () => {
|
|||||||
expect(input2.prop('mode')).toEqual('yaml');
|
expect(input2.prop('mode')).toEqual('yaml');
|
||||||
expect(input2.prop('value')).toEqual('foo: bar\n');
|
expect(input2.prop('value')).toEqual('foo: bar\n');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should render label and value= --- when there are no values', () => {
|
test('should render label and value= --- when there are no values', () => {
|
||||||
const wrapper = shallow(<VariablesDetail value="" label="Variables" />);
|
const wrapper = shallow(<VariablesDetail value="" label="Variables" />);
|
||||||
expect(wrapper.find('Styled(CodeMirrorInput)').length).toBe(1);
|
expect(wrapper.find('Styled(CodeMirrorInput)').length).toBe(1);
|
||||||
expect(wrapper.find('div.pf-c-form__label').text()).toBe('Variables');
|
expect(wrapper.find('div.pf-c-form__label').text()).toBe('Variables');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should update value if prop changes', () => {
|
||||||
|
const wrapper = mount(
|
||||||
|
<VariablesDetail value="---foo: bar" label="Variables" />
|
||||||
|
);
|
||||||
|
act(() => {
|
||||||
|
wrapper.find('YamlJsonToggle').invoke('onChange')('javascript');
|
||||||
|
});
|
||||||
|
wrapper.setProps({
|
||||||
|
value: '---bar: baz',
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
const input = wrapper.find('Styled(CodeMirrorInput)');
|
||||||
|
expect(input.prop('mode')).toEqual('javascript');
|
||||||
|
expect(input.prop('value')).toEqual('{\n "bar": "baz"\n}');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should default yaml value to "---"', () => {
|
||||||
|
const wrapper = shallow(<VariablesDetail value="" label="Variables" />);
|
||||||
|
const input = wrapper.find('Styled(CodeMirrorInput)');
|
||||||
|
expect(input.prop('value')).toEqual('---');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should default empty json to "{}"', () => {
|
||||||
|
const wrapper = mount(<VariablesDetail value="" label="Variables" />);
|
||||||
|
act(() => {
|
||||||
|
wrapper.find('YamlJsonToggle').invoke('onChange')('javascript');
|
||||||
|
});
|
||||||
|
wrapper.setProps({ value: '' });
|
||||||
|
const input = wrapper.find('Styled(CodeMirrorInput)');
|
||||||
|
expect(input.prop('value')).toEqual('{}');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ function Inventory({ i18n, setBreadcrumb }) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
try {
|
try {
|
||||||
|
setHasContentLoading(true);
|
||||||
const { data } = await InventoriesAPI.readDetail(match.params.id);
|
const { data } = await InventoriesAPI.readDetail(match.params.id);
|
||||||
setBreadcrumb(data);
|
setBreadcrumb(data);
|
||||||
setInventory(data);
|
setInventory(data);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useRef } 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,19 +18,29 @@ function InventoryDetail({ inventory, i18n }) {
|
|||||||
const [hasContentLoading, setHasContentLoading] = useState(true);
|
const [hasContentLoading, setHasContentLoading] = useState(true);
|
||||||
const [contentError, setContentError] = useState(null);
|
const [contentError, setContentError] = useState(null);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const isMounted = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
isMounted.current = true;
|
||||||
(async () => {
|
(async () => {
|
||||||
setHasContentLoading(true);
|
setHasContentLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data } = await InventoriesAPI.readInstanceGroups(inventory.id);
|
const { data } = await InventoriesAPI.readInstanceGroups(inventory.id);
|
||||||
|
if (!isMounted.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setInstanceGroups(data.results);
|
setInstanceGroups(data.results);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setContentError(err);
|
setContentError(err);
|
||||||
} finally {
|
} finally {
|
||||||
setHasContentLoading(false);
|
if (isMounted.current) {
|
||||||
|
setHasContentLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
return () => {
|
||||||
|
isMounted.current = false;
|
||||||
|
};
|
||||||
}, [inventory.id]);
|
}, [inventory.id]);
|
||||||
|
|
||||||
const deleteInventory = async () => {
|
const deleteInventory = async () => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { object } from 'prop-types';
|
import { object } from 'prop-types';
|
||||||
|
|
||||||
@@ -15,8 +15,10 @@ function InventoryEdit({ inventory }) {
|
|||||||
const [contentLoading, setContentLoading] = useState(true);
|
const [contentLoading, setContentLoading] = useState(true);
|
||||||
const [credentialTypeId, setCredentialTypeId] = useState(null);
|
const [credentialTypeId, setCredentialTypeId] = useState(null);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const isMounted = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
isMounted.current = true;
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
try {
|
try {
|
||||||
const [
|
const [
|
||||||
@@ -32,15 +34,23 @@ function InventoryEdit({ inventory }) {
|
|||||||
kind: 'insights',
|
kind: 'insights',
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
if (!isMounted.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setInstanceGroups(loadedInstanceGroups);
|
setInstanceGroups(loadedInstanceGroups);
|
||||||
setCredentialTypeId(loadedCredentialTypeId[0].id);
|
setCredentialTypeId(loadedCredentialTypeId[0].id);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err);
|
setError(err);
|
||||||
} finally {
|
} finally {
|
||||||
setContentLoading(false);
|
if (isMounted.current) {
|
||||||
|
setContentLoading(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
loadData();
|
loadData();
|
||||||
|
return () => {
|
||||||
|
isMounted.current = false;
|
||||||
|
};
|
||||||
}, [inventory.id, contentLoading, inventory, credentialTypeId]);
|
}, [inventory.id, contentLoading, inventory, credentialTypeId]);
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user