mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 18:07:36 -02:30
more ui_next search pr feedback:
- updae .filter().length calls to .find() - fix ProjectList errors
This commit is contained in:
@@ -146,7 +146,7 @@ class AddResourceRole extends React.Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Username`),
|
name: i18n._(t`Username`),
|
||||||
key: 'username',
|
key: 'username',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`First Name`),
|
name: i18n._(t`First Name`),
|
||||||
@@ -155,7 +155,7 @@ class AddResourceRole extends React.Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Last Name`),
|
name: i18n._(t`Last Name`),
|
||||||
key: 'last_name',
|
key: 'last_name',
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const userSortColumns = [
|
const userSortColumns = [
|
||||||
@@ -170,14 +170,14 @@ class AddResourceRole extends React.Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Last Name`),
|
name: i18n._(t`Last Name`),
|
||||||
key: 'last_name',
|
key: 'last_name',
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const teamSearchColumns = [
|
const teamSearchColumns = [
|
||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
|
|||||||
@@ -24,7 +24,11 @@ class SelectResourceStep extends React.Component {
|
|||||||
this.qsConfig = getQSConfig('resource', {
|
this.qsConfig = getQSConfig('resource', {
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 5,
|
page_size: 5,
|
||||||
order_by: `${props.sortColumns.filter(col => col.key === 'name').length ? 'name' : 'username'}`
|
order_by: `${
|
||||||
|
props.sortColumns.filter(col => col.key === 'name').length
|
||||||
|
? 'name'
|
||||||
|
: 'username'
|
||||||
|
}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ describe('<SelectResourceStep />', () => {
|
|||||||
{
|
{
|
||||||
name: 'Username',
|
name: 'Username',
|
||||||
key: 'username',
|
key: 'username',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const sortColumns = [
|
const sortColumns = [
|
||||||
{
|
{
|
||||||
name: 'Username',
|
name: 'Username',
|
||||||
key: 'username'
|
key: 'username',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|||||||
@@ -2,12 +2,16 @@ import React, { Fragment } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import { Checkbox } from '@patternfly/react-core';
|
||||||
Checkbox,
|
|
||||||
} from '@patternfly/react-core';
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { SearchIcon } from '@patternfly/react-icons';
|
import { SearchIcon } from '@patternfly/react-icons';
|
||||||
import { DataToolbar, DataToolbarContent, DataToolbarGroup, DataToolbarToggleGroup, DataToolbarItem } from '@patternfly/react-core/dist/umd/experimental';
|
import {
|
||||||
|
DataToolbar,
|
||||||
|
DataToolbarContent,
|
||||||
|
DataToolbarGroup,
|
||||||
|
DataToolbarToggleGroup,
|
||||||
|
DataToolbarItem,
|
||||||
|
} from '@patternfly/react-core/dist/umd/experimental';
|
||||||
import ExpandCollapse from '../ExpandCollapse';
|
import ExpandCollapse from '../ExpandCollapse';
|
||||||
import Search from '../Search';
|
import Search from '../Search';
|
||||||
import Sort from '../Sort';
|
import Sort from '../Sort';
|
||||||
@@ -60,7 +64,8 @@ class DataListToolbar extends React.Component {
|
|||||||
|
|
||||||
const showExpandCollapse = onCompact && onExpand;
|
const showExpandCollapse = onCompact && onExpand;
|
||||||
return (
|
return (
|
||||||
<DataToolbar id={`${qsConfig.namespace}-list-toolbar`}
|
<DataToolbar
|
||||||
|
id={`${qsConfig.namespace}-list-toolbar`}
|
||||||
clearAllFilters={clearAllFilters}
|
clearAllFilters={clearAllFilters}
|
||||||
collapseListedFiltersBreakpoint="xl"
|
collapseListedFiltersBreakpoint="xl"
|
||||||
>
|
>
|
||||||
@@ -89,11 +94,7 @@ class DataListToolbar extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</DataToolbarItem>
|
</DataToolbarItem>
|
||||||
<DataToolbarItem>
|
<DataToolbarItem>
|
||||||
<Sort
|
<Sort qsConfig={qsConfig} columns={sortColumns} onSort={onSort} />
|
||||||
qsConfig={qsConfig}
|
|
||||||
columns={sortColumns}
|
|
||||||
onSort={onSort}
|
|
||||||
/>
|
|
||||||
</DataToolbarItem>
|
</DataToolbarItem>
|
||||||
</DataToolbarToggleGroup>
|
</DataToolbarToggleGroup>
|
||||||
<DataToolbarGroup>
|
<DataToolbarGroup>
|
||||||
|
|||||||
@@ -25,12 +25,8 @@ describe('<DataListToolbar />', () => {
|
|||||||
const onSelectAll = jest.fn();
|
const onSelectAll = jest.fn();
|
||||||
|
|
||||||
test('it triggers the expected callbacks', () => {
|
test('it triggers the expected callbacks', () => {
|
||||||
const searchColumns = [
|
const searchColumns = [{ name: 'Name', key: 'name', isDefault: true }];
|
||||||
{ name: 'Name', key: 'name', isDefault: true }
|
const sortColumns = [{ name: 'Name', key: 'name' }];
|
||||||
];
|
|
||||||
const sortColumns = [
|
|
||||||
{ name: 'Name', key: 'name' }
|
|
||||||
];
|
|
||||||
const search = 'button[aria-label="Search submit button"]';
|
const search = 'button[aria-label="Search submit button"]';
|
||||||
const searchTextInput = 'input[aria-label="Search text input"]';
|
const searchTextInput = 'input[aria-label="Search text input"]';
|
||||||
const selectAll = 'input[aria-label="Select all"]';
|
const selectAll = 'input[aria-label="Select all"]';
|
||||||
@@ -86,12 +82,12 @@ describe('<DataListToolbar />', () => {
|
|||||||
|
|
||||||
const searchColumns = [
|
const searchColumns = [
|
||||||
{ name: 'Foo', key: 'foo', isDefault: true },
|
{ name: 'Foo', key: 'foo', isDefault: true },
|
||||||
{ name: 'Bar', key: 'bar' }
|
{ name: 'Bar', key: 'bar' },
|
||||||
];
|
];
|
||||||
const sortColumns = [
|
const sortColumns = [
|
||||||
{ name: 'Foo', key: 'foo' },
|
{ name: 'Foo', key: 'foo' },
|
||||||
{ name: 'Bar', key: 'bar' },
|
{ name: 'Bar', key: 'bar' },
|
||||||
{ name: 'Bakery', key: 'Bakery' }
|
{ name: 'Bakery', key: 'Bakery' },
|
||||||
];
|
];
|
||||||
|
|
||||||
toolbar = mountWithContexts(
|
toolbar = mountWithContexts(
|
||||||
@@ -189,17 +185,13 @@ describe('<DataListToolbar />', () => {
|
|||||||
const downAlphaIconSelector = 'SortAlphaDownIcon';
|
const downAlphaIconSelector = 'SortAlphaDownIcon';
|
||||||
const upAlphaIconSelector = 'SortAlphaUpIcon';
|
const upAlphaIconSelector = 'SortAlphaUpIcon';
|
||||||
|
|
||||||
const numericColumns = [
|
const numericColumns = [{ name: 'ID', key: 'id' }];
|
||||||
{ name: 'ID', key: 'id' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const alphaColumns = [
|
const alphaColumns = [{ name: 'Name', key: 'name' }];
|
||||||
{ name: 'Name', key: 'name' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const searchColumns = [
|
const searchColumns = [
|
||||||
{ name: 'Name', key: 'name', isDefault: true },
|
{ name: 'Name', key: 'name', isDefault: true },
|
||||||
{ name: 'ID', key: 'id' }
|
{ name: 'ID', key: 'id' },
|
||||||
];
|
];
|
||||||
|
|
||||||
toolbar = mountWithContexts(
|
toolbar = mountWithContexts(
|
||||||
@@ -248,12 +240,8 @@ describe('<DataListToolbar />', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should render additionalControls', () => {
|
test('should render additionalControls', () => {
|
||||||
const searchColumns = [
|
const searchColumns = [{ name: 'Name', key: 'name', isDefault: true }];
|
||||||
{ name: 'Name', key: 'name', isDefault: true }
|
const sortColumns = [{ name: 'Name', key: 'name' }];
|
||||||
];
|
|
||||||
const sortColumns = [
|
|
||||||
{ name: 'Name', key: 'name' }
|
|
||||||
];
|
|
||||||
|
|
||||||
toolbar = mountWithContexts(
|
toolbar = mountWithContexts(
|
||||||
<DataListToolbar
|
<DataListToolbar
|
||||||
@@ -278,12 +266,8 @@ describe('<DataListToolbar />', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('it triggers the expected callbacks', () => {
|
test('it triggers the expected callbacks', () => {
|
||||||
const searchColumns = [
|
const searchColumns = [{ name: 'Name', key: 'name', isDefault: true }];
|
||||||
{ name: 'Name', key: 'name', isDefault: true }
|
const sortColumns = [{ name: 'Name', key: 'name' }];
|
||||||
];
|
|
||||||
const sortColumns = [
|
|
||||||
{ name: 'Name', key: 'name' }
|
|
||||||
];
|
|
||||||
toolbar = mountWithContexts(
|
toolbar = mountWithContexts(
|
||||||
<DataListToolbar
|
<DataListToolbar
|
||||||
qsConfig={QS_CONFIG}
|
qsConfig={QS_CONFIG}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import React, { Fragment } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { DataToolbar, DataToolbarContent } from '@patternfly/react-core/dist/umd/experimental';
|
import {
|
||||||
|
DataToolbar,
|
||||||
|
DataToolbarContent,
|
||||||
|
} from '@patternfly/react-core/dist/umd/experimental';
|
||||||
import DataListToolbar from '@components/DataListToolbar';
|
import DataListToolbar from '@components/DataListToolbar';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -40,7 +43,7 @@ class ListHeader extends React.Component {
|
|||||||
const { location, qsConfig } = this.props;
|
const { location, qsConfig } = this.props;
|
||||||
let params = parseQueryString(qsConfig, location.search);
|
let params = parseQueryString(qsConfig, location.search);
|
||||||
params = mergeParams(params, { [key]: value });
|
params = mergeParams(params, { [key]: value });
|
||||||
params = replaceParams(params, { 'page' : 1 })
|
params = replaceParams(params, { page: 1 });
|
||||||
this.pushHistoryState(params);
|
this.pushHistoryState(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +57,9 @@ class ListHeader extends React.Component {
|
|||||||
const { location, qsConfig } = this.props;
|
const { location, qsConfig } = this.props;
|
||||||
let oldParams = parseQueryString(qsConfig, location.search);
|
let oldParams = parseQueryString(qsConfig, location.search);
|
||||||
if (parseInt(value, 10)) {
|
if (parseInt(value, 10)) {
|
||||||
oldParams = removeParams(qsConfig, oldParams, { [key]: parseInt(value, 10) });
|
oldParams = removeParams(qsConfig, oldParams, {
|
||||||
|
[key]: parseInt(value, 10),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.pushHistoryState(removeParams(qsConfig, oldParams, { [key]: value }));
|
this.pushHistoryState(removeParams(qsConfig, oldParams, { [key]: value }));
|
||||||
}
|
}
|
||||||
@@ -96,7 +101,8 @@ class ListHeader extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{isEmpty ? (
|
{isEmpty ? (
|
||||||
<DataToolbar id={`${qsConfig.namespace}-list-toolbar`}
|
<DataToolbar
|
||||||
|
id={`${qsConfig.namespace}-list-toolbar`}
|
||||||
clearAllFilters={this.handleRemoveAll}
|
clearAllFilters={this.handleRemoveAll}
|
||||||
collapseListedFiltersBreakpoint="md"
|
collapseListedFiltersBreakpoint="md"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -16,12 +16,8 @@ describe('ListHeader', () => {
|
|||||||
<ListHeader
|
<ListHeader
|
||||||
itemCount={50}
|
itemCount={50}
|
||||||
qsConfig={qsConfig}
|
qsConfig={qsConfig}
|
||||||
searchColumns={[
|
searchColumns={[{ name: 'foo', key: 'foo', isDefault: true }]}
|
||||||
{ name: 'foo', key: 'foo', isDefault: true},
|
sortColumns={[{ name: 'foo', key: 'foo' }]}
|
||||||
]}
|
|
||||||
sortColumns={[
|
|
||||||
{ name: 'foo', key: 'foo'},
|
|
||||||
]}
|
|
||||||
renderToolbar={renderToolbarFn}
|
renderToolbar={renderToolbarFn}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -37,12 +33,8 @@ describe('ListHeader', () => {
|
|||||||
<ListHeader
|
<ListHeader
|
||||||
itemCount={7}
|
itemCount={7}
|
||||||
qsConfig={qsConfig}
|
qsConfig={qsConfig}
|
||||||
searchColumns={[
|
searchColumns={[{ name: 'foo', key: 'foo', isDefault: true }]}
|
||||||
{ name: 'foo', key: 'foo', isDefault: true},
|
sortColumns={[{ name: 'foo', key: 'foo' }]}
|
||||||
]}
|
|
||||||
sortColumns={[
|
|
||||||
{ name: 'foo', key: 'foo'},
|
|
||||||
]}
|
|
||||||
/>,
|
/>,
|
||||||
{ context: { router: { history } } }
|
{ context: { router: { history } } }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ function CredentialLookup({
|
|||||||
credentialTypeId,
|
credentialTypeId,
|
||||||
value,
|
value,
|
||||||
history,
|
history,
|
||||||
i18n
|
i18n,
|
||||||
}) {
|
}) {
|
||||||
const [credentials, setCredentials] = useState([]);
|
const [credentials, setCredentials] = useState([]);
|
||||||
const [count, setCount] = useState(0);
|
const [count, setCount] = useState(0);
|
||||||
@@ -79,7 +79,7 @@ function CredentialLookup({
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
@@ -88,12 +88,14 @@ function CredentialLookup({
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Modified By (Username)`),
|
name: i18n._(t`Modified By (Username)`),
|
||||||
key: 'modified_by__username',
|
key: 'modified_by__username',
|
||||||
}
|
},
|
||||||
|
]}
|
||||||
|
sortColumns={[
|
||||||
|
{
|
||||||
|
name: i18n._(t`Name`),
|
||||||
|
key: 'name',
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
sortColumns={[{
|
|
||||||
name: i18n._(t`Name`),
|
|
||||||
key: 'name'
|
|
||||||
}]}
|
|
||||||
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 })}
|
||||||
|
|||||||
@@ -68,11 +68,11 @@ function InstanceGroupsLookup(props) {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Credential Name`),
|
name: i18n._(t`Credential Name`),
|
||||||
key: 'credential__name'
|
key: 'credential__name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
@@ -83,10 +83,12 @@ function InstanceGroupsLookup(props) {
|
|||||||
key: 'modified_by__username',
|
key: 'modified_by__username',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
sortColumns={[{
|
sortColumns={[
|
||||||
name: i18n._(t`Name`),
|
{
|
||||||
key: 'name'
|
name: i18n._(t`Name`),
|
||||||
}]}
|
key: 'name',
|
||||||
|
},
|
||||||
|
]}
|
||||||
multiple={state.multiple}
|
multiple={state.multiple}
|
||||||
header={i18n._(t`Instance Groups`)}
|
header={i18n._(t`Instance Groups`)}
|
||||||
name="instanceGroups"
|
name="instanceGroups"
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ function InventoryLookup({
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ function MultiCredentialsLookup(props) {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
@@ -137,10 +137,12 @@ function MultiCredentialsLookup(props) {
|
|||||||
key: 'modified_by__username',
|
key: 'modified_by__username',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
sortColumns={[{
|
sortColumns={[
|
||||||
name: i18n._(t`Name`),
|
{
|
||||||
key: 'name'
|
name: i18n._(t`Name`),
|
||||||
}]}
|
key: 'name',
|
||||||
|
},
|
||||||
|
]}
|
||||||
multiple={isMultiple}
|
multiple={isMultiple}
|
||||||
header={i18n._(t`Credentials`)}
|
header={i18n._(t`Credentials`)}
|
||||||
name="credentials"
|
name="credentials"
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ function OrganizationLookup({
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
@@ -85,10 +85,12 @@ function OrganizationLookup({
|
|||||||
key: 'modified_by__username',
|
key: 'modified_by__username',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
sortColumns={[{
|
sortColumns={[
|
||||||
name: i18n._(t`Name`),
|
{
|
||||||
key: 'name'
|
name: i18n._(t`Name`),
|
||||||
}]}
|
key: 'name',
|
||||||
|
},
|
||||||
|
]}
|
||||||
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 })}
|
||||||
|
|||||||
@@ -74,32 +74,17 @@ function ProjectLookup({
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Type`),
|
name: i18n._(t`Type`),
|
||||||
options: [
|
options: [
|
||||||
[
|
[``, i18n._(t`Manual`)],
|
||||||
``,
|
[`git`, i18n._(t`Git`)],
|
||||||
i18n._(t`Manual`)
|
[`hg`, i18n._(t`Mercurial`)],
|
||||||
],
|
[`svn`, i18n._(t`Subversion`)],
|
||||||
[
|
[`insights`, i18n._(t`Red Hat Insights`)],
|
||||||
`git`,
|
],
|
||||||
i18n._(t`Git`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`hg`,
|
|
||||||
i18n._(t`Mercurial`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`svn`,
|
|
||||||
i18n._(t`Subversion`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`insights`,
|
|
||||||
i18n._(t`Red Hat Insights`)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`SCM URL`),
|
name: i18n._(t`SCM URL`),
|
||||||
@@ -118,7 +103,7 @@ function ProjectLookup({
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
options={projects}
|
options={projects}
|
||||||
optionCount={count}
|
optionCount={count}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ OptionsList.defaultProps = {
|
|||||||
multiple: false,
|
multiple: false,
|
||||||
renderItemChip: null,
|
renderItemChip: null,
|
||||||
searchColumns: [],
|
searchColumns: [],
|
||||||
sortColumns: []
|
sortColumns: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withI18n()(OptionsList);
|
export default withI18n()(OptionsList);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ describe('<OptionsList />', () => {
|
|||||||
value={[]}
|
value={[]}
|
||||||
options={options}
|
options={options}
|
||||||
optionCount={3}
|
optionCount={3}
|
||||||
searchColumns={[{name: 'Foo', key: 'foo', isDefault: true}]}
|
searchColumns={[{ name: 'Foo', key: 'foo', isDefault: true }]}
|
||||||
sortColumns={[{ name: 'Foo', key: 'foo' }]}
|
sortColumns={[{ name: 'Foo', key: 'foo' }]}
|
||||||
qsConfig={qsConfig}
|
qsConfig={qsConfig}
|
||||||
selectItem={() => {}}
|
selectItem={() => {}}
|
||||||
@@ -40,7 +40,7 @@ describe('<OptionsList />', () => {
|
|||||||
value={[options[1]]}
|
value={[options[1]]}
|
||||||
options={options}
|
options={options}
|
||||||
optionCount={3}
|
optionCount={3}
|
||||||
searchColumns={[{name: 'Foo', key: 'foo', isDefault: true}]}
|
searchColumns={[{ name: 'Foo', key: 'foo', isDefault: true }]}
|
||||||
sortColumns={[{ name: 'Foo', key: 'foo' }]}
|
sortColumns={[{ name: 'Foo', key: 'foo' }]}
|
||||||
qsConfig={qsConfig}
|
qsConfig={qsConfig}
|
||||||
selectItem={() => {}}
|
selectItem={() => {}}
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ class NotificationList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Type`),
|
name: i18n._(t`Type`),
|
||||||
@@ -218,7 +218,7 @@ class NotificationList extends Component {
|
|||||||
['slack', i18n._(t`Slack`)],
|
['slack', i18n._(t`Slack`)],
|
||||||
['twilio', i18n._(t`Twilio`)],
|
['twilio', i18n._(t`Twilio`)],
|
||||||
['webhook', i18n._(t`Webhook`)],
|
['webhook', i18n._(t`Webhook`)],
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class PaginatedDataList extends React.Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const sortColumns = toolbarSortColumns.length
|
const sortColumns = toolbarSortColumns.length
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class ResourceAccessList extends React.Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Username`),
|
name: i18n._(t`Username`),
|
||||||
key: 'username',
|
key: 'username',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`First Name`),
|
name: i18n._(t`First Name`),
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
DataToolbarGroup,
|
DataToolbarGroup,
|
||||||
DataToolbarItem,
|
DataToolbarItem,
|
||||||
DataToolbarFilter
|
DataToolbarFilter,
|
||||||
} from '@patternfly/react-core/dist/umd/experimental';
|
} from '@patternfly/react-core/dist/umd/experimental';
|
||||||
import { SearchIcon } from '@patternfly/react-icons';
|
import { SearchIcon } from '@patternfly/react-icons';
|
||||||
import { parseQueryString } from '@util/qs';
|
import { parseQueryString } from '@util/qs';
|
||||||
@@ -44,7 +44,7 @@ class Search extends React.Component {
|
|||||||
isSearchDropdownOpen: false,
|
isSearchDropdownOpen: false,
|
||||||
searchKey: columns.find(col => col.isDefault).key,
|
searchKey: columns.find(col => col.isDefault).key,
|
||||||
searchValue: '',
|
searchValue: '',
|
||||||
isFilterDropdownOpen: false
|
isFilterDropdownOpen: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleSearchInputChange = this.handleSearchInputChange.bind(this);
|
this.handleSearchInputChange = this.handleSearchInputChange.bind(this);
|
||||||
@@ -52,8 +52,12 @@ class Search extends React.Component {
|
|||||||
this.handleDropdownSelect = this.handleDropdownSelect.bind(this);
|
this.handleDropdownSelect = this.handleDropdownSelect.bind(this);
|
||||||
this.handleSearch = this.handleSearch.bind(this);
|
this.handleSearch = this.handleSearch.bind(this);
|
||||||
this.handleTextKeyDown = this.handleTextKeyDown.bind(this);
|
this.handleTextKeyDown = this.handleTextKeyDown.bind(this);
|
||||||
this.handleFilterDropdownToggle = this.handleFilterDropdownToggle.bind(this);
|
this.handleFilterDropdownToggle = this.handleFilterDropdownToggle.bind(
|
||||||
this.handleFilterDropdownSelect = this.handleFilterDropdownSelect.bind(this);
|
this
|
||||||
|
);
|
||||||
|
this.handleFilterDropdownSelect = this.handleFilterDropdownSelect.bind(
|
||||||
|
this
|
||||||
|
);
|
||||||
this.handleFilterBooleanSelect = this.handleFilterBooleanSelect.bind(this);
|
this.handleFilterBooleanSelect = this.handleFilterBooleanSelect.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +81,8 @@ class Search extends React.Component {
|
|||||||
const { onSearch, qsConfig } = this.props;
|
const { onSearch, qsConfig } = this.props;
|
||||||
|
|
||||||
const isNonStringField =
|
const isNonStringField =
|
||||||
qsConfig.integerFields.filter(field => field === searchKey).length ||
|
qsConfig.integerFields.find(field => field === searchKey) ||
|
||||||
qsConfig.dateFields.filter(field => field === searchKey).length;
|
qsConfig.dateFields.find(field => field === searchKey);
|
||||||
|
|
||||||
const actualSearchKey = isNonStringField
|
const actualSearchKey = isNonStringField
|
||||||
? searchKey
|
? searchKey
|
||||||
@@ -121,7 +125,12 @@ class Search extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const { up } = DropdownPosition;
|
const { up } = DropdownPosition;
|
||||||
const { columns, i18n, onRemove, qsConfig, location } = this.props;
|
const { columns, i18n, onRemove, qsConfig, location } = this.props;
|
||||||
const { isSearchDropdownOpen, searchKey, searchValue, isFilterDropdownOpen } = this.state;
|
const {
|
||||||
|
isSearchDropdownOpen,
|
||||||
|
searchKey,
|
||||||
|
searchValue,
|
||||||
|
isFilterDropdownOpen,
|
||||||
|
} = this.state;
|
||||||
const { name: searchColumnName } = columns.find(
|
const { name: searchColumnName } = columns.find(
|
||||||
({ key }) => key === searchKey
|
({ key }) => key === searchKey
|
||||||
);
|
);
|
||||||
@@ -143,8 +152,8 @@ class Search extends React.Component {
|
|||||||
const queryParams = parseQueryString(qsConfig, location.search);
|
const queryParams = parseQueryString(qsConfig, location.search);
|
||||||
|
|
||||||
const queryParamsByKey = {};
|
const queryParamsByKey = {};
|
||||||
columns.forEach(({name, key}) => {
|
columns.forEach(({ name, key }) => {
|
||||||
queryParamsByKey[key] = {key, label: name, chips: []};
|
queryParamsByKey[key] = { key, label: name, chips: [] };
|
||||||
});
|
});
|
||||||
const nonDefaultParams = filterDefaultParams(
|
const nonDefaultParams = filterDefaultParams(
|
||||||
Object.keys(queryParams || {}),
|
Object.keys(queryParams || {}),
|
||||||
@@ -152,12 +161,13 @@ class Search extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
nonDefaultParams.forEach(key => {
|
nonDefaultParams.forEach(key => {
|
||||||
const columnKey = key
|
const columnKey = key.replace('__icontains', '').replace('or__', '');
|
||||||
.replace('__icontains', '')
|
const label = columns.filter(
|
||||||
.replace('or__', '');
|
({ key: keyToCheck }) => columnKey === keyToCheck
|
||||||
const label = columns
|
).length
|
||||||
.filter(({key: keyToCheck}) => columnKey === keyToCheck).length ? columns
|
? columns.filter(({ key: keyToCheck }) => columnKey === keyToCheck)[0]
|
||||||
.filter(({key: keyToCheck}) => columnKey === keyToCheck)[0].name : columnKey;
|
.name
|
||||||
|
: columnKey;
|
||||||
|
|
||||||
queryParamsByKey[columnKey] = { key, label, chips: [] };
|
queryParamsByKey[columnKey] = { key, label, chips: [] };
|
||||||
|
|
||||||
@@ -171,7 +181,7 @@ class Search extends React.Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return queryParamsByKey;
|
return queryParamsByKey;
|
||||||
}
|
};
|
||||||
|
|
||||||
const chipsByKey = getChipsByKey();
|
const chipsByKey = getChipsByKey();
|
||||||
|
|
||||||
@@ -179,7 +189,7 @@ class Search extends React.Component {
|
|||||||
<DataToolbarGroup variant="filter-group">
|
<DataToolbarGroup variant="filter-group">
|
||||||
<DataToolbarItem>
|
<DataToolbarItem>
|
||||||
{searchDropdownItems.length > 0 ? (
|
{searchDropdownItems.length > 0 ? (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
onToggle={this.handleDropdownToggle}
|
onToggle={this.handleDropdownToggle}
|
||||||
onSelect={this.handleDropdownSelect}
|
onSelect={this.handleDropdownSelect}
|
||||||
direction={up}
|
direction={up}
|
||||||
@@ -195,68 +205,90 @@ class Search extends React.Component {
|
|||||||
isOpen={isSearchDropdownOpen}
|
isOpen={isSearchDropdownOpen}
|
||||||
dropdownItems={searchDropdownItems}
|
dropdownItems={searchDropdownItems}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
/>) : (<NoOptionDropdown>{searchColumnName}</NoOptionDropdown>)}
|
|
||||||
</DataToolbarItem>
|
|
||||||
{columns.map(({ key, name, options, isBoolean }) => (<DataToolbarFilter
|
|
||||||
chips={chipsByKey[key] ? chipsByKey[key].chips : []}
|
|
||||||
deleteChip={(unusedKey, val) => { onRemove(chipsByKey[key].key, val) }}
|
|
||||||
categoryName={chipsByKey[key] ? chipsByKey[key].label : key}
|
|
||||||
key={key}
|
|
||||||
showToolbarItem={searchKey === key}
|
|
||||||
>
|
|
||||||
{options && (<Select
|
|
||||||
variant={SelectVariant.checkbox}
|
|
||||||
aria-label={name}
|
|
||||||
onToggle={this.handleFilterDropdownToggle}
|
|
||||||
onSelect={(event, selection) => this.handleFilterDropdownSelect(key, event, selection)}
|
|
||||||
selections={chipsByKey[key].chips}
|
|
||||||
isExpanded={isFilterDropdownOpen}
|
|
||||||
placeholderText={`Filter by ${name.toLowerCase()}`}
|
|
||||||
>
|
|
||||||
{options.map(([optionKey]) => (
|
|
||||||
<Fragment key={optionKey}>
|
|
||||||
{ /* TODO: update value to being object
|
|
||||||
{ actualValue: optionKey, toString: () => label }
|
|
||||||
currently a pf bug that makes the checked logic
|
|
||||||
not work with object-based values */ }
|
|
||||||
<SelectOption key={optionKey} value={optionKey} />
|
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</Select>) || isBoolean && (
|
|
||||||
<Select
|
|
||||||
aria-label={name}
|
|
||||||
onToggle={this.handleFilterDropdownToggle}
|
|
||||||
onSelect={(event, selection) => this.handleFilterBooleanSelect(key, selection)}
|
|
||||||
selections={chipsByKey[key].chips[0]}
|
|
||||||
isExpanded={isFilterDropdownOpen}
|
|
||||||
placeholderText={`Filter by ${name.toLowerCase()}`}
|
|
||||||
>
|
|
||||||
{ /* TODO: update value to being object
|
|
||||||
{ actualValue: optionKey, toString: () => label }
|
|
||||||
currently a pf bug that makes the checked logic
|
|
||||||
not work with object-based values */ }
|
|
||||||
<SelectOption key="true" value="true" />
|
|
||||||
<SelectOption key="false" value="false" />
|
|
||||||
</Select>
|
|
||||||
) || (<InputGroup>
|
|
||||||
{/* TODO: add support for dates:
|
|
||||||
qsConfig.dateFields.filter(field => field === key).length && "date" */}
|
|
||||||
<TextInput
|
|
||||||
type={qsConfig.integerFields.filter(field => field === key).length && "number" || "search"}
|
|
||||||
aria-label={i18n._(t`Search text input`)}
|
|
||||||
value={searchValue}
|
|
||||||
onChange={this.handleSearchInputChange}
|
|
||||||
onKeyDown={this.handleTextKeyDown}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
) : (
|
||||||
variant={ButtonVariant.control}
|
<NoOptionDropdown>{searchColumnName}</NoOptionDropdown>
|
||||||
aria-label={i18n._(t`Search submit button`)}
|
)}
|
||||||
onClick={this.handleSearch}
|
</DataToolbarItem>
|
||||||
>
|
{columns.map(({ key, name, options, isBoolean }) => (
|
||||||
<SearchIcon />
|
<DataToolbarFilter
|
||||||
</Button>
|
chips={chipsByKey[key] ? chipsByKey[key].chips : []}
|
||||||
</InputGroup>)}
|
deleteChip={(unusedKey, val) => {
|
||||||
</DataToolbarFilter>))}
|
onRemove(chipsByKey[key].key, val);
|
||||||
|
}}
|
||||||
|
categoryName={chipsByKey[key] ? chipsByKey[key].label : key}
|
||||||
|
key={key}
|
||||||
|
showToolbarItem={searchKey === key}
|
||||||
|
>
|
||||||
|
{(options && (
|
||||||
|
<Select
|
||||||
|
variant={SelectVariant.checkbox}
|
||||||
|
aria-label={name}
|
||||||
|
onToggle={this.handleFilterDropdownToggle}
|
||||||
|
onSelect={(event, selection) =>
|
||||||
|
this.handleFilterDropdownSelect(key, event, selection)
|
||||||
|
}
|
||||||
|
selections={chipsByKey[key].chips}
|
||||||
|
isExpanded={isFilterDropdownOpen}
|
||||||
|
placeholderText={`Filter by ${name.toLowerCase()}`}
|
||||||
|
>
|
||||||
|
{options.map(([optionKey]) => (
|
||||||
|
<Fragment key={optionKey}>
|
||||||
|
{/* TODO: update value to being object
|
||||||
|
{ actualValue: optionKey, toString: () => label }
|
||||||
|
currently a pf bug that makes the checked logic
|
||||||
|
not work with object-based values */}
|
||||||
|
<SelectOption key={optionKey} value={optionKey} />
|
||||||
|
</Fragment>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)) ||
|
||||||
|
(isBoolean && (
|
||||||
|
<Select
|
||||||
|
aria-label={name}
|
||||||
|
onToggle={this.handleFilterDropdownToggle}
|
||||||
|
onSelect={(event, selection) =>
|
||||||
|
this.handleFilterBooleanSelect(key, selection)
|
||||||
|
}
|
||||||
|
selections={chipsByKey[key].chips[0]}
|
||||||
|
isExpanded={isFilterDropdownOpen}
|
||||||
|
placeholderText={`Filter by ${name.toLowerCase()}`}
|
||||||
|
>
|
||||||
|
{/* TODO: update value to being object
|
||||||
|
{ actualValue: optionKey, toString: () => label }
|
||||||
|
currently a pf bug that makes the checked logic
|
||||||
|
not work with object-based values */}
|
||||||
|
<SelectOption key="true" value="true" />
|
||||||
|
<SelectOption key="false" value="false" />
|
||||||
|
</Select>
|
||||||
|
)) || (
|
||||||
|
<InputGroup>
|
||||||
|
{/* TODO: add support for dates:
|
||||||
|
qsConfig.dateFields.filter(field => field === key).length && "date" */}
|
||||||
|
<TextInput
|
||||||
|
type={
|
||||||
|
(qsConfig.integerFields.find(
|
||||||
|
field => field === searchKey
|
||||||
|
) &&
|
||||||
|
'number') ||
|
||||||
|
'search'
|
||||||
|
}
|
||||||
|
aria-label={i18n._(t`Search text input`)}
|
||||||
|
value={searchValue}
|
||||||
|
onChange={this.handleSearchInputChange}
|
||||||
|
onKeyDown={this.handleTextKeyDown}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant={ButtonVariant.control}
|
||||||
|
aria-label={i18n._(t`Search submit button`)}
|
||||||
|
onClick={this.handleSearch}
|
||||||
|
>
|
||||||
|
<SearchIcon />
|
||||||
|
</Button>
|
||||||
|
</InputGroup>
|
||||||
|
)}
|
||||||
|
</DataToolbarFilter>
|
||||||
|
))}
|
||||||
</DataToolbarGroup>
|
</DataToolbarGroup>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -266,12 +298,12 @@ Search.propTypes = {
|
|||||||
qsConfig: QSConfig.isRequired,
|
qsConfig: QSConfig.isRequired,
|
||||||
columns: SearchColumns.isRequired,
|
columns: SearchColumns.isRequired,
|
||||||
onSearch: PropTypes.func,
|
onSearch: PropTypes.func,
|
||||||
onRemove: PropTypes.func
|
onRemove: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
Search.defaultProps = {
|
Search.defaultProps = {
|
||||||
onSearch: null,
|
onSearch: null,
|
||||||
onRemove: null
|
onRemove: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withI18n()(withRouter(Search));
|
export default withI18n()(withRouter(Search));
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DataToolbar, DataToolbarContent } from '@patternfly/react-core/dist/umd/experimental';
|
import {
|
||||||
|
DataToolbar,
|
||||||
|
DataToolbarContent,
|
||||||
|
} from '@patternfly/react-core/dist/umd/experimental';
|
||||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||||
import Search from './Search';
|
import Search from './Search';
|
||||||
|
|
||||||
@@ -20,9 +23,7 @@ describe('<Search />', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('it triggers the expected callbacks', () => {
|
test('it triggers the expected callbacks', () => {
|
||||||
const columns = [
|
const columns = [{ name: 'Name', key: 'name', isDefault: true }];
|
||||||
{ name: 'Name', key: 'name', isDefault: true }
|
|
||||||
];
|
|
||||||
|
|
||||||
const searchBtn = 'button[aria-label="Search submit button"]';
|
const searchBtn = 'button[aria-label="Search submit button"]';
|
||||||
const searchTextInput = 'input[aria-label="Search text input"]';
|
const searchTextInput = 'input[aria-label="Search text input"]';
|
||||||
@@ -30,16 +31,13 @@ describe('<Search />', () => {
|
|||||||
const onSearch = jest.fn();
|
const onSearch = jest.fn();
|
||||||
|
|
||||||
search = mountWithContexts(
|
search = mountWithContexts(
|
||||||
<DataToolbar id={`${QS_CONFIG.namespace}-list-toolbar`}
|
<DataToolbar
|
||||||
|
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||||
clearAllFilters={() => {}}
|
clearAllFilters={() => {}}
|
||||||
collapseListedFiltersBreakpoint="md"
|
collapseListedFiltersBreakpoint="md"
|
||||||
>
|
>
|
||||||
<DataToolbarContent>
|
<DataToolbarContent>
|
||||||
<Search
|
<Search qsConfig={QS_CONFIG} columns={columns} onSearch={onSearch} />
|
||||||
qsConfig={QS_CONFIG}
|
|
||||||
columns={columns}
|
|
||||||
onSearch={onSearch}
|
|
||||||
/>
|
|
||||||
</DataToolbarContent>
|
</DataToolbarContent>
|
||||||
</DataToolbar>
|
</DataToolbar>
|
||||||
);
|
);
|
||||||
@@ -53,21 +51,16 @@ describe('<Search />', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('handleDropdownToggle properly updates state', async () => {
|
test('handleDropdownToggle properly updates state', async () => {
|
||||||
const columns = [
|
const columns = [{ name: 'Name', key: 'name', isDefault: true }];
|
||||||
{ name: 'Name', key: 'name', isDefault: true }
|
|
||||||
];
|
|
||||||
const onSearch = jest.fn();
|
const onSearch = jest.fn();
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<DataToolbar id={`${QS_CONFIG.namespace}-list-toolbar`}
|
<DataToolbar
|
||||||
|
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||||
clearAllFilters={() => {}}
|
clearAllFilters={() => {}}
|
||||||
collapseListedFiltersBreakpoint="md"
|
collapseListedFiltersBreakpoint="md"
|
||||||
>
|
>
|
||||||
<DataToolbarContent>
|
<DataToolbarContent>
|
||||||
<Search
|
<Search qsConfig={QS_CONFIG} columns={columns} onSearch={onSearch} />
|
||||||
qsConfig={QS_CONFIG}
|
|
||||||
columns={columns}
|
|
||||||
onSearch={onSearch}
|
|
||||||
/>
|
|
||||||
</DataToolbarContent>
|
</DataToolbarContent>
|
||||||
</DataToolbar>
|
</DataToolbar>
|
||||||
).find('Search');
|
).find('Search');
|
||||||
@@ -83,16 +76,13 @@ describe('<Search />', () => {
|
|||||||
];
|
];
|
||||||
const onSearch = jest.fn();
|
const onSearch = jest.fn();
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<DataToolbar id={`${QS_CONFIG.namespace}-list-toolbar`}
|
<DataToolbar
|
||||||
|
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||||
clearAllFilters={() => {}}
|
clearAllFilters={() => {}}
|
||||||
collapseListedFiltersBreakpoint="md"
|
collapseListedFiltersBreakpoint="md"
|
||||||
>
|
>
|
||||||
<DataToolbarContent>
|
<DataToolbarContent>
|
||||||
<Search
|
<Search qsConfig={QS_CONFIG} columns={columns} onSearch={onSearch} />
|
||||||
qsConfig={QS_CONFIG}
|
|
||||||
columns={columns}
|
|
||||||
onSearch={onSearch}
|
|
||||||
/>
|
|
||||||
</DataToolbarContent>
|
</DataToolbarContent>
|
||||||
</DataToolbar>
|
</DataToolbar>
|
||||||
).find('Search');
|
).find('Search');
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ import {
|
|||||||
SortNumericUpIcon,
|
SortNumericUpIcon,
|
||||||
} from '@patternfly/react-icons';
|
} from '@patternfly/react-icons';
|
||||||
|
|
||||||
import {
|
import { parseQueryString } from '@util/qs';
|
||||||
parseQueryString
|
|
||||||
} from '@util/qs';
|
|
||||||
import { SortColumns, QSConfig } from '@types';
|
import { SortColumns, QSConfig } from '@types';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
@@ -51,7 +49,7 @@ class Sort extends React.Component {
|
|||||||
sortOrder = 'ascending';
|
sortOrder = 'ascending';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qsConfig.integerFields.filter(field => field === sortKey).length) {
|
if (qsConfig.integerFields.find(field => field === sortKey)) {
|
||||||
isNumeric = true;
|
isNumeric = true;
|
||||||
} else {
|
} else {
|
||||||
isNumeric = false;
|
isNumeric = false;
|
||||||
@@ -61,7 +59,7 @@ class Sort extends React.Component {
|
|||||||
isSortDropdownOpen: false,
|
isSortDropdownOpen: false,
|
||||||
sortKey,
|
sortKey,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
isNumeric
|
isNumeric,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleDropdownToggle = this.handleDropdownToggle.bind(this);
|
this.handleDropdownToggle = this.handleDropdownToggle.bind(this);
|
||||||
@@ -78,13 +76,11 @@ class Sort extends React.Component {
|
|||||||
const { sortOrder } = this.state;
|
const { sortOrder } = this.state;
|
||||||
const { innerText } = target;
|
const { innerText } = target;
|
||||||
|
|
||||||
const [{ key: sortKey }] = columns.filter(
|
const [{ key: sortKey }] = columns.filter(({ name }) => name === innerText);
|
||||||
({ name }) => name === innerText
|
|
||||||
);
|
|
||||||
|
|
||||||
let isNumeric;
|
let isNumeric;
|
||||||
|
|
||||||
if (qsConfig.integerFields.filter(field => field === sortKey).length) {
|
if (qsConfig.integerFields.find(field => field === sortKey)) {
|
||||||
isNumeric = true;
|
isNumeric = true;
|
||||||
} else {
|
} else {
|
||||||
isNumeric = false;
|
isNumeric = false;
|
||||||
@@ -131,23 +127,23 @@ class Sort extends React.Component {
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
{sortedColumnName && (
|
{sortedColumnName && (
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
{sortDropdownItems.length > 0 && (<Dropdown
|
{(sortDropdownItems.length > 0 && (
|
||||||
onToggle={this.handleDropdownToggle}
|
<Dropdown
|
||||||
onSelect={this.handleDropdownSelect}
|
onToggle={this.handleDropdownToggle}
|
||||||
direction={up}
|
onSelect={this.handleDropdownSelect}
|
||||||
isOpen={isSortDropdownOpen}
|
direction={up}
|
||||||
toggle={
|
isOpen={isSortDropdownOpen}
|
||||||
<DropdownToggle
|
toggle={
|
||||||
id="awx-sort"
|
<DropdownToggle
|
||||||
onToggle={this.handleDropdownToggle}
|
id="awx-sort"
|
||||||
>
|
onToggle={this.handleDropdownToggle}
|
||||||
{sortedColumnName}
|
>
|
||||||
</DropdownToggle>
|
{sortedColumnName}
|
||||||
}
|
</DropdownToggle>
|
||||||
dropdownItems={sortDropdownItems}
|
}
|
||||||
/>) || (
|
dropdownItems={sortDropdownItems}
|
||||||
<NoOptionDropdown>{sortedColumnName}</NoOptionDropdown>
|
/>
|
||||||
)}
|
)) || <NoOptionDropdown>{sortedColumnName}</NoOptionDropdown>}
|
||||||
<Button
|
<Button
|
||||||
variant={ButtonVariant.control}
|
variant={ButtonVariant.control}
|
||||||
aria-label={i18n._(t`Sort`)}
|
aria-label={i18n._(t`Sort`)}
|
||||||
@@ -165,11 +161,11 @@ class Sort extends React.Component {
|
|||||||
Sort.propTypes = {
|
Sort.propTypes = {
|
||||||
qsConfig: QSConfig.isRequired,
|
qsConfig: QSConfig.isRequired,
|
||||||
columns: SortColumns.isRequired,
|
columns: SortColumns.isRequired,
|
||||||
onSort: PropTypes.func
|
onSort: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
Sort.defaultProps = {
|
Sort.defaultProps = {
|
||||||
onSort: null
|
onSort: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withI18n()(withRouter(Sort));
|
export default withI18n()(withRouter(Sort));
|
||||||
|
|||||||
@@ -30,11 +30,7 @@ describe('<Sort />', () => {
|
|||||||
const onSort = jest.fn();
|
const onSort = jest.fn();
|
||||||
|
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<Sort
|
<Sort qsConfig={qsConfig} columns={columns} onSort={onSort} />
|
||||||
qsConfig={qsConfig}
|
|
||||||
columns={columns}
|
|
||||||
onSort={onSort}
|
|
||||||
/>
|
|
||||||
).find('Sort');
|
).find('Sort');
|
||||||
|
|
||||||
wrapper.find(sortBtn).simulate('click');
|
wrapper.find(sortBtn).simulate('click');
|
||||||
@@ -62,17 +58,13 @@ describe('<Sort />', () => {
|
|||||||
{
|
{
|
||||||
name: 'Bakery',
|
name: 'Bakery',
|
||||||
key: 'bakery',
|
key: 'bakery',
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const onSort = jest.fn();
|
const onSort = jest.fn();
|
||||||
|
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<Sort
|
<Sort qsConfig={qsConfig} columns={columns} onSort={onSort} />
|
||||||
qsConfig={qsConfig}
|
|
||||||
columns={columns}
|
|
||||||
onSort={onSort}
|
|
||||||
/>
|
|
||||||
).find('Sort');
|
).find('Sort');
|
||||||
const sortDropdownToggle = wrapper.find('Button');
|
const sortDropdownToggle = wrapper.find('Button');
|
||||||
expect(sortDropdownToggle.length).toBe(1);
|
expect(sortDropdownToggle.length).toBe(1);
|
||||||
@@ -99,17 +91,13 @@ describe('<Sort />', () => {
|
|||||||
{
|
{
|
||||||
name: 'Bakery',
|
name: 'Bakery',
|
||||||
key: 'bakery',
|
key: 'bakery',
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const onSort = jest.fn();
|
const onSort = jest.fn();
|
||||||
|
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<Sort
|
<Sort qsConfig={qsConfig} columns={columns} onSort={onSort} />
|
||||||
qsConfig={qsConfig}
|
|
||||||
columns={columns}
|
|
||||||
onSort={onSort}
|
|
||||||
/>
|
|
||||||
).find('Sort');
|
).find('Sort');
|
||||||
const sortDropdownToggle = wrapper.find('Button');
|
const sortDropdownToggle = wrapper.find('Button');
|
||||||
expect(sortDropdownToggle.length).toBe(1);
|
expect(sortDropdownToggle.length).toBe(1);
|
||||||
@@ -136,17 +124,13 @@ describe('<Sort />', () => {
|
|||||||
{
|
{
|
||||||
name: 'Bakery',
|
name: 'Bakery',
|
||||||
key: 'bakery',
|
key: 'bakery',
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const onSort = jest.fn();
|
const onSort = jest.fn();
|
||||||
|
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<Sort
|
<Sort qsConfig={qsConfig} columns={columns} onSort={onSort} />
|
||||||
qsConfig={qsConfig}
|
|
||||||
columns={columns}
|
|
||||||
onSort={onSort}
|
|
||||||
/>
|
|
||||||
).find('Sort');
|
).find('Sort');
|
||||||
|
|
||||||
wrapper.instance().handleDropdownSelect({ target: { innerText: 'Bar' } });
|
wrapper.instance().handleDropdownSelect({ target: { innerText: 'Bar' } });
|
||||||
@@ -172,17 +156,13 @@ describe('<Sort />', () => {
|
|||||||
{
|
{
|
||||||
name: 'Bakery',
|
name: 'Bakery',
|
||||||
key: 'bakery',
|
key: 'bakery',
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const onSort = jest.fn();
|
const onSort = jest.fn();
|
||||||
|
|
||||||
const wrapper = mountWithContexts(
|
const wrapper = mountWithContexts(
|
||||||
<Sort
|
<Sort qsConfig={qsConfig} columns={columns} onSort={onSort} />
|
||||||
qsConfig={qsConfig}
|
|
||||||
columns={columns}
|
|
||||||
onSort={onSort}
|
|
||||||
/>
|
|
||||||
).find('Sort');
|
).find('Sort');
|
||||||
expect(wrapper.state('isSortDropdownOpen')).toEqual(false);
|
expect(wrapper.state('isSortDropdownOpen')).toEqual(false);
|
||||||
wrapper.instance().handleDropdownToggle(true);
|
wrapper.instance().handleDropdownToggle(true);
|
||||||
@@ -216,12 +196,8 @@ describe('<Sort />', () => {
|
|||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const numericColumns = [
|
const numericColumns = [{ name: 'ID', key: 'id' }];
|
||||||
{ name: 'ID', key: 'id' },
|
const alphaColumns = [{ name: 'Name', key: 'name' }];
|
||||||
];
|
|
||||||
const alphaColumns = [
|
|
||||||
{ name: 'Name', key: 'name' },
|
|
||||||
];
|
|
||||||
const onSort = jest.fn();
|
const onSort = jest.fn();
|
||||||
|
|
||||||
sort = mountWithContexts(
|
sort = mountWithContexts(
|
||||||
@@ -236,11 +212,7 @@ describe('<Sort />', () => {
|
|||||||
expect(downNumericIcon.length).toBe(1);
|
expect(downNumericIcon.length).toBe(1);
|
||||||
|
|
||||||
sort = mountWithContexts(
|
sort = mountWithContexts(
|
||||||
<Sort
|
<Sort qsConfig={qsConfigNumUp} columns={numericColumns} onSort={onSort} />
|
||||||
qsConfig={qsConfigNumUp}
|
|
||||||
columns={numericColumns}
|
|
||||||
onSort={onSort}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const upNumericIcon = sort.find(upNumericIconSelector);
|
const upNumericIcon = sort.find(upNumericIconSelector);
|
||||||
@@ -258,11 +230,7 @@ describe('<Sort />', () => {
|
|||||||
expect(downAlphaIcon.length).toBe(1);
|
expect(downAlphaIcon.length).toBe(1);
|
||||||
|
|
||||||
sort = mountWithContexts(
|
sort = mountWithContexts(
|
||||||
<Sort
|
<Sort qsConfig={qsConfigAlphaUp} columns={alphaColumns} onSort={onSort} />
|
||||||
qsConfig={qsConfigAlphaUp}
|
|
||||||
columns={alphaColumns}
|
|
||||||
onSort={onSort}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const upAlphaIcon = sort.find(upAlphaIconSelector);
|
const upAlphaIcon = sort.find(upAlphaIconSelector);
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class HostsList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
|
|||||||
@@ -181,12 +181,12 @@ function InventoryGroupsList({ i18n, location, match }) {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Is Root Group`),
|
name: i18n._(t`Is Root Group`),
|
||||||
key: 'parents__isnull',
|
key: 'parents__isnull',
|
||||||
isBoolean: true
|
isBoolean: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
@@ -200,8 +200,8 @@ function InventoryGroupsList({ i18n, location, match }) {
|
|||||||
toolbarSortColumns={[
|
toolbarSortColumns={[
|
||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name'
|
key: 'name',
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
renderItem={item => (
|
renderItem={item => (
|
||||||
<InventoryGroupItem
|
<InventoryGroupItem
|
||||||
|
|||||||
@@ -161,7 +161,9 @@ describe('<InventoryGroupsList />', () => {
|
|||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('DataToolbar Button[aria-label="Delete"]').invoke('onClick')();
|
wrapper
|
||||||
|
.find('DataToolbar Button[aria-label="Delete"]')
|
||||||
|
.invoke('onClick')();
|
||||||
});
|
});
|
||||||
await waitForElement(
|
await waitForElement(
|
||||||
wrapper,
|
wrapper,
|
||||||
@@ -193,7 +195,9 @@ describe('<InventoryGroupsList />', () => {
|
|||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('DataToolbar Button[aria-label="Delete"]').invoke('onClick')();
|
wrapper
|
||||||
|
.find('DataToolbar Button[aria-label="Delete"]')
|
||||||
|
.invoke('onClick')();
|
||||||
});
|
});
|
||||||
await waitForElement(
|
await waitForElement(
|
||||||
wrapper,
|
wrapper,
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ function InventoryHosts({ i18n, location, match }) {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
@@ -150,8 +150,8 @@ function InventoryHosts({ i18n, location, match }) {
|
|||||||
toolbarSortColumns={[
|
toolbarSortColumns={[
|
||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name'
|
key: 'name',
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
renderToolbar={props => (
|
renderToolbar={props => (
|
||||||
<DataListToolbar
|
<DataListToolbar
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ class InventoriesList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
|
|||||||
@@ -23,12 +23,16 @@ import { getQSConfig, parseQueryString } from '@util/qs';
|
|||||||
|
|
||||||
import JobListItem from './JobListItem';
|
import JobListItem from './JobListItem';
|
||||||
|
|
||||||
const QS_CONFIG = getQSConfig('job', {
|
const QS_CONFIG = getQSConfig(
|
||||||
page: 1,
|
'job',
|
||||||
page_size: 20,
|
{
|
||||||
order_by: '-finished',
|
page: 1,
|
||||||
not__launch_type: 'sync',
|
page_size: 20,
|
||||||
}, ['page', 'page_size', 'id']);
|
order_by: '-finished',
|
||||||
|
not__launch_type: 'sync',
|
||||||
|
},
|
||||||
|
['page', 'page_size', 'id']
|
||||||
|
);
|
||||||
|
|
||||||
class JobList extends Component {
|
class JobList extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -167,88 +171,46 @@ class JobList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`ID`),
|
name: i18n._(t`ID`),
|
||||||
key: 'id'
|
key: 'id',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Label Name`),
|
name: i18n._(t`Label Name`),
|
||||||
key: 'labels__name'
|
key: 'labels__name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Job Type`),
|
name: i18n._(t`Job Type`),
|
||||||
key: `type`,
|
key: `type`,
|
||||||
options: [
|
options: [
|
||||||
[
|
[`project_update`, i18n._(t`SCM Update`)],
|
||||||
`project_update`,
|
[`inventory_update`, i18n._(t`Inventory Sync`)],
|
||||||
i18n._(t`SCM Update`)
|
[`job`, i18n._(t`Playbook Run`)],
|
||||||
],
|
[`ad_hoc_command`, i18n._(t`Command`)],
|
||||||
[
|
[`system_job`, i18n._(t`Management Job`)],
|
||||||
`inventory_update`,
|
[`workflow_job`, i18n._(t`Workflow Job`)],
|
||||||
i18n._(t`Inventory Sync`)
|
],
|
||||||
],
|
|
||||||
[
|
|
||||||
`job`,
|
|
||||||
i18n._(t`Playbook Run`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`ad_hoc_command`,
|
|
||||||
i18n._(t`Command`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`system_job`,
|
|
||||||
i18n._(t`Management Job`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`workflow_job`,
|
|
||||||
i18n._(t`Workflow Job`)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
key: 'created_by__username'
|
key: 'created_by__username',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Status`),
|
name: i18n._(t`Status`),
|
||||||
key: 'status',
|
key: 'status',
|
||||||
options: [
|
options: [
|
||||||
[
|
[`new`, i18n._(t`New`)],
|
||||||
`new`,
|
[`pending`, i18n._(t`Pending`)],
|
||||||
i18n._(t`New`)
|
[`waiting`, i18n._(t`Waiting`)],
|
||||||
],
|
[`running`, i18n._(t`Running`)],
|
||||||
[
|
[`successful`, i18n._(t`Successful`)],
|
||||||
`pending`,
|
[`failed`, i18n._(t`Failed`)],
|
||||||
i18n._(t`Pending`)
|
[`error`, i18n._(t`Error`)],
|
||||||
],
|
[`canceled`, i18n._(t`Canceled`)],
|
||||||
[
|
],
|
||||||
`waiting`,
|
},
|
||||||
i18n._(t`Waiting`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`running`,
|
|
||||||
i18n._(t`Running`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`successful`,
|
|
||||||
i18n._(t`Successful`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`failed`,
|
|
||||||
i18n._(t`Failed`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`error`,
|
|
||||||
i18n._(t`Error`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`canceled`,
|
|
||||||
i18n._(t`Canceled`)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]}
|
]}
|
||||||
toolbarSortColumns={[
|
toolbarSortColumns={[
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ function OrganizationsList({ i18n }) {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created By (Username)`),
|
name: i18n._(t`Created By (Username)`),
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ function OrganizationTeams({ id, i18n }) {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Created by (username)`),
|
name: i18n._(t`Created by (username)`),
|
||||||
|
|||||||
@@ -160,32 +160,18 @@ class ProjectsList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Type`),
|
name: i18n._(t`Type`),
|
||||||
|
key: 'type',
|
||||||
options: [
|
options: [
|
||||||
[
|
[``, i18n._(t`Manual`)],
|
||||||
``,
|
[`git`, i18n._(t`Git`)],
|
||||||
i18n._(t`Manual`)
|
[`hg`, i18n._(t`Mercurial`)],
|
||||||
],
|
[`svn`, i18n._(t`Subversion`)],
|
||||||
[
|
[`insights`, i18n._(t`Red Hat Insights`)],
|
||||||
`git`,
|
],
|
||||||
i18n._(t`Git`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`hg`,
|
|
||||||
i18n._(t`Mercurial`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`svn`,
|
|
||||||
i18n._(t`Subversion`)
|
|
||||||
],
|
|
||||||
[
|
|
||||||
`insights`,
|
|
||||||
i18n._(t`Red Hat Insights`)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`SCM URL`),
|
name: i18n._(t`SCM URL`),
|
||||||
@@ -204,7 +190,7 @@ class ProjectsList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
renderToolbar={props => (
|
renderToolbar={props => (
|
||||||
<DataListToolbar
|
<DataListToolbar
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ class TeamsList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Organization Name`),
|
name: i18n._(t`Organization Name`),
|
||||||
|
|||||||
@@ -218,21 +218,15 @@ class TemplatesList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Name`),
|
name: i18n._(t`Name`),
|
||||||
key: 'name',
|
key: 'name',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Type`),
|
name: i18n._(t`Type`),
|
||||||
key: 'type',
|
key: 'type',
|
||||||
options: [
|
options: [
|
||||||
[
|
[`job_template`, i18n._(t`Job Template`)],
|
||||||
`job_template`,
|
[`workflow_job_template`, i18n._(t`Workflow Template`)],
|
||||||
i18n._(t`Job Template`)
|
],
|
||||||
],
|
|
||||||
[
|
|
||||||
`workflow_job_template`,
|
|
||||||
i18n._(t`Workflow Template`)
|
|
||||||
],
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`Playbook name`),
|
name: i18n._(t`Playbook name`),
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ class UsersList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Username`),
|
name: i18n._(t`Username`),
|
||||||
key: 'username',
|
key: 'username',
|
||||||
isDefault: true
|
isDefault: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n._(t`First Name`),
|
name: i18n._(t`First Name`),
|
||||||
@@ -167,7 +167,7 @@ class UsersList extends Component {
|
|||||||
{
|
{
|
||||||
name: i18n._(t`Last Name`),
|
name: i18n._(t`Last Name`),
|
||||||
key: 'last_name',
|
key: 'last_name',
|
||||||
}
|
},
|
||||||
]}
|
]}
|
||||||
toolbarSortColumns={[
|
toolbarSortColumns={[
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ export const SearchColumns = arrayOf(
|
|||||||
key: string.isRequired,
|
key: string.isRequired,
|
||||||
isDefault: bool,
|
isDefault: bool,
|
||||||
isBoolean: bool,
|
isBoolean: bool,
|
||||||
options: arrayOf(arrayOf(string, string))
|
options: arrayOf(arrayOf(string, string)),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export function getQSConfig(
|
|||||||
throw new Error('a QS namespace is required');
|
throw new Error('a QS namespace is required');
|
||||||
}
|
}
|
||||||
// if order_by isn't passed, default to name
|
// if order_by isn't passed, default to name
|
||||||
if (!Object.keys(defaultParams).filter(key => key === 'order_by').length) {
|
if (!defaultParams.order_by) {
|
||||||
defaultParams.order_by = 'name';
|
defaultParams.order_by = 'name';
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -193,7 +193,6 @@ function removeParam(oldVal, deleteVal) {
|
|||||||
* @return {object} merged namespaced params object
|
* @return {object} merged namespaced params object
|
||||||
*/
|
*/
|
||||||
export function mergeParams(oldParams, newParams) {
|
export function mergeParams(oldParams, newParams) {
|
||||||
debugger;
|
|
||||||
const merged = {};
|
const merged = {};
|
||||||
Object.keys(oldParams).forEach(key => {
|
Object.keys(oldParams).forEach(key => {
|
||||||
merged[key] = mergeParam(oldParams[key], newParams[key]);
|
merged[key] = mergeParam(oldParams[key], newParams[key]);
|
||||||
|
|||||||
@@ -122,10 +122,12 @@ describe('qs (qs.js)', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should set order_by in defaultParams if it is not passed', () => {
|
test('should set order_by in defaultParams if it is not passed', () => {
|
||||||
expect(getQSConfig('organization', {
|
expect(
|
||||||
page: 1,
|
getQSConfig('organization', {
|
||||||
page_size: 5,
|
page: 1,
|
||||||
})).toEqual({
|
page_size: 5,
|
||||||
|
})
|
||||||
|
).toEqual({
|
||||||
namespace: 'organization',
|
namespace: 'organization',
|
||||||
defaultParams: { page: 1, page_size: 5, order_by: 'name' },
|
defaultParams: { page: 1, page_size: 5, order_by: 'name' },
|
||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
|
|||||||
Reference in New Issue
Block a user