-
Notifications
You must be signed in to change notification settings - Fork 30
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
Assign policy wizard #906
Assign policy wizard #906
Conversation
/hold |
236d1fc
to
fed040c
Compare
fed040c
to
7d54c68
Compare
7d54c68
to
0c69e3c
Compare
}) => { | ||
const [isOpen, setOpen] = React.useState(false); | ||
const [selected, setSelected] = React.useState<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.
In the Assign policy modal, the use case is to clear all selected labels for the clear button. So i want to control setSelected from outside of this component.
@@ -190,6 +193,8 @@ export const NameValueEditor: React.FC<NameValueEditorProps> = | |||
toolTip, | |||
nameString, | |||
valueString, | |||
extraProps, | |||
PairElementComponent = PairElement, |
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 am passing my own custom component to change the NameValueEditor body, But functionality is re-used.
@@ -337,10 +338,6 @@ export const LocalVolumeSetBody: React.FC<LocalVolumeSetBodyProps> = ({ | |||
onChange={(selectedValues: string[]) => | |||
formHandler('deviceType', selectedValues) | |||
} | |||
defaultSelected={[ |
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.
Since I removed setSelected from multiselecteddropdown.tsx, it no longer has defaultSelected props. I am expecting the state variable "selected" should be pre-initialized with the default variable.
state.deviceType has default redux initialized value of this defaultSelected, no need to pass explicitly.
@@ -0,0 +1,137 @@ | |||
import { DRPC_STATUS } from '@odf/mco/constants'; | |||
import { DisasterRecoveryFormatted } from '@odf/mco/hooks'; |
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 can reuse this file for a subscription app also, so created separate util for that
0c69e3c
to
b0faa16
Compare
Screencast.from.2023-06-28.15-57-10.webm |
b0faa16
to
0c11eea
Compare
0c11eea
to
fcc4846
Compare
/hold cancel |
a772c18
to
4bc26d9
Compare
packages/mco/constants/common.ts
Outdated
@@ -14,3 +14,5 @@ export const enum VOLUME_REPLICATION_HEALTH { | |||
export const ACM_OBSERVABILITY_FLAG = 'ACM_OBSERVABILITY'; | |||
export const ADMIN_FLAG = 'ADMIN'; | |||
export const ODFMCO_OPERATOR_NAMESPACE = 'openshift-operators'; | |||
export const ACM_SEARCH_PROXY_URL = | |||
'/api/proxy/plugin/acm/console/multicloud/proxy/search'; |
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.
Need to move all ACM related constant in separate file
drPlacementControl?: DRPlacementControlKind; | ||
drPolicy?: DRPolicyKind; | ||
drClusters?: DRClusterKind[]; |
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.
drpc resources are optional for unprotected apps
}) => { | ||
const [isOpen, setOpen] = React.useState(false); | ||
const [selected, setSelected] = React.useState<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.
b1ce37f
to
1f026c2
Compare
locales/en/plugin__odf-console.json
Outdated
@@ -214,7 +225,17 @@ | |||
"Assigned on": "Assigned on", | |||
"View configurations": "View configurations", | |||
"No activity": "No activity", | |||
"Back": "Back", | |||
"Delete": "Delete", | |||
"Select a placement": "Select a placement", |
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.
"Select a placement": "Select a placement", | |
"Select a placement": "Select a placement", |
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.
ack
}; | ||
} else { | ||
return { | ||
title: t('Manage data policy'), |
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.
are we still calling it Manage data policy
even though we only allow assign as of now ?
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.
Ya, But Title and description needs to be decided, doc team is working on this
|
||
const assignPolicy = () => { | ||
setAssignDisabled(true); | ||
const updateContext = async ( |
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 updateContext = async ( | |
const updateContext = ( |
const getPlacementTags = (drpcs: DRPlacementControlType[]) => | ||
!!drpcs.length | ||
? drpcs.map( | ||
(drpc) => [getName(drpc.placementInfo), drpc?.pvcSelector] || [] |
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 will never reach this condition...
(drpc) => [getName(drpc.placementInfo), drpc?.pvcSelector] || [] | |
(drpc) => [getName(drpc.placementInfo), drpc?.pvcSelector] |
const getLabelsFromSearchResult = (searchResult: SearchResult): string[] => { | ||
const pvcLabels = | ||
searchResult?.data.searchResult?.[0]?.items.reduce( | ||
(acc, item) => [...acc, ...item?.[LABEL]?.split(SPLIT_CHAR)], |
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.
spread will give error when item?.[LABEL]?.split(SPLIT_CHAR)
is undefined
...
const getLabelsFromSearchResult = (searchResult: SearchResult): string[] => { | ||
const pvcLabels = | ||
searchResult?.data.searchResult?.[0]?.items.reduce( | ||
(acc, item) => [...acc, ...item?.[LABEL]?.split(SPLIT_CHAR)], |
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 should work ??
(acc, item) => [...acc, ...item?.[LABEL]?.split(SPLIT_CHAR)], | |
(acc, item) => [...acc, ...item[LABEL]?.split(SPLIT_CHAR)], |
|
||
const getPlacementsFromTags = (tags: TagsType, currIndex: number): string[] => | ||
tags.reduce((acc, tag, index) => { | ||
const placement = tag?.[0]; |
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 not an array like 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.
tag is an array type and it has only two indexes, one is the placement of string type, other one is the label of string[] type.
type TagsType = (string | string[])[][];
basically tag?.[0] is string, tag?.[1]; is array
const NameValueEditorComponent = (props) => ( | ||
<AsyncLoader | ||
loader={() => | ||
import('@odf/shared/utils/NameValueEditor').then((c) => c.NameValueEditor) | ||
} | ||
{...props} | ||
/> | ||
); |
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.
nits: better to export this as LazyNameValueEditor
from shared
and use that everywhere...
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.
also do we even need lazy import ??
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 are using lazy loading against NameValueEditor component in multiple places for code splitting: https://legacy.reactjs.org/docs/code-splitting.html
To avoid increasing the size of the bundle using some complex library.
Thanks, @bipuladh for the ref 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.
yup, I got that... but my doubt was whether we are saving lot of bundle size by doing splitting here ??
Default NameValueEditor
had code for PairElement
, but in MCO we are passing that as a prop as well PairElementComponent
(which means it is getting bundled in same code as the one which is calling the FC)... so is there any major advantage of splitting here ??
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.
anyway, no issues with using lazy loading, but don;t see any specific reason as well here... by some complex library
do u mean these ??
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
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.
Maybe i am wrong here but I thought bundle creation is nothing to do with runtime calls, MCO calls the PairElementComponent, or PairElement is decided at runtime, so it will still affect the bundle size when i use NameValueEditor directly.
values: clusterNames, | ||
}, | ||
], | ||
limit: 20, |
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.
- do we need limit ??
- in the
workloadNamespace
, can there be PVCs which are not related to this Application, how we decide whether a PVC is independent or belongs to an ACM Application ??
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, UI API read needs a limit. UI can't read large amounts of PVCs. It will affect the performance. As per PM and QE, the number of PVCs per app is around 20 only, the count may go a little bit higher in the future but never read all PVCs blindly.
UI can't decide which PVCs are related to the app and which PVCs are not realted. UI is just assuming all PVCs under the namespace are realted to the app only. It is up to the user to decide which label to select.
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.
so it will mean that for cases where app has more than 20 PVCs, our UI will not work as expected and can show some missing 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.
UI needs a limit, If they wants to use more PVC, then they have to use CLI way
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.
my question here would be limit
just tells us how my data points the response
from the API call will be right ??
If limit=20 or limit=200, in both cases it will still be a single API request right ?? so will it make diff to hard limit it to be 20
PVCs ?? @GowthamShanmugam
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.
in list pages, say Secrets
a cluster can have 300 secrets as well... all we display on UI and we send a single API call which gives us all 300 secret in a single response...
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.
UI just need to maintain a list of all PVCs (which it can easily), any other performance impact which I might be missing ??
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 usually send an API request to the local cluster, But here ACM search API is sending an API request to the managed clusters.
ACM is sending an API request to its managed cluster agent, and an agent will receive the API request and read all PVC from the namespace and convert the result to a custom response object and send it back to the hub cluster.
if we give a limit of 20 then it will read only first 20 PVCs from the namespace. it means the API request will be waiting for the 20 PVC results to be parsed. If we increase the limit then it will take increase the API response time.
Per namespace, I dont think the user will create more than 20 PVCs, If QE thinks the number is not enough i will increase 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.
The idea here is, not all PVCs should have a unique namespace, the user has to reuse the labels as much as possible between PVCs
export const getClusterNamesFromPlacements = (placements: PlacementType[]) => | ||
placements?.reduce( | ||
(acc, placemnt) => [...acc, ...placemnt?.deploymentClusters], | ||
[] | ||
); |
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 to confirm, r u sure we already do not have this function defined somewhere ?? seems like something we have done at other places as well.
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 for the custom object type, the old one for the PlacementDecisionKind object which takes from clusters from status?.decisions
); | ||
|
||
// ACM search proxy api call | ||
const [searchResult] = useACMSafeFetch( |
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 about handling loading
and error
??
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 thought about this, but with the current UX I dont see any places to display error message or any other option, Need to check with ux what to do
const createDRPlacementControlObj = ( | ||
placement: PlacementType, | ||
dataPolicyRef: ObjectReference | ||
): DRPlacementControlType => ({ | ||
apiVersion: DRPlacementControlModel.apiVersion, | ||
kind: DRPlacementControlModel.kind, | ||
metadata: { | ||
name: `${getName(placement)}-drpc`, | ||
namespace: getNamespace(placement), | ||
}, | ||
drPolicyRef: dataPolicyRef, | ||
placementInfo: placement, | ||
pvcSelector: [], | ||
}); | ||
|
||
const updateLabels = ( | ||
drPlacementControl: DRPlacementControlType, | ||
labels: string[] | ||
): DRPlacementControlType => ({ | ||
...drPlacementControl, | ||
pvcSelector: 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.
can't we re-use getDRPCKindObj
from utils
??
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 custom-type object for wizard flow,
All the components under the manage policy modal will understand this custom type,
So I am keeping this custom type to reuse components, for example, policy configuration view (used for review and create page, as well as to display policy configurations)
At the end of the assign policy wizard i am converting this custom type to using getDRPCKindObj to create DRPC.
packages/mco/hooks/acm-safe-fetch.ts
Outdated
.catch((err) => { | ||
setError(err); | ||
}); | ||
}, [setResponse, searchQuery, safeFetch]); |
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.
}, [setResponse, searchQuery, safeFetch]); | |
}, [setResponse, searchQuery]); |
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.
safeFetch is also one dependency
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 needed as it won;t change (check useURLPoll
)...
if needed anyway then wrap safeFetch
in a useCallback
before returning it from 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.
currently if u add it as it is then it will cause issues...
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 sure how it works for useURLPoll, i am getting lint error if i am not adding it in dependency
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.
u can disable the lint error... or if u do not want to do that let;s use useCallback
so that ref of safeFetch
do not changes...
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.
for disabling use // eslint-disable-next-line <error_name>
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 want to use useCallback
u need to use it in the hook itself that returns safeFetch
.
d478a7e
to
08d45c9
Compare
Signed-off-by: Gowtham Shanmugasundaram <[email protected]>
08d45c9
to
f01c7a1
Compare
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.
lgtm
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: GowthamShanmugam, SanjalKatiyar 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 |
/test odf-console-e2e-aws |
On top of: #903