Skip to content

Commit

Permalink
Change search to handle multiple resources
Browse files Browse the repository at this point in the history
  • Loading branch information
zherman0 committed Jan 14, 2020
1 parent 54dd29d commit 248c032
Show file tree
Hide file tree
Showing 7 changed files with 461 additions and 167 deletions.
33 changes: 20 additions & 13 deletions frontend/packages/operator-lifecycle-manager/src/style.scss
@@ -1,13 +1,13 @@
// Bootstrap Core variables and mixins
@import "~bootstrap-sass/assets/stylesheets/bootstrap/variables";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/mixins";
@import '~bootstrap-sass/assets/stylesheets/bootstrap/variables';
@import '~bootstrap-sass/assets/stylesheets/bootstrap/mixins';

// Patternfly Core variables and mixins
@import "~patternfly/dist/sass/patternfly/variables";
@import "~patternfly/dist/sass/patternfly/bootstrap-mixin-overrides";
@import "~patternfly/dist/sass/patternfly/mixins";
@import '~patternfly/dist/sass/patternfly/variables';
@import '~patternfly/dist/sass/patternfly/bootstrap-mixin-overrides';
@import '~patternfly/dist/sass/patternfly/mixins';
@import '~patternfly/dist/sass/patternfly/icons';
@import "~patternfly-react/dist/sass/patternfly-react";
@import '~patternfly-react/dist/sass/patternfly-react';

$co-affinity-row-margin: 15px;

Expand All @@ -28,14 +28,16 @@ $co-affinity-row-margin: 15px;
.co-clusterserviceversion-link {
.co-clusterserviceversion-logo {
flex-direction: column;
@media (min-width: $screen-xs-min) and (max-width: $screen-xs-max),(min-width: $screen-md-min) {
@media (min-width: $screen-xs-min) and (max-width: $screen-xs-max),
(min-width: $screen-md-min) {
flex-direction: row;
}
}
}

.co-clusterserviceversion-link {
&:focus, &:hover {
&:focus,
&:hover {
text-decoration: none;

.co-clusterserviceversion-logo__name__clusterserviceversion {
Expand Down Expand Up @@ -71,8 +73,7 @@ $co-affinity-row-margin: 15px;
margin-bottom: 5px;
margin-top: 0;
}
.co-m-pane__heading--logo
.co-clusterserviceversion-logo__name__provider {
.co-m-pane__heading--logo .co-clusterserviceversion-logo__name__provider {
font-size: var(--pf-global--FontSize--sm);
}

Expand Down Expand Up @@ -155,7 +156,7 @@ $co-affinity-row-margin: 15px;
--pf-c-accordion__toggle-text--active--Color: var(--pf-global--Color--100) !important;
--pf-c-accordion__toggle-text--active--FontWeight: 600 !important;
--pf-c-accordion__toggle-text--expanded--Color: var(--pf-global--Color--100) !important;
--pf-c-accordion__toggle-text--expanded--FontWeight : 600 !important;
--pf-c-accordion__toggle-text--expanded--FontWeight: 600 !important;
--pf-c-accordion__toggle-text--focus--Color: var(--pf-global--Color--100) !important;
--pf-c-accordion__toggle-text--focus--FontWeight: 600 !important;
--pf-c-accordion__toggle-text--hover--Color: var(--pf-global--Color--100) !important;
Expand All @@ -181,7 +182,7 @@ $co-affinity-row-margin: 15px;
.co-create-operand__header {
border-bottom: 1px solid #ddd;
padding: 10px 15px;
@media(min-width: $screen-sm-min) {
@media (min-width: $screen-sm-min) {
padding: 0 30px 15px;
}
}
Expand Down Expand Up @@ -216,7 +217,6 @@ $co-affinity-row-margin: 15px;
margin-bottom: $co-affinity-row-margin;
}


.co-affinity-term__topology-input {
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -279,3 +279,10 @@ $co-affinity-row-margin: 15px;
.key-operator-value__row {
padding-bottom: 15px;
}

.span--icon__right-margin {
margin-right: 6px;
}
.resource-dropdown__right-margin {
margin-right: 12px;
}
62 changes: 52 additions & 10 deletions frontend/public/components/events.jsx
Expand Up @@ -136,31 +136,73 @@ export class EventsList extends React.Component {
super(props);
this.state = {
type: 'all',
kind: 'all',
textFilter: '',
selected: ['All'],
};
}

updateSelected = (event, selection) => {
const { selected } = this.state;
const updateItems = selected.includes(selection)
? selected.filter((keepItem) => keepItem !== selection)
: [...selected, selection];
this.setState({ selected: updateItems });
};

clearSelection = () => {
this.setState({ selected: [] });
};

getEvents = () => {
const { selected, type, textFilter } = this.state;
const events = [];
if (selected.includes('All') || selected.length <= 0) {
events.push(
<EventStream
{...this.props}
key={'all-resources-event'}
type={type}
kind={'all'}
mock={this.props.mock}
textFilter={textFilter}
/>,
);
} else {
selected.forEach((kind) => {
events.push(
<EventStream
{...this.props}
key={kind}
type={type}
kind={kind}
mock={this.props.mock}
textFilter={textFilter}
/>,
);
});
}
return events;
};

render() {
const { type, kind, textFilter } = this.state;
const { autoFocus = true, mock } = this.props;
const { type, selected } = this.state;
const { autoFocus = true } = this.props;

return (
<>
<div className="co-m-pane__filter-bar">
<div className="co-m-pane__filter-bar-group">
<ResourceListDropdown
className="btn-group"
onChange={(v) => this.setState({ kind: v })}
selected={kind}
showAll
title="All Resources"
onChange={this.updateSelected}
selected={selected}
showAll={true}
clearSelection={this.clearSelection}
/>
<Dropdown
className="btn-group"
items={eventTypes}
onChange={(v) => this.setState({ type: v })}
selectedKey={this.state.type}
selectedKey={type}
title="All Types"
/>
</div>
Expand All @@ -172,7 +214,7 @@ export class EventsList extends React.Component {
/>
</div>
</div>
<EventStream {...this.props} type={type} kind={kind} mock={mock} textFilter={textFilter} />
{this.getEvents()}
</>
);
}
Expand Down
29 changes: 18 additions & 11 deletions frontend/public/components/factory/list-page.jsx
Expand Up @@ -209,6 +209,7 @@ export const FireMan_ = connect(
filterLabel,
helpText,
resources,
showTextFilter = true,
textFilter,
badge,
title,
Expand Down Expand Up @@ -276,15 +277,17 @@ export const FireMan_ = connect(
</div>
)}
{createLink && <div className="co-m-pane__filter-bar-group">{createLink}</div>}
<div className="co-m-pane__filter-bar-group co-m-pane__filter-bar-group--filter">
<TextFilter
label={filterLabel}
onChange={(e) => this.applyFilter(textFilter, e.target.value)}
defaultValue={this.defaultValue}
tabIndex={1}
autoFocus={autoFocus}
/>
</div>
{showTextFilter && (
<div className="co-m-pane__filter-bar-group co-m-pane__filter-bar-group--filter">
<TextFilter
label={filterLabel}
onChange={(e) => this.applyFilter(textFilter, e.target.value)}
defaultValue={this.defaultValue}
tabIndex={1}
autoFocus={autoFocus}
/>
</div>
)}
</div>
<div className="co-m-pane__body">
{inject(this.props.children, {
Expand Down Expand Up @@ -334,7 +337,7 @@ FireMan_.propTypes = {
title: PropTypes.string,
};

/** @type {React.SFC<{ListComponent: React.ComponentType<any>, kind: string, helpText?: any, namespace?: string, filterLabel?: string, textFilter?: string, title?: string, showTitle?: boolean, rowFilters?: any[], selector?: any, fieldSelector?: string, canCreate?: boolean, createButtonText?: string, createProps?: any, mock?: boolean, badge?: React.ReactNode} >} */
/** @type {React.SFC<{ListComponent: React.ComponentType<any>, kind: string, helpText?: any, namespace?: string, filterLabel?: string, textFilter?: string, title?: string, showTextFilter?: boolean, showTitle?: boolean, rowFilters?: any[], selector?: any, fieldSelector?: string, canCreate?: boolean, createButtonText?: string, createProps?: any, mock?: boolean, badge?: React.ReactNode} >} */
export const ListPage = withFallback((props) => {
const {
autoFocus,
Expand All @@ -352,6 +355,7 @@ export const ListPage = withFallback((props) => {
name,
namespace,
selector,
showTextFilter = true,
showTitle = true,
skipAccessReview,
textFilter,
Expand Down Expand Up @@ -416,6 +420,7 @@ export const ListPage = withFallback((props) => {
resources={resources}
rowFilters={rowFilters}
selectorFilterLabel="Filter by selector (app=nginx) ..."
showTextFilter={showTextFilter}
showTitle={showTitle}
textFilter={textFilter}
title={title}
Expand All @@ -426,7 +431,7 @@ export const ListPage = withFallback((props) => {

ListPage.displayName = 'ListPage';

/** @type {React.SFC<{canCreate?: boolean, createButtonText?: string, createProps?: any, createAccessReview?: Object, flatten?: Function, title?: string, label?: string, showTitle?: boolean, helpText?: any, filterLabel?: string, textFilter?: string, rowFilters?: any[], resources: any[], ListComponent: React.ComponentType<any>, namespace?: string, customData?: any, badge?: React.ReactNode >} */
/** @type {React.SFC<{canCreate?: boolean, createButtonText?: string, createProps?: any, createAccessReview?: Object, flatten?: Function, title?: string, label?: string, showTextFilter?: boolean, showTitle?: boolean, helpText?: any, filterLabel?: string, textFilter?: string, rowFilters?: any[], resources: any[], ListComponent: React.ComponentType<any>, namespace?: string, customData?: any, badge?: React.ReactNode >} */
export const MultiListPage = (props) => {
const {
autoFocus,
Expand All @@ -442,6 +447,7 @@ export const MultiListPage = (props) => {
mock,
namespace,
rowFilters,
showTextFilter = true,
showTitle = true,
staticFilters,
textFilter,
Expand All @@ -468,6 +474,7 @@ export const MultiListPage = (props) => {
helpText={helpText}
resources={mock ? [] : resources}
selectorFilterLabel="Filter by selector (app=nginx) ..."
showTextFilter={showTextFilter}
textFilter={textFilter}
title={showTitle ? title : undefined}
badge={badge}
Expand Down
46 changes: 28 additions & 18 deletions frontend/public/components/resource-dropdown.tsx
@@ -1,7 +1,6 @@
import * as React from 'react';
import * as _ from 'lodash-es';
import { connect } from 'react-redux';
import * as PropTypes from 'prop-types';
import { Map as ImmutableMap, OrderedMap, Set as ImmutableSet } from 'immutable';
import * as classNames from 'classnames';
import * as fuzzy from 'fuzzysearch';
Expand All @@ -12,8 +11,8 @@ import {
K8sResourceKindReference,
referenceForModel,
apiVersionForReference,
kindForReference,
} from '../module/k8s';
import { Badge, Checkbox } from '@patternfly/react-core';

// Blacklist known duplicate resources.
const blacklistGroups = ImmutableSet([
Expand Down Expand Up @@ -43,9 +42,10 @@ const blacklistResources = ImmutableSet([
'extensions/v1beta1.ReplicationControllerDummy',
]);

const DropdownItem: React.SFC<DropdownItemProps> = ({ model, showGroup }) => (
const DropdownItem: React.SFC<DropdownItemProps> = ({ model, showGroup, checked }) => (
<>
<span className="co-resource-item">
<span className={'co-resource-item'}>
<Checkbox id={model.kind} isChecked={checked} />
<span className="co-resource-icon--fixed-width">
<ResourceIcon kind={referenceForModel(model)} />
</span>
Expand Down Expand Up @@ -99,17 +99,25 @@ const ResourceListDropdown_: React.SFC<ResourceListDropdownProps> = (props) => {
const kinds = resources.groupBy((m) => m.kind);
const isDup = (kind) => kinds.get(kind).size > 1;

const isDropdownSelected = (kind: string) => {
return _.includes(selected, kind);
};
// Create dropdown items for each resource.
const items = resources.map((model) => (
<DropdownItem key={referenceForModel(model)} model={model} showGroup={isDup(model.kind)} />
<DropdownItem
key={referenceForModel(model)}
model={model}
showGroup={isDup(model.kind)}
checked={isDropdownSelected(referenceForModel(model))}
/>
)) as OrderedMap<string, JSX.Element>;

// Add an "All" item to the top if `showAll`.
const allItems = (showAll
? OrderedMap({
all: (
<>
<span className="co-resource-item">
<Checkbox id="all-resources" isChecked={true} />
<span className="co-resource-icon--fixed-width">
<ResourceIcon kind="All" />
</span>
Expand All @@ -122,7 +130,6 @@ const ResourceListDropdown_: React.SFC<ResourceListDropdownProps> = (props) => {
: items
).toJS() as { [s: string]: JSX.Element };

const selectedKey = allItems[selected] ? selected : kindForReference(selected);
const autocompleteFilter = (text, item) => {
const { model } = item.props;
if (!model) {
Expand All @@ -132,16 +139,26 @@ const ResourceListDropdown_: React.SFC<ResourceListDropdownProps> = (props) => {
return fuzzy(_.toLower(text), _.toLower(model.kind));
};

const titleBadge = (): JSX.Element => {
let title: JSX.Element = null;
const count = selected.length;
title = (
<div key={'title-resource'}>
Resources <Badge isRead>{count}</Badge>
</div>
);
return title;
};

return (
<Dropdown
menuClassName="dropdown-menu--text-wrap"
className={classNames('co-type-selector', className)}
items={allItems}
title={allItems[selectedKey]}
title={titleBadge()}
onChange={onChange}
autocompleteFilter={autocompleteFilter}
autocompletePlaceholder="Select Resource"
selectedKey={selectedKey}
/>
);
};
Expand All @@ -155,17 +172,9 @@ export const ResourceListDropdown = connect(resourceListDropdownStateToProps)(
ResourceListDropdown_,
);

ResourceListDropdown.propTypes = {
onChange: PropTypes.func.isRequired,
selected: PropTypes.string,
showAll: PropTypes.bool,
className: PropTypes.string,
id: PropTypes.string,
};

export type ResourceListDropdownProps = {
// FIXME: `selected` should be GroupVersionKind
selected: K8sResourceKindReference;
selected: K8sResourceKindReference[];
onChange: Function;
allModels: ImmutableMap<K8sResourceKindReference, K8sKind>;
preferredVersions: { groupVersion: string; version: string }[];
Expand All @@ -177,4 +186,5 @@ export type ResourceListDropdownProps = {
type DropdownItemProps = {
model: K8sKind;
showGroup?: boolean;
checked?: boolean;
};

0 comments on commit 248c032

Please sign in to comment.