mirror of
https://github.com/ansible/awx.git
synced 2026-01-12 02:19:58 -03:30
Merge pull request #10959 from AlexSCorey/10642-MisalignedTableHeaders
Fixes misalignment on template list and advanced search Key dropdown bug
This commit is contained in:
commit
4d1fa4d262
@ -29,6 +29,12 @@ class Users extends Base {
|
||||
});
|
||||
}
|
||||
|
||||
readOrganizationOptions(userId, params) {
|
||||
return this.http.options(`${this.baseUrl}${userId}/organizations/`, {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
readRoles(userId, params) {
|
||||
return this.http.get(`${this.baseUrl}${userId}/roles/`, {
|
||||
params,
|
||||
|
||||
@ -68,7 +68,6 @@ export function HeaderCell({
|
||||
columnIndex,
|
||||
idPrefix,
|
||||
className,
|
||||
alignRight,
|
||||
children,
|
||||
}) {
|
||||
const sort = sortKey
|
||||
@ -83,7 +82,7 @@ export function HeaderCell({
|
||||
id={sortKey ? `${idPrefix}-${sortKey}` : null}
|
||||
className={className}
|
||||
sort={sort}
|
||||
css={alignRight ? 'text-align: right' : null}
|
||||
css={children === 'Actions' ? 'text-align: right' : null}
|
||||
>
|
||||
{children}
|
||||
</Th>
|
||||
|
||||
@ -144,7 +144,7 @@ function CredentialList() {
|
||||
<HeaderRow qsConfig={QS_CONFIG}>
|
||||
<HeaderCell sortKey="name">{t`Name`}</HeaderCell>
|
||||
<HeaderCell>{t`Type`}</HeaderCell>
|
||||
<HeaderCell alignRight>{t`Actions`}</HeaderCell>
|
||||
<HeaderCell>{t`Actions`}</HeaderCell>
|
||||
</HeaderRow>
|
||||
}
|
||||
renderRow={(item, index) => (
|
||||
|
||||
@ -68,7 +68,7 @@ function HostList() {
|
||||
actions: results[1].data.actions,
|
||||
relatedSearchableKeys: (
|
||||
results[1]?.data?.related_search_fields || []
|
||||
).map((val) => val.slice(0, -8)),
|
||||
).map((val) => (val.endsWith('search') ? val.slice(0, -8) : val)),
|
||||
searchableKeys: getSearchableKeys(results[1].data.actions?.GET),
|
||||
};
|
||||
}, [location]),
|
||||
|
||||
@ -95,6 +95,7 @@ describe('<HostList />', () => {
|
||||
GET: {},
|
||||
POST: {},
|
||||
},
|
||||
related_search_fields: ['first_key__search', 'ansible_facts'],
|
||||
},
|
||||
});
|
||||
});
|
||||
@ -121,6 +122,10 @@ describe('<HostList />', () => {
|
||||
});
|
||||
await waitForLoaded(wrapper);
|
||||
|
||||
expect(
|
||||
wrapper.find('PaginatedTable').props().toolbarRelatedSearchableKeys
|
||||
).toStrictEqual(['first_key', 'ansible_facts']);
|
||||
|
||||
expect(HostsAPI.read).toHaveBeenCalled();
|
||||
expect(wrapper.find('HostListItem')).toHaveLength(3);
|
||||
});
|
||||
|
||||
@ -59,7 +59,7 @@ function InventoryHostList() {
|
||||
actions: hostOptions.data.actions,
|
||||
relatedSearchableKeys: (
|
||||
hostOptions?.data?.related_search_fields || []
|
||||
).map((val) => val.slice(0, -8)),
|
||||
).map((val) => (val.endsWith('search') ? val.slice(0, -8) : val)),
|
||||
searchableKeys: getSearchableKeys(hostOptions.data.actions?.GET),
|
||||
};
|
||||
}, [id, search]),
|
||||
|
||||
@ -91,6 +91,7 @@ describe('<InventoryHostList />', () => {
|
||||
GET: {},
|
||||
POST: {},
|
||||
},
|
||||
related_search_fields: ['first_key__search', 'ansible_facts'],
|
||||
},
|
||||
});
|
||||
|
||||
@ -123,6 +124,9 @@ describe('<InventoryHostList />', () => {
|
||||
test('should fetch hosts from api and render them in the list', async () => {
|
||||
expect(InventoriesAPI.readHosts).toHaveBeenCalled();
|
||||
expect(wrapper.find('InventoryHostItem').length).toBe(3);
|
||||
expect(
|
||||
wrapper.find('PaginatedTable').props().toolbarRelatedSearchableKeys
|
||||
).toStrictEqual(['first_key', 'ansible_facts']);
|
||||
});
|
||||
|
||||
test('should render Run Commands button', async () => {
|
||||
|
||||
@ -36,7 +36,14 @@ function InventorySourceList() {
|
||||
const {
|
||||
isLoading,
|
||||
error: fetchError,
|
||||
result: { result, sourceCount, sourceChoices, sourceChoicesOptions },
|
||||
result: {
|
||||
result,
|
||||
sourceCount,
|
||||
sourceChoices,
|
||||
sourceChoicesOptions,
|
||||
searchableKeys,
|
||||
relatedSearchableKeys,
|
||||
},
|
||||
request: fetchSources,
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
@ -50,12 +57,20 @@ function InventorySourceList() {
|
||||
sourceCount: results[0].data.count,
|
||||
sourceChoices: results[1].data.actions.GET.source.choices,
|
||||
sourceChoicesOptions: results[1].data.actions,
|
||||
searchableKeys: Object.keys(results[1].data.actions?.GET || {}).filter(
|
||||
(key) => results[1].data.actions?.GET[key].filterable
|
||||
),
|
||||
relatedSearchableKeys: (
|
||||
results[1]?.data?.related_search_fields || []
|
||||
).map((val) => val.slice(0, -8)),
|
||||
};
|
||||
}, [id, search]),
|
||||
{
|
||||
result: [],
|
||||
sourceCount: 0,
|
||||
sourceChoices: [],
|
||||
searchableKeys: [],
|
||||
relatedSearchableKeys: [],
|
||||
}
|
||||
);
|
||||
|
||||
@ -149,6 +164,8 @@ function InventorySourceList() {
|
||||
<>
|
||||
<PaginatedTable
|
||||
contentError={fetchError}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
hasContentLoading={
|
||||
isLoading ||
|
||||
isDeleteLoading ||
|
||||
|
||||
@ -27,7 +27,10 @@ const QS_CONFIG = getQSConfig('system_job_templates', {
|
||||
const buildSearchKeys = (options) => {
|
||||
const actions = options?.data?.actions?.GET || {};
|
||||
const searchableKeys = getSearchableKeys(actions);
|
||||
const relatedSearchableKeys = options?.data?.related_search_fields || [];
|
||||
|
||||
const relatedSearchableKeys = (
|
||||
options?.data?.related_search_fields || []
|
||||
).map((val) => val.slice(0, -8));
|
||||
|
||||
return { searchableKeys, relatedSearchableKeys };
|
||||
};
|
||||
|
||||
@ -23,17 +23,29 @@ function UserOrganizationList() {
|
||||
const { id: userId } = useParams();
|
||||
|
||||
const {
|
||||
result: { organizations, count },
|
||||
result: { organizations, count, searchableKeys, relatedSearchableKeys },
|
||||
error: contentError,
|
||||
isLoading,
|
||||
request: fetchOrgs,
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const params = parseQueryString(QS_CONFIG, location.search);
|
||||
const {
|
||||
data: { results, count: orgCount },
|
||||
} = await UsersAPI.readOrganizations(userId, params);
|
||||
const [
|
||||
{
|
||||
data: { results, count: orgCount },
|
||||
},
|
||||
actions,
|
||||
] = await Promise.all([
|
||||
UsersAPI.readOrganizations(userId, params),
|
||||
UsersAPI.readOrganizationOptions(),
|
||||
]);
|
||||
return {
|
||||
searchableKeys: Object.keys(actions.data.actions?.GET || {}).filter(
|
||||
(key) => actions.data.actions?.GET[key].filterable
|
||||
),
|
||||
relatedSearchableKeys: (actions?.data?.related_search_fields || []).map(
|
||||
(val) => val.slice(0, -8)
|
||||
),
|
||||
organizations: results,
|
||||
count: orgCount,
|
||||
};
|
||||
@ -41,6 +53,8 @@ function UserOrganizationList() {
|
||||
{
|
||||
organizations: [],
|
||||
count: 0,
|
||||
searchableKeys: [],
|
||||
relatedSearchableKeys: [],
|
||||
}
|
||||
);
|
||||
|
||||
@ -52,6 +66,8 @@ function UserOrganizationList() {
|
||||
<PaginatedTable
|
||||
items={organizations}
|
||||
contentError={contentError}
|
||||
toolbarSearchableKeys={searchableKeys}
|
||||
toolbarRelatedSearchableKeys={relatedSearchableKeys}
|
||||
hasContentLoading={isLoading}
|
||||
itemCount={count}
|
||||
pluralizedItemName={t`Organizations`}
|
||||
|
||||
@ -33,6 +33,9 @@ describe('<UserOrganizationlist />', () => {
|
||||
count: 1,
|
||||
},
|
||||
});
|
||||
UsersAPI.readOrganizationOptions.mockResolvedValue({
|
||||
data: { actions: { GET: {} } },
|
||||
});
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<Route
|
||||
@ -69,5 +72,6 @@ describe('<UserOrganizationlist />', () => {
|
||||
page_size: 20,
|
||||
type: 'organization',
|
||||
});
|
||||
expect(UsersAPI.readOrganizationOptions).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user