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 users list to vm details page #5698
Conversation
@pcbailey please reveiw |
1f07213
to
d625935
Compare
frontend/packages/kubevirt-plugin/src/components/vms/vm-users.tsx
Outdated
Show resolved
Hide resolved
props: { className: tableColumnClasses[1] }, | ||
}, | ||
{ | ||
title: 'Log in time', |
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 "Login time" instead of "Log in time". There's a slight difference between the two. "Log in" is an instruction to someone to log in to the system, with "log" being used as a verb. A "login" is a noun and refers to either the credentials used to log in to a system or a specific instance where a user has logged in.
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.
hmm.. thanks !
did look a little off to me didn't know why :-)
|
||
const UsersTableRow = ({ obj, index, key, style }) => { | ||
return ( | ||
<TableRow id={obj?.metadata.uid} index={index} trKey={key} style={style}> |
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 isobj
? I assume it's user information. I would recommend using a more descriptive name unless there's a reason to leave it generic. Could we use selectors to access the properties of obj
?
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.
nice +1, fixed
{obj?.metadata?.domain} | ||
</TableData> | ||
<TableData className={tableColumnClasses[2]}> | ||
<Timestamp timestamp={new Date(obj?.metadata?.loginTime).toUTCString()} /> |
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 much cleaner than the date formatting code you were working with before. =)
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.
yes :-)
return ( | ||
<StatusItem | ||
Icon={BlueInfoCircleIcon} | ||
message="This VM does not have guest agent installed. Some metrics and management features will not be available." |
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 probably add this message text as a constant in one of the strings files so we can use it wherever it's needed.
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
const url = `apis/subresources.kubevirt.io/v1alpha3/namespaces/${namespace}/virtualmachineinstances/${name}/guestosinfo`; | ||
|
||
const usersResult = urlResults.getIn([url, 'data']); | ||
const usersResultError = urlResults.getIn([url, 'loadError']); | ||
|
||
const data = | ||
usersResult && | ||
usersResult?.userList && | ||
usersResult?.userList.map((u) => ({ | ||
metadata: { | ||
name: u?.userName, | ||
domain: u?.domain, | ||
loginTime: u?.loginTime && u.loginTime * 1000, | ||
}, | ||
})); | ||
|
||
React.useEffect(() => { | ||
watchURL(url); | ||
return () => { | ||
stopWatchURL(url); | ||
}; | ||
}, [watchURL, stopWatchURL, url]); |
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 assume we're going to put this code in a centralized location? I can add it to my existing PR if you want, and maybe create a wrapper class to make it easier to work with. What do you think?
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.
@yaacov @pcbailey
Are you sure we should be using withDashboardResources HOC for list which is not inside the dashboard?
We are going to reuse this url call in multiple places?
Having a hook for this would be nice. It would be also nicer if we could remove the HOC altogether and have all the logic in the hook.
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.
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.
+1
|
||
const name = getName(vmi); | ||
const namespace = getNamespace(vmi); | ||
const url = `apis/subresources.kubevirt.io/v1alpha3/namespaces/${namespace}/virtualmachineinstances/${name}/guestosinfo`; |
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.
can we make a function out of 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.
done
const url = `apis/subresources.kubevirt.io/v1alpha3/namespaces/${namespace}/virtualmachineinstances/${name}/guestosinfo`; | ||
|
||
const usersResult = urlResults.getIn([url, 'data']); | ||
const usersResultError = urlResults.getIn([url, 'loadError']); | ||
|
||
const data = | ||
usersResult && | ||
usersResult?.userList && | ||
usersResult?.userList.map((u) => ({ | ||
metadata: { | ||
name: u?.userName, | ||
domain: u?.domain, | ||
loginTime: u?.loginTime && u.loginTime * 1000, | ||
}, | ||
})); | ||
|
||
React.useEffect(() => { | ||
watchURL(url); | ||
return () => { | ||
stopWatchURL(url); | ||
}; | ||
}, [watchURL, stopWatchURL, url]); |
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.
@yaacov @pcbailey
Are you sure we should be using withDashboardResources HOC for list which is not inside the dashboard?
We are going to reuse this url call in multiple places?
Having a hook for this would be nice. It would be also nicer if we could remove the HOC altogether and have all the logic in the hook.
usersResult && | ||
usersResult?.userList && | ||
usersResult?.userList.map((u) => ({ | ||
metadata: { |
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 know we do this for name sorting, but still it is a bit weird to wrap everything in metadata. I wonder if we can do something about it.
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.
ahhh, forgot to do the sorting ... addning sort ( I knew the metadata has a reason :-) )
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.
added the missing sort
|
||
const tableColumnClasses = [ | ||
classNames('col-lg-3', 'col-md-3', 'col-sm-4', 'col-xs-6'), | ||
classNames('col-lg-3', 'col-md-3', 'col-sm-4', 'hidden-xs'), |
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 the domain? Is it a good decision to hide it for smaller devices?
Shouldn't we switch the priority and show the Login time instead of Elapsed login time on smaller devices? Especially, because there is timezone in Login time
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 the domain?
domain is the ip address user logged in from, if we need to choose logged in time and domain, I'll choose logged in time
Shouldn't we switch the priority and show the Login time instead of Elapsed login time on smaller devices? Especially, because there is timezone in Login time
make sense to me too, switching
p.s.
@matthewcarleton in the designs do we have a way to specify how things look on small screens ?
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
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.
domain is the ip address user logged in from, if we need to choose logged in time and domain, I'll choose logged in time
I see, I vote for having user | domain | login time
visible every time
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 :-) fixing
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
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 the domain?
domain is the ip address user logged in from, if we need to choose logged in time and domain, I'll choose logged in time
Shouldn't we switch the priority and show the Login time instead of Elapsed login time on smaller devices? Especially, because there is timezone in Login time
make sense to me too, switching
p.s.
@matthewcarleton in the designs do we have a way to specify how things look on small screens ?
If we are using a PF4 component it should be good for mobile right? Is there anything unique about this that doesn't just use a default PF table?
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 we are using a PF4 component it should be good for mobile right? Is there anything unique about this that doesn't just use a default PF table?
@matthewcarleton
yes, the question here is witch columns should magically disappear on small displays.
The discussion above is: should we show 3 or only 2 columns on extra small display.
for example we decided here to show 3 columns ( removed the elapsed time ):
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.
sorry I didn't get this before it merged but we should be using a modifier class to get the responsive state.
If you use pf-m-grid-md
you won't need to remove that column for smaller screens b/c it will stack.
f23851a
to
69bd9d1
Compare
Patternfly table makes the sorted column blue, see: |
/test e2e-gcp-console |
fixed :-) |
@@ -0,0 +1,152 @@ | |||
import * as React from 'react'; | |||
import { connect } from 'react-redux'; | |||
import { watchURL, stopWatchURL } from '@console/internal/actions/dashboards'; |
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.
dont use dashboards stuff outside of dashboards. It would be good to create a new hook for polling some url. You can take a look at https://github.com/openshift/console/blob/master/frontend/public/components/graphs/prometheus-poll-hook.ts - create something generic and reuse it also in prometheus-poll-hook
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 ! using pool hook now
import { VMIKind } from '../../types'; | ||
|
||
const guestAgentURL = (name: string, namespace: string) => | ||
`apis/subresources.kubevirt.io/v1alpha3/namespaces/${namespace}/virtualmachineinstances/${name}/guestosinfo`; |
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.
There's already logic for creating subresources url such as https://github.com/openshift/console/blob/master/frontend/packages/kubevirt-plugin/src/selectors/vmi/combined.ts#L60
you should try to reuse that
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 it's fixed now :-)
})); | ||
|
||
// eslint-disable-next-line react-hooks/rules-of-hooks | ||
React.useEffect(() => { |
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 a coditional usage of hook. It needs to be moved on top before all if/returns
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
/test e2e-gcp-console |
const DEFAULT_SAMPLES = 60; | ||
const DEFAULT_TIMESPAN = 60 * 60 * 1000; // 1 hour | ||
|
||
export const usePrometheusPoll = ({ | ||
delay = DEFAULT_DELAY, | ||
delay = URL_POLL_DEFAULT_DELAY, |
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.
no need to define the default value as url-poll hook does that.
delay = URL_POLL_DEFAULT_DELAY, | |
delay, |
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.
+1
|
||
export const URL_POLL_DEFAULT_DELAY = 15000; // 15 seconds | ||
|
||
export const useURLPoll = ( |
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 could improve the types with some generics. Like defining the return value to not be any
export const useURLPoll = ( | |
export const useURLPoll = <R>( | |
url: string, | |
delay = URL_POLL_DEFAULT_DELAY, | |
...dependencies: any[] | |
): URLPoll<R> => { |
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.
Nice !
return { response, error, loading }; | ||
}; | ||
|
||
export type URLPoll = { |
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.
export type URLPoll = { | |
export type URLPoll<R> = [ R, any, boolean ]; |
|
||
usePoll(tick, delay, ...dependencies); | ||
|
||
return { response, error, loading }; |
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'd prefer to return an array to align with other hooks
return { response, error, loading }; | |
return [ response, error, loading ]; |
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.
+1
@@ -0,0 +1,46 @@ | |||
/* eslint-disable react-hooks/exhaustive-deps */ | |||
import { useCallback, useState } from 'react'; | |||
import { usePoll, useSafeFetch } from '.'; |
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.
please dont import from index file, it causes circular deps
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.
fixed
@@ -59,3 +59,4 @@ export { default } from './operator-backed-owner-references'; | |||
export * from './field-level-help'; | |||
export * from './details-item'; | |||
export * from './types'; | |||
export * from './use-url-hook'; |
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.
lets not add this hook to index file. We want to remove all indexes as they cause issues due to circular deps
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.
fixed
}, [url]); | ||
|
||
usePoll(tick, delay, endTime, query, timespan); | ||
const { response, error, loading } = useURLPoll(url, delay, endTime, query, timespan); |
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 you use array format and generics for useURLPoll use can do
const { response, error, loading } = useURLPoll(url, delay, endTime, query, timespan); | |
return useURLPoll<PrometheusResponse>(url, delay, endTime, query, timespan); |
@@ -0,0 +1,46 @@ | |||
/* eslint-disable react-hooks/exhaustive-deps */ |
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.
to align with other hooks we should call this file url-poll-hook
...dependencies: any[] | ||
): URLPoll => { | ||
const [error, setError] = useState(); | ||
const [response, setResponse] = useState(); |
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.
const [response, setResponse] = useState(); | |
const [response, setResponse] = useState<R>(); |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: rawagner, yaacov 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 |
Add users list to vm details
Design:
http://openshift.github.io/openshift-origin-design/designs/virtualization/4.x/expose-guest-data/expose%20guest%20data.html#details-tab
Screenshot:
two users is logged in
guest agent is not installed
no logged in users
vm is not running
load error: