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

feat(frontend): Show Archive tab for runs in Experiment Detail page #5040

Merged
merged 12 commits into from
Feb 11, 2021

Conversation

zijianjoy
Copy link
Collaborator

@zijianjoy zijianjoy commented Jan 27, 2021

Description of your changes:

Video: https://youtu.be/wlE0rd6235s

Behavior: When user selects an Experiment, it will shows a tab selection in Experiment Detail page for Active and Archived runs.

  1. If Experiment itself is Active, the run list tab selection is Active by default.
  2. If Experiment itself is Archived, the run list tab selection is Archived by default.
  3. If Active run list is selected, toolbar will show Archive button.
  4. If Archive run list is selected, toolbar will show Restore button.

Checklist:

@zijianjoy zijianjoy linked an issue Jan 28, 2021 that may be closed by this pull request
@zijianjoy
Copy link
Collaborator Author

/test kubeflow-pipeline-e2e-test

@Bobgy
Copy link
Contributor

Bobgy commented Jan 29, 2021

@zijianjoy
Copy link
Collaborator Author

The changes seem to break frontend integration testing, you'll need to update https://github.com/kubeflow/pipelines/blob/master/test/frontend-integration-test/helloworld.spec.js accordingly.

You can find the error log at https://oss-prow.knative.dev/view/gs/oss-prow/pr-logs/pull/kubeflow_pipelines/5040/kubeflow-pipeline-e2e-test/1354907745475629056#1:build-log.txt%3A5305

Thank you for pointing it out! I have applied the fix for E2E tests

@Bobgy
Copy link
Contributor

Bobgy commented Feb 3, 2021

@zijianjoy Thank you for building up the new UX! It's absolutely great!

I've just got some minor code organization questions, did you investigate if we can refactor the AllRunsAndArchive.tsx, so that it fits the new needs by RunListsRouter (probably by extracting out a core component with configurable behavior)?

As far I can tell, the two components are almost identical in visual appearance, while the only thing that's different is -- that RunListsRouter filters by an experiment.

RunListsRouter:
image
AllRunsAndArchive:
image

@Bobgy
Copy link
Contributor

Bobgy commented Feb 3, 2021

/cc @StefanoFioravanzo
Looks like you are very active on KFP UI recently, I'm curious if you'd want to participate in some code review.

@StefanoFioravanzo
Copy link
Member

@Bobgy absolutely! I will take a look at the PR in a day or two

@zijianjoy
Copy link
Collaborator Author

As far I can tell, the two components are almost identical in visual appearance, while the only thing that's different is -- that RunListsRouter filters by an experiment.

That is a good point, I have explored merging RunListsRouter.tsx to AllRunsAndArchive.tsx in this PR. However, the current component structure is a bit hard to scale: the existing file name is called AllRunsAndArchive.tsx, and it has two children components as AllRunsLists.tsx and ArchiveRuns.tsx. But if we add one more state to a run in the future, say pending, then we need to create a new child component PendingRuns.tsx, and change the name AllRunsAndArchive.tsx to AllRunsAndArchiveAndPending.tsx.

Therefore I suggest to start a new file called RunListsRouter, and progressively migrate the existing component structure to there. Since this refactoring is going to be big and out-of-scope for the issue, I am going to hold on to it for now.

How do you think?

@Bobgy
Copy link
Contributor

Bobgy commented Feb 4, 2021

Thanks, sounds like a good plan.
I'll take a look again as if RunListsRouter will be the future core that supports all our major requirements

Copy link
Contributor

@Bobgy Bobgy left a comment

Choose a reason for hiding this comment

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

The code looks good overall!

I did a detailed code read and left some -- mostly nit pickings.

frontend/src/pages/RunListsRouter.tsx Outdated Show resolved Hide resolved
*/
class RunListsRouter extends React.PureComponent<RunListsRouterProps> {
protected _isMounted = true;
private _runlistRef = React.createRef<RunList>();
Copy link
Contributor

Choose a reason for hiding this comment

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

Writing some longer term issues we need to address later. (Non blocker for this PR)

https://reactjs.org/docs/refs-and-the-dom.html
It's recommended to avoid using ref when possible, because the data/event flow mechanism conflicts with React's recommendation of one-way data flow philosophy (see https://reactjs.org/docs/thinking-in-react.html).

For example, instead of exposing open() and close() methods on a Dialog component, pass an isOpen prop to it.

Similar to this example, I think to avoid exposing refresh() as a public method, we could have a prop called sth like refreshCounter: number, the child components can do a refresh whenever it sees an update in refreshCounter -- using componentDidUpdate or useEffect react hook. In this way, we no longer need to add refs all the way and trigger a method to refresh components, one refresh would be as simple as a state update to the refreshCounter.
We'd also need a onLoad callback, that will be triggered by child components when a page finishes loading.

I think these comments may be hard to follow, we can follow up later to dive into more details. I'd like to start these discussions now, because I know there are many anti-patterns in the existing code and I hope they do not keep contaminating new code written when possible (in this case, it's fairly hard to avoid the existing pattern).

After avoiding the bad patterns, we can write components using functions and react hooks: https://reactjs.org/docs/hooks-overview.html. It's a nice way to make abstraction on state changes (and a lot more!).

Copy link
Member

Choose a reason for hiding this comment

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

@Bobgy this is a great argument! Do you think you could start an issue to document these antipatterns, maybe with a brief proposed initial solution, so we can keep track of them? You know the repository and the codebase better than anyone else. If we can keep our context there and start a discussion, then we will be able to address these one by one

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thank you @Bobgy and @StefanoFioravanzo ! I agree with following one-way data flow approach and we should avoid using Ref as much as we can. I have attempted to change my PR to follow the suggested guide. But I found out that it requires changes beyond just ExperimentDetail.tsx, therefore I cautiously replace the implementation in ExperimentDetail.tsx with the one-way data flow practice, while keeping other files with Ref approach for now. RunList.tsx change affects multiple pages so I leave it unchanged to avoid large PR. We can take it as a first step of migration away from Ref, and gradually refactoring the codebase along the way.

To @StefanoFioravanzo: Good suggestion! I have created #5118 so feel free to make your proposal there. The goal is to document the agreed practices in README file so all contributors can follow along.

Copy link
Contributor

Choose a reason for hiding this comment

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

Awesome, I'll put more there soon

frontend/src/pages/RunListsRouter.tsx Outdated Show resolved Hide resolved
frontend/src/pages/RunListsRouter.tsx Outdated Show resolved Hide resolved
frontend/src/pages/ExperimentDetails.tsx Outdated Show resolved Hide resolved
frontend/src/pages/ExperimentDetails.tsx Outdated Show resolved Hide resolved
@StefanoFioravanzo
Copy link
Member

@zijianjoy Why did you rename AllRunsAndArchive.test.tsx to AllRunsAndArchive.test.jsx.tsx?

@StefanoFioravanzo
Copy link
Member

BTW @zijianjoy This contribution is great! I think @Bobgy made a good pass on the code and I don't have much to add for now.

I would like just to confirm this, design wise: KFP currently treats archival of Experiments and Runs completely independently, correct? I can have an archived Experiments with just active Runs and vice-versa.

If this holds, I would propose to make the state of the Experiment super explicit, in the RunListsRouter page. I know that we have the Archive/Restore button on the top-right, but I think a label Active or Archived besides the Experiment name on the top would help greatly. WDYT?

@Bobgy
Copy link
Contributor

Bobgy commented Feb 5, 2021

To clarify, restoring runs after an experiment is archived should not succeed.

But agree that making it visually distinguishable for experiment state is helpful! That's a good suggestion.

It can be a separate PR or not. You can make the decision

@zijianjoy
Copy link
Collaborator Author

@zijianjoy Why did you rename AllRunsAndArchive.test.tsx to AllRunsAndArchive.test.jsx.tsx?

Actually I am doing the opposite, I don't know why the codebase has such a name AllRunsAndArchive.test.jsx.tsx, and it caused the whole file not being tested at all. I renamed it to AllRunsAndArchive.test.tsx to enable testing.

@zijianjoy
Copy link
Collaborator Author

@StefanoFioravanzo

I would like just to confirm this, design wise: KFP currently treats archival of Experiments and Runs completely independently, correct? I can have an archived Experiments with just active Runs and vice-versa.

@Bobgy

To clarify, restoring runs after an experiment is archived should not succeed.

But agree that making it visually distinguishable for experiment state is helpful! That's a good suggestion.

It can be a separate PR or not. You can make the decision

I have created #5114 to discuss the relationship between Experiment and Runs. Once we made a decision, we can create subsequent PR for the change. Currently I agree that Runs in Archived Experiment cannot be restored, but our backend doesn't enforce it. We can make changes based on the discussion result.

@Bobgy
Copy link
Contributor

Bobgy commented Feb 11, 2021

/lgtm
/approve

Awesome, this is a great first step towards more declarative implementation!

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Bobgy, zijianjoy

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

1 similar comment
@google-oss-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Bobgy, zijianjoy

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

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.

After archiving an experiment, its runs can no longer be observed
5 participants