Skip to content
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

Merged

Conversation

SanjalKatiyar
Copy link
Collaborator

@SanjalKatiyar SanjalKatiyar commented Sep 20, 2024

@SanjalKatiyar SanjalKatiyar force-pushed the s3_object_list branch 8 times, most recently from 82f6556 to 4caedcc Compare September 25, 2024 14:30
@SanjalKatiyar SanjalKatiyar changed the title [WIP] Add buckets overview page (header, details/objects list tabs, actions) layout Add buckets overview page (header, details/objects list tabs, actions) layout Sep 25, 2024
@alfonsomthd
Copy link
Collaborator

@SanjalKatiyar you should rebase in order to fix conflicts inlocales/en/plugin__odf-console.json.

@SanjalKatiyar
Copy link
Collaborator Author

@SanjalKatiyar you should rebase in order to fix conflicts inlocales/en/plugin__odf-console.json.

Ack, will do once PR is reviewed and fix it along with other review comments.

Comment on lines 51 to 77
...(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`),
},
]
Copy link
Contributor

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?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will update...

},
]
: []),
...(isCreatedByOBC
Copy link
Contributor

@GowthamShanmugam GowthamShanmugam Sep 27, 2024

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?

Copy link
Contributor

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
Copy link
Contributor

@GowthamShanmugam GowthamShanmugam Sep 27, 2024

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.

Copy link
Collaborator Author

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, () =>
Copy link
Contributor

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?

Copy link
Collaborator Author

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...

Copy link
Collaborator

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 ?

Copy link
Collaborator

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()}
Copy link
Contributor

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack !

Copy link
Collaborator Author

@SanjalKatiyar SanjalKatiyar Sep 30, 2024

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...

Copy link
Collaborator Author

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...

Copy link
Collaborator

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.

Copy link
Collaborator Author

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}{' '}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{!foldersPath ? bucketName : currentFolder}{' '}
{!foldersPath ? bucketName : currentFolder}

Copy link
Collaborator Author

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>
Copy link
Contributor

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 :)

Copy link
Collaborator Author

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';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { ObjectCrFormat } from '../../../types';
import { ObjectCRFormat } from '../../../types';

thoughts?

Copy link
Collaborator Author

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';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { getPath, convertObjectsDataToCrFormat } from '../../../utils';
import { getPath, convertObjectsDataToCRFormat } from '../../../utils';

same here

Comment on lines +75 to +81
if (isNext) {
newTokens.previous.push(newTokens.current);
newTokens.current = newTokens.next;
} else {
newTokens.current = newTokens.previous.pop();
}
newTokens.next = response.NextContinuationToken;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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

Copy link
Collaborator Author

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...

Copy link
Contributor

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.

Copy link
Contributor

@GowthamShanmugam GowthamShanmugam Sep 27, 2024

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 }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use types.

Copy link
Collaborator Author

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...

Copy link
Contributor

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);
Copy link
Contributor

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 ?

Copy link
Collaborator Author

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, '');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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>
Copy link
Contributor

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?

Copy link
Collaborator

@alfonsomthd alfonsomthd Sep 30, 2024

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.

Copy link
Collaborator

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.

Copy link
Contributor

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack !

Comment on lines +143 to +144
const actions = () => {
return (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const actions = () => {
return (
const actions = () => (

nit

Copy link
Collaborator Author

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}
Copy link
Contributor

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

Copy link
Collaborator Author

@SanjalKatiyar SanjalKatiyar Sep 30, 2024

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 }) => {
Copy link
Contributor

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 }> = ({
Copy link
Contributor

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.

Copy link
Collaborator Author

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);
Copy link
Contributor

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.

Copy link
Collaborator Author

@SanjalKatiyar SanjalKatiyar Sep 30, 2024

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).

@bipuladh
Copy link
Contributor

/lgtm
We can take up the minor comments in the follow up PRs

Copy link
Contributor

openshift-ci bot commented Sep 30, 2024

[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:
  • OWNERS [SanjalKatiyar,bipuladh]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot openshift-merge-bot bot merged commit eb8baf6 into red-hat-storage:master Sep 30, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants