-
Notifications
You must be signed in to change notification settings - Fork 613
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
Add Status component to @console/shared #1697
Add Status component to @console/shared #1697
Conversation
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.
Overall I'm not sure of the purpose of these components.
I expect shared components to solve common use cases all console contributions have.
Please elaborate your description.
children: React.ReactNode; | ||
}; | ||
|
||
export const Status = ({ icon, children }: StatusProps) => ( |
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 React.FC<...>
to type components.
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.
When I use React.FC, current linting setup forces me to explicitly add type for props which introduces unnecessary duplication:
export const Status: React.FC<StatusProps> = ({ icon, children }: StatusProps) => (...
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.
That's not right. I am currently updating dev console in the monorepo and do not encounter this. Could you provide the error please and indicate what typescript version you are using (hopefully the one from the workspace).
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 the error I am getting: #1539 (review)
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.
IIUC this is addressed by #1721 (see ESLint update commit).
|
||
export const Status = ({ icon, children }: StatusProps) => ( | ||
<> | ||
{icon && <Icon type="pf" name={icon} className="kubevirt-status__icon" />} {children} |
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.
Should the space use {' '}
to ensure it is rendered? But then you need to do more logic to only include the space of the icon is rendered.
Not exactly sure if the purpose but is it supposed to allow any icon as status?
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.
Originally the space was not included and margin styling was used to ensure the space is present. I'd prefer using space as it adjusts to the font size. I'll fix this to include the space only when icon is present.
|
||
export const PopoverStatus = ({ icon, header, children }: PopoverStatusProps) => ( | ||
<Popover position="right" headerContent={header} bodyContent={children}> | ||
<span className="kubevirt-status__popover"> |
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.
We should not use non console classnames in shared components.
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.
Yep, I forgot to remove/change this.
<Popover position="right" headerContent={header} bodyContent={children}> | ||
<span className="kubevirt-status__popover"> | ||
<Status icon={icon}> | ||
<Button className="kubevirt-status__button" bsStyle="link"> |
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.
A button without any event handling?
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 Button is internally enhanced by Popover and acts as a toggle (https://patternfly-react.surge.sh/patternfly-4/components/popover/)
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.
oh pf... :/
It looks like it will add the event handlers to the span.
); | ||
|
||
type LinkStatusProps = StatusProps & { | ||
linkMessage?: 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.
Rename to linkTitle to be consistent with usage
describe('<Status />', () => { | ||
it('renders correctly', () => { | ||
const component = shallow(testStatus()); | ||
expect(component).toMatchSnapshot(); |
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 snapshot seems to have a lot of noise.
I also see little value in this test case.
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 think this relates to the common practice where each React component has (at least) a simple snapshot test to ensure the rendered markup doesn't change unexpectedly.
As for the messy snapshot file, there are things which don't make sense to serialize (like symbols), meaning we should update Jest & Enzyme & related dependency versions and ensure the generated snapshots are meaningful.
Console doesn't currently have any snapshot tests (git grep 'toMatchSnapshot'
returns nothing) so we should revisit the Enzyme (to-JSON) serializer stuff here. This also relates to #1648 which I'm revisiting at the moment.
@spadgett @vojtechszocs |
|
||
export const Status = ({ icon, children }: StatusProps) => ( | ||
<> | ||
{icon && <Icon type="pf" name={icon} className="kubevirt-status__icon" />} {children} |
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.
Is this suppose to be limited to certain "status" icons? or can they be anything?
PF4 icons don't work this way as they are component based.
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.
Icon
comes from patternfly-react
package which means PF3 (component showcase).
Supported type
includes pf
(PatternFly specific) and fa
(FontAwesome complementary). name
depends on type
.
In this case, since type
is hardcoded to pf
, name
could be checked against a list of available PF icon names, but I'm not sure if such list exists.
Good question. I see that My understanding is that |
|
||
import { Status, PopoverStatus } from '../status'; | ||
|
||
export default [ |
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.
@jtomasek If I understand correctly, this is the Cosmos fixture format, right?
@christianvogt This could be another use case for console-scripts
package - add Cosmos dependency & configuration and use it in packages that wish to leverage this tool.
/test e2e-aws-console-olm |
This seems like the wrong way to approach this. There are two parts here:
This looks like you copied status-icon.tsx and made some changes. The code will drift over time if we do this, and it might be hard to get rid of the old component. We're still trying to remove list.tsx as an example. I think (1) and (2) should be separate PRs, and we shouldn't introduce duplicate components. /hold |
What icons are you changing? It's hard to tell because you've copied the code to another file, so there's no diff :) We just recently updated all the icons for this design: https://openshift.github.io/openshift-origin-design/web-console/4.0-designs/status/status There were some specific reasons we chose the ones we did. |
I am not changing any icons, I just used PF4 component based counterparts. https://patternfly-react.surge.sh/patternfly-4/icons/Icons/ |
status?: string; | ||
}; | ||
|
||
export const GenericStatus: React.FC<{ status?: string }> = ({ status, children }) => { |
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 think GenericStatus
is a bad name.
React.FC<{ status?: string }>
should reference the prop type
<StatusIconAndText icon={icon} title={title} /> | ||
); | ||
|
||
export const SuccessStatus: React.FC<{ title: string }> = ({ title }) => ( |
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 a pre-defined type for the react props.
}; | ||
|
||
export const StatusIconAndText: React.FC<StatusProps> = ({ icon, title, spin }) => { | ||
if (!title) { |
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 there is an icon but no title, you don't want to show the icon?
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 don't think we want to show icon when there is no title. I am sticking with the original StatusIconAndText logic: https://github.com/openshift/console/blob/master/frontend/public/components/utils/status-icon.tsx#L72-L74
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.
ok
import { DASH } from '../../constants'; | ||
|
||
type StatusProps = { | ||
icon?: React.ReactElement; |
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.
Is the intention to only support patternfly react icons? Or any component? If it's only a patternfly react icon, we can change the prop types to accept color
and size
just like the pattern fly react icons, and instead of ReactElement
accept a component type. Then you can render it without the need to cloneElement
.
@spadgett (fyi @vojtechszocs) for shared components (and any new code in packages in general) do we want to adopt PascalCase component naming along with expecting a single default component export and multiple files, over single large file with multiple components? It's a fairly wide adopted convention and one that patternfly also follows. |
+1 |
Just It sounds like the technical approach here needs some tweaking, but UXD agrees that more flexibility around how Statuses can be labeled and interacted with (in both Tables and Resource Details pages) would be a great improvement. |
@@ -79,7 +80,7 @@ export const StatusDescriptor: React.SFC<DescriptorProps> = (props) => { | |||
</div> | |||
<dd className="olm-descriptor__value"> | |||
{descriptor.displayName === 'Status' ? | |||
(<StatusIconAndText status={value} iconName={value === 'Running' ? 'ok' : undefined} />) : | |||
({value === 'Running' ? <SuccessStatus status={value} /> : <Status status={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.
Just some thoughts.
I'd like to be able to use the same Status
component here instead. But we should then enumerate on a set of accepted status values in the prop types:
<Status status={value === 'Running' && 'Complete' || value} />
Alternatively, provide bool props (for the pre-defined finite set of concrete statuses) that take precedence over the status:
<Status status={value} success={value === 'Running'} />
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.
Just some thoughts.
I'd like to be able to use the same
Status
component here instead. But we should then enumerate on a set of accepted status values in the prop types:
<Status status={value === 'Running' && 'Complete' || value} />
I actually did this initially when I created this patch. But then I realised it is not possible as the status passed as prop is used as a title
for the StatusIconAndText so your example value === 'Running'
results in Icon + 'Complete'
instead of Icon + 'Running'
Alternatively, provide bool props (for the pre-defined finite set of concrete statuses) that take precedence over the status:
<Status status={value} success={value === 'Running'} />
I feel like expanding Status component to address this may be a bit overkill. What we need is to provide a way to define mapping of a certain (custom) status string to predefined status component (which ensures to render correct icon)
e.g.:
switch (status) {
case 'discovered':
return <SuccessStatus title={status} />;
case 'discovering':
return <ProgressStatus title={status} />;
case 'discovery error':
return <ErrorStatus title={status}>{errorMessage}</ErrorStatus>;
default:
return <Status status={status} /> // fall back to Status component for other states
}
This IMHO nicely says: "discovered
is a success
status"...
Comparing this to current solution which says: "Make 'Running' status act the same as 'Complete' status"
There is currently also one other way to define custom status existing implementation and that is by using iconName
on the StatusIconAndText component. (see https://github.com/openshift/console/pull/1774/files#diff-2b92d7e552b962318adc922d3e6f4b61R39). I find this also quite bad as it forces you to specify icon name, which can lead to icon usage inconsistency and problems when icons are refactored/changed.
@spadgett noted a problem of ensuring to achieve consistency of same icon always being used for given status string. I think my changes don't make the current situation worse in this regard. Your example shows, there are cases when it is necessary to deviate from this. My changes add standardised status components which should help avoid this.
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.
heh of course i wasn't thinking about title being the status itself ... argh
|
||
export const StatusIconAndText: React.FC<StatusIconAndTextProps> = ({ icon, title, spin }) => { | ||
if (!title) { | ||
return <>{DASH}</>; |
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: isn't it possible to simply return a string here? (without wrapping it in a fragment, which doesn't contribute any markup on its own)
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.
Unfortunately not! Typescript bug ;/
}; | ||
|
||
export const Status: React.FC<StatusProps> = ({ status, children }) => { | ||
switch (status) { |
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 seems that the concepts of status
and title
are merged together at the moment, carried over from the existing StatusIconAndText
component design.
With this Status
component, we could map states (statuses?) to titles if we ever decide to decouple these concepts. In general, the status
string should be the key indicator to determine icon and any other data needed to render the underlying StatusIconAndText
.
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
case 'Completed': | ||
case 'Enabled': | ||
case 'Ready': | ||
case 'Up to date': |
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: this is inconsistent with other status values where words are always capitalized, but I guess we want to keep it this way for now.
return ( | ||
<> | ||
{icon && | ||
React.cloneElement(icon, { |
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: I think we should avoid React.cloneElement
if possible.
Did you consider using an Icon
prop that references a React component type, instead of its instance?
For example: Icon && <Icon className={...} otherProp={...} />
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.
@christianvogt suggested the same, that solution prevents ability to pass custom props to the icon. We would have to introduce additional iconProps prop to satisfy that. Maybe passing additional props is YAGNI but I would rather keep that option available to provide a way to pass in custom className or id which IMHO can be a valid use case.
+1 from me as well. |
If we could use ESLint to check this (in a way that fits the modular |
But we should look to add this sort of popover consistently throughout console instead of just these specific plugins. My concern is that we're only adding it in a few places and not looking more broadly at existing console pages. Notably we should align the project workloads tab error reporting with these status popovers. They have a similar purpose, but are implemented differently (tooltips). But we also show status in many other places (pods, builds, routes, etc.). |
@spadgett Is it worth making a push to quickly find other places in the UI where this info would be helpful so that the addition isn't too jarring? If we were able to provide locations and content, how hard would it be to add to more pages? |
As part of this PR I am replacing all occurrences of existing StatusIconAndText and replacing it with new Status component (second commit 099db40). I think we can easily go through these replacements and identify if there is an error message available and add the message to I found out that there are 2 places where |
|
/retest |
/test e2e-aws |
/lgtm |
/hold cancel |
/test e2e-aws-console |
1 similar comment
/test e2e-aws-console |
/retest Please review the full test history for this PR and help us cut down flakes. |
6 similar comments
/retest Please review the full test history for this PR and help us cut down flakes. |
/retest Please review the full test history for this PR and help us cut down flakes. |
/retest Please review the full test history for this PR and help us cut down flakes. |
/retest Please review the full test history for this PR and help us cut down flakes. |
/retest Please review the full test history for this PR and help us cut down flakes. |
/retest Please review the full test history for this PR and help us cut down flakes. |
* Introduces common Status components which are supposed to replace current StatusIconAndText component usage * Expands Icon + Text implementation with Link and Popover capabilities * Allows to define custom resource specific status handling while reusing existing status components (important for plugins) * Allows to easily define custom status components while reusing underlining components provided * Current StatusIconAndText usage is replaces by Status component * Uses PatternFly4 icons * Adds ability to render icon only * Adds ability to specify custom title for the status
Module is replaced with new components in @console/shared/components/status
Rebased, fixed conflict in |
/test e2e-aws-console-olm |
/lgtm |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: honza, jtomasek, vojtechszocs The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
StatusIconAndText
component usageStatusIconAndText
usage is replaces byStatus
componentNext steps:
StatusIconAndText
component withStatus
componentStatusIconAndText
component