-
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
Add buckets overview page (header, details/objects list tabs, actions) layout #1591
Add buckets overview page (header, details/objects list tabs, actions) layout #1591
Conversation
82f6556
to
4caedcc
Compare
packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx
Outdated
Show resolved
Hide resolved
@SanjalKatiyar you should rebase in order to fix conflicts in |
Ack, will do once PR is reviewed and fix it along with other review comments. |
...(isCreatedByOBC | ||
? [ | ||
{ | ||
title: t('Edit labels'), | ||
onClick: () => | ||
launcher(defaultModalMap[ModalKeys.EDIT_LABELS], { | ||
extraProps: { | ||
resource: noobaaObjectBucket, | ||
resourceModel: NooBaaObjectBucketModel, | ||
}, | ||
isOpen: true, | ||
}), | ||
}, | ||
] | ||
: []), | ||
...(isCreatedByOBC | ||
? [ | ||
{ | ||
title: t('Edit annotations'), | ||
onClick: () => | ||
launcher(defaultModalMap[ModalKeys.EDIT_ANN], { | ||
extraProps: { | ||
resource: noobaaObjectBucket, | ||
resourceModel: NooBaaObjectBucketModel, | ||
}, | ||
isOpen: true, | ||
}), | ||
}, | ||
] | ||
: []), | ||
...(isCreatedByOBC | ||
? [ | ||
{ | ||
title: t('Edit bucket'), | ||
onClick: () => navigate(`${BUCKETS_BASE_ROUTE}/${bucketName}/yaml`), | ||
}, | ||
] |
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 there any reason the same check has been repeated? we can move three options from the same list, right?
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.
will update...
}, | ||
] | ||
: []), | ||
...(isCreatedByOBC |
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 YAML visible for folder view?
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! isCreatedByOBC will be false for folder view, got it
I prefer to move comment (will be false if we are inside folder view): https://github.com/red-hat-storage/odf-console/pull/1591/files#diff-1f39da47c37a872f0a045b71647ab27ae7d8e5527e3c38457b910e79538ef615R118 here
) | ||
); | ||
const noobaaObjectBucket: K8sResourceKind = objectBuckets?.find( | ||
(ob) => ob.spec?.endpoint?.bucketName === bucketName |
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 doubt is do we need to loop all object buckets? we can use the bucketName in useK8sWatchResource to look for the specific object right? if the bucket name is found then it is OBC then not found then s3.
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.
"ObjectBucket" CR name is different from actual underlying "Bucket" name... CR's spec will have the correct name...
const { t } = useCustomTranslation(); | ||
|
||
const { noobaaS3 } = React.useContext(NoobaaS3Context); | ||
const { data, error, isLoading } = useSWR(LIST_BUCKET, () => |
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! there is no API endpoint to read a specific bucket?
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.
yeah, I did not find any...
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.
@SanjalKatiyar have you cheked HeadBucket
?
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.
Nevermind, it seems it doesn't contain the info you need...
<CreatedOnSkeleton /> | ||
) : ( | ||
<h4 className="text-muted"> | ||
{t('Created on: ') + bucketCreatedOn?.toString()} |
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.
OCP console follows UTC date-time format, we need to makesure it display on a same format
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 !
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 keeping it as it is for now... ODF shows UTC only for tooltip, we don't have tooltip right now here... other issue is Timestamp
FC display time as eg: 7 mins ago
etc which works well for websocket connections as time gets continuously updated, but here we have to manually refresh...
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 displayed format here will be dependent on local timezone... we can confirm on @alfonsomthd system once this PR is merged...
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.
@SanjalKatiyar the UK dev cluster has set the London timezone, so we can test it there.
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 check, in case SDK passes the timezone info to the server based off browser's settings then even UK cluster will not work for the verification... u will have to later run specifically on your system and verify...
return ( | ||
<div className="pf-v5-u-display-flex pf-v5-u-flex-direction-column"> | ||
<div className="pf-v5-u-display-flex pf-v5-u-flex-direction-row"> | ||
{!foldersPath ? bucketName : currentFolder}{' '} |
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.
{!foldersPath ? bucketName : currentFolder}{' '} | |
{!foldersPath ? bucketName : currentFolder} |
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 was added by linter, will check again though...
</div> | ||
{!foldersPath && | ||
(fresh ? <CreatedOn bucketName={bucketName} /> : <CreatedOnSkeleton />)} | ||
<h4> |
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 asking myself is correct to add components inside tags like h, Text, p, etc..
will figure it out :)
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.
yeah, no issues with that...
CustomActionsToggleProps, | ||
} from '@patternfly/react-table'; | ||
import { LIST_OBJECTS, DELIMITER, MAX_KEYS, PREFIX } from '../../../constants'; | ||
import { ObjectCrFormat } from '../../../types'; |
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.
import { ObjectCrFormat } from '../../../types'; | |
import { ObjectCRFormat } from '../../../types'; |
thoughts?
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.
either is fine IMO, we don't follow any specific rule in this repo... I have seen both naming formats...
} from '@patternfly/react-table'; | ||
import { LIST_OBJECTS, DELIMITER, MAX_KEYS, PREFIX } from '../../../constants'; | ||
import { ObjectCrFormat } from '../../../types'; | ||
import { getPath, convertObjectsDataToCrFormat } 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.
import { getPath, convertObjectsDataToCrFormat } from '../../../utils'; | |
import { getPath, convertObjectsDataToCRFormat } from '../../../utils'; |
same here
if (isNext) { | ||
newTokens.previous.push(newTokens.current); | ||
newTokens.current = newTokens.next; | ||
} else { | ||
newTokens.current = newTokens.previous.pop(); | ||
} | ||
newTokens.next = response.NextContinuationToken; |
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 (isNext) { | |
newTokens.previous.push(newTokens.current); | |
newTokens.current = newTokens.next; | |
} else { | |
newTokens.current = newTokens.previous.pop(); | |
} | |
newTokens.next = response.NextContinuationToken; | |
if (isNext) { | |
newTokens.previous.push(newTokens.current); | |
newTokens.current = newTokens.next; | |
newTokens.next = response.NextContinuationToken; | |
} else { | |
// I am assuming this is for back | |
newTokens.next = newTokens.current | |
newTokens.current = newTokens.previous.pop(); | |
} |
because back noting to do with response.NextContinuationToken I 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.
current conditions in the PR are tested and works 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.
Ok! it works becuase in esponse.NextContinuationToken and newTokens.current may have same values.
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.
But i agree it is safer to use in response.NextContinuationToken for newTokens.next. because,if any object is deleted, then newTokens.current is not the right value to use. i like this logic.
<Skeleton width="25%" height="15%" /> | ||
); | ||
|
||
const CreatedOn: React.FC<{ bucketName: string }> = ({ bucketName }) => { |
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 types.
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 didn't get it, I am using type, right ?? just I am not storing it in a separate variable as it's only a single prop...
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 always use a different variable in our codebase. So it would be nice to stick to the conventions.
const name = object.metadata.name.replace(foldersPath, ''); | ||
const prefix = !!foldersPath | ||
? encodeURIComponent(foldersPath + name) | ||
: encodeURIComponent(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.
prefix is required for non-foldersPath also? means, when the foldersPath is empty then encodeURIComponent for prefix and prefix used under {isFolder ? (
os isFolder can be true when foldersPath is empty ?
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 used for creating a URL for the folder view, each folder view will have a prefix in the URL...
initial buckets page will not have foldersPath
, but when we drill down prefix will be folder name...
|
||
const { launcher, bucketName, foldersPath } = extraProps; | ||
const isFolder = object.isFolder; | ||
const name = object.metadata.name.replace(foldersPath, ''); |
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 name = object.metadata.name.replace(foldersPath, ''); | |
const name = getName(object).replace(foldersPath, ''); |
optional
<Td translate={null} dataLabel={columnNames[3]}> | ||
{object.apiResponse.lastModified} | ||
</Td> | ||
<Td translate={null} dataLabel={columnNames[3]} isActionCell> |
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.
columnNames[3] is used twice, is this expected?
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.
@GowthamShanmugam @SanjalKatiyar this is why I would prefer for all our tables to not depend on hardcoded column numbers but iterating and using the iterator index variable (or column id) so adding/removing a column should be error-free.
Here is how I did it for storage client list.
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.
@SanjalKatiyar not saying that my suggestion should be applied here in this PR: just something that we should discuss (also better alternatives) for future implementations.
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.
From the link above, what I understood is, that you are suggesting to use name as a column id.
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 !
4caedcc
to
4ce0c35
Compare
4ce0c35
to
baab291
Compare
const actions = () => { | ||
return ( |
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 actions = () => { | |
return ( | |
const actions = () => ( |
nit
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 !
variant={ButtonVariant.link} | ||
icon={<BlueSyncIcon />} | ||
onClick={triggerRefresh} | ||
isDisabled={!fresh} |
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.
Does fresh
mean being refreshed? If that is the case let's rename it to isRefreshing
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.
fresh = true
means it's latest (mounting/mounted)... fresh = false
means it's refreshing (un-mounting/un-mounted)...
<Skeleton width="25%" height="15%" /> | ||
); | ||
|
||
const CreatedOn: React.FC<{ bucketName: string }> = ({ bucketName }) => { |
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 always use a different variable in our codebase. So it would be nice to stick to the conventions.
); | ||
}; | ||
|
||
const BucketResourceStatus: React.FC<{ resourceStatus: 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.
Same as above. Let's stick to our conventions.
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 see multiple such instance where we are using types directly for a FC (instead of a variable), even I wasn't aware that we have such a convention :P
} | ||
|
||
.bucket-label--margin-top { | ||
margin-top: calc(0.3rem * -1); |
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.
why are we using negative margin to pull things? There should be a better way to do 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.
Just curious, is something wrong with -ve values ??
Even MDN describe it as A positive value places it farther from its neighbors, while a negative value places it closer
in it's very first paragraph :/ (also, I didn't find it being mentioned as a bad practice or bad convention).
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: bipuladh, 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 |
eb8baf6
into
red-hat-storage:master
https://issues.redhat.com/browse/RHSTOR-6196
https://issues.redhat.com/browse/RHSTOR-6199