-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ui): Add label filter to workflow list page. Fixes #802 #2196
Conversation
error?: Error; | ||
} | ||
|
||
export class InputFilter extends React.Component<InputProps, InputState> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is abstracted from original NamespaceFilter
to make it a generic input box with local cache.
<i className='fa fa-times-circle' /> | ||
</a> | ||
</> | ||
<InputFilter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reference to abstracted InputFilter
</> | ||
<InputFilter | ||
value={this.namespace} | ||
placeholder='Namespace' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use placeholder
to replace Namespace
text.
@@ -0,0 +1,16 @@ | |||
import * as React from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tags-input
is introduced from argo-cd
.
@@ -0,0 +1,53 @@ | |||
import * as React from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
checkbox-filter
introduces a list of checkboxes with counts displayed for for each item.
return ( | ||
<Consumer> | ||
{ctx => ( | ||
<Page | ||
title='Workflows' | ||
toolbar={{ | ||
filter, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Phase filter is now part of workflow-filters
.
@@ -104,9 +96,20 @@ export class WorkflowsList extends BasePage<RouteComponentProps<any>, State> { | |||
} | |||
] | |||
}, | |||
tools: [<NamespaceFilter key='namespace-filter' value={this.namespace} onChange={namespace => (this.namespace = namespace)} />] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Namespace filter is now also part of workflow-filters
Codecov Report
@@ Coverage Diff @@
## master #2196 +/- ##
======================================
Coverage 11.7% 11.7%
======================================
Files 52 52
Lines 26313 26313
======================================
Hits 3081 3081
Misses 22837 22837
Partials 395 395 Continue to review full report at Codecov.
|
ui/src/app/shared/components/checkbox-filter/checkbox-filter.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks pretty good so for - some minor comments - it might be good to do a side-by-side review on Monday - maybe include @simster7 ?
@@ -30,17 +28,7 @@ export class NamespaceFilter extends React.Component<Props, State> { | |||
} | |||
|
|||
private set namespace(namespace: string) { | |||
this.setState(state => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with this code removed - how do entries get saved into local storage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's moved to generic component input-filter
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If all these getters and setters do is modify and read from state I would recommend not using them and simply modifying and reading state directly. Way more explicit and React-y
|
||
interface InputState { | ||
input: string; | ||
localInputs: string[]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this name - would something like previousValue
be good?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to localCache
interface InputProps { | ||
value: string; | ||
placeholder: string; | ||
type: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is "type"? is in select
or checkbox
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used to generate the local storage key. I renamed it to name
.
|
||
require('./tags-input.scss'); | ||
|
||
export class TagsInput extends React.Component<TagsInputProps, {tags: string[]; input: string; focused: boolean}> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alexmt should we be pushing this into the shared Argo UI code? does that still exist?
error?: Error; | ||
} | ||
|
||
export class WorkflowFilters extends React.Component<WorkflowFilterProps, WorkflowFilterState> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like how we have one big component that comprises of smaller ones
ui/src/app/shared/components/checkbox-filter/checkbox-filter.scss
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work for your first React PR! Jotted down some initial comments, but this should have a more in-depth review soon. A couple of things:
- The design is not responsive:
-
It might be just my build, but it seems like this is very broken and slow. See: https://cl.ly/4d454b27345a. This will need some reworking and actual testing before it's ready.
-
This needs a
make lint
ui/src/app/workflows/components/workflows-list/workflows-list.tsx
Outdated
Show resolved
Hide resolved
ui/src/app/workflows/components/workflows-list/workflows-list.tsx
Outdated
Show resolved
Hide resolved
namespace={this.namespace} | ||
phases={this.phases} | ||
labels={this.labels} | ||
onChange={(namespace, phases, labels) => this.handleChanges(namespace, phases, labels)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could simply pass in the function here
onChange={(namespace, phases, labels) => this.handleChanges(namespace, phases, labels)} | |
onChange={this.handleChanges} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Somehow it doesn't work.....
ui/src/app/workflows/components/workflow-filters/workflow-filters.tsx
Outdated
Show resolved
Hide resolved
namespace: props.namespace, | ||
phases: props.phases, | ||
labels: props.labels |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not too sure about this pattern... there should only be one source of truth about what the current namespace
, phases
, and labels
are. Right now we are storing it in three different places: the URL, state in workflows-list
, and this state. It should all be consolidated in one. Why store state here if you pass in an onChange
that changes the state of the parent component... forcing a re-render here anyway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Realized the same thing, removed the state and used the props.
} | ||
}} | ||
renderInput={props => ( | ||
<input |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole <input>
field doesn't seem like it is the correct way to do this. Can you check how we take input elsewhere in the codebase?
} | ||
if (filter.labels && filter.labels.length > 0) { | ||
if (labelSelector.length > 0) { | ||
labelSelector += ','; | ||
} | ||
labelSelector += filter.labels.join(','); | ||
} | ||
if (labelSelector.length > 0) { | ||
queryParams.push(`listOptions.labelSelector=${labelSelector}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The labelSelector
logic should be extracted as a utility function
ui/src/app/workflows/components/workflow-filters/workflow-filters.tsx
Outdated
Show resolved
Hide resolved
I noticed the slow responsive issue, it seems like the API call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent work! This is a great PR. Conditional approval: please fix the un-responsive design. I.e. the site doesn't resize well with different screen sizes. See: https://cl.ly/bd0c78ca10df
import {Autocomplete} from '../../../../node_modules/argo-ui'; | ||
|
||
interface InputProps { | ||
value: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pick: maybe call this initialValue
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
I feel like value
would be better, since it's still a <input type="text">
, using value
to be consistent with it.
}; | ||
} | ||
|
||
private set value(value: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setter should be converted to a function and renamed something like setValueAndCache
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
require('./tags-input.scss'); | ||
|
||
export class TagsInput extends React.Component<TagsInputProps, {tags: string[]; input: string; focused: boolean}> { | ||
private inputEl: HTMLInputElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit pick:
private inputEl: HTMLInputElement; | |
private inputElement: HTMLInputElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
<NamespaceFilter | ||
value={this.props.namespace} | ||
onChange={ns => { | ||
this.props.onChange(ns, this.props.selectedPhases, this.props.selectedLabels); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much better!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
const value = wf.metadata.labels[label]; | ||
const suggestedLabel = `${label}=${value}`; | ||
if (!suggestions.some(v => v === suggestedLabel)) { | ||
suggestions.push(`${label}=${value}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Fixed. |
Fixes: #802
Checklist:
"fix(controller): Updates such and such. Fixes #1234"
.