Skip to content

feat: add multi-mode view for Flink Artifacts/UDFs #2313

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

shouples
Copy link
Contributor

@shouples shouples commented Aug 8, 2025

Summary of Changes

Continuation of #2243, but with reusable MultiModeViewProvider and ViewProviderDelegate classes to switch between "Flink Artifacts" and "Flink UDFs" modes in the single confluent-flink-artifacts view.

flink-multi-view.mov

Any additional details or context that should be provided?

  • The current action-toggling behavior works fine for two view modes, but we'll need to explore better UI/UX if a view needs three modes. Cycling through them would be clunky, but a quickpick may feel like overkill.
  • I don't like the FlinkArtifactsUDFs* naming pattern, but can't come up with anything better at the moment without it being too vague

Pull request checklist

Please check if your PR fulfills the following (if applicable):

Tests
  • Added new
  • Updated existing
  • Deleted existing
Other
  • All new disposables (event listeners, views, channels, etc.) collected as for eventual cleanup?
  • Does anything in this PR need to be mentioned in the user-facing CHANGELOG or README?
  • Have you validated this change locally by packaging and installing the extension .vsix file?
    gulp clicktest

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Cerchie what do you think about if we moved the uploadUDF command into here as a more generalized command area for UDFs?

Copy link
Contributor

Choose a reason for hiding this comment

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

that jives with what we have for Flink statements etc... sure!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I want to rename this file to something else, but I'm not sure what. Can be a future branch.

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe flinkUDFs to reflect the final state of the resource? Or flinkArtifactsAndUDFs.... the rest of the files in viewProviders seem to be named after the type of resource you're viewing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the rest of the files in viewProviders seem to be named after the type of resource you're viewing

That's the tricky part here - we're enabling users to view either Artifacts or UDFs, so naming for only one of them doesn't feel quite right. 🤔

}
}

export function triageGetFlinkArtifactsError(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to src/viewProviders/multiViewDelegates/flinkArtifactsDelegate.ts


describe("FlinkArtifactsViewProvider", () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Most of these tests moved to src/viewProviders/multiViewDelegates/flinkArtifactsDelegate.test.ts

@sonarqube-confluent
Copy link

Passed

Analysis Details

6 Issues

  • Bug 0 Bugs
  • Vulnerability 0 Vulnerabilities
  • Code Smell 6 Code Smells

Coverage and Duplications

  • Coverage 84.30% Coverage (69.60% Estimated after merge)
  • Duplications No duplication information (0.80% Estimated after merge)

Project ID: vscode

View in SonarQube

@shouples shouples marked this pull request as ready for review August 18, 2025 13:42
@Copilot Copilot AI review requested due to automatic review settings August 18, 2025 13:42
@shouples shouples requested a review from a team as a code owner August 18, 2025 13:42
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements a multi-mode view provider for Flink artifacts and UDFs, allowing users to switch between viewing Flink artifacts and UDFs within a single tree view. The implementation introduces a reusable architecture for multi-mode view providers that can be applied to other views requiring mode switching.

Key changes:

  • Creates a new MultiModeViewProvider base class for multi-mode tree views
  • Implements delegate pattern with separate FlinkArtifactsDelegate and FlinkUDFsDelegate classes
  • Adds commands and UI elements for switching between artifacts and UDFs modes

Reviewed Changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/viewProviders/baseModels/multiViewBase.ts New base classes for multi-mode view providers and delegates
src/viewProviders/flinkArtifacts.ts Refactored to use multi-mode architecture with FlinkArtifactsUDFsViewProvider
src/viewProviders/multiViewDelegates/flinkArtifactsDelegate.ts Delegate for handling artifacts mode logic and error handling
src/viewProviders/multiViewDelegates/flinkUDFsDelegate.ts Delegate for handling UDFs mode with placeholder implementation
src/commands/flinkArtifacts.ts New command for switching to artifacts mode
src/commands/flinkUDFs.ts New command for switching to UDFs mode
src/models/flinkUDF.ts New model and tree item classes for Flink UDFs
src/emitters.ts Added event emitter for view mode switching
src/context/values.ts Added context value for tracking current view mode
src/extension.ts Updated to register new commands and initialize view mode context
package.json Added command definitions and menu contributions for mode switching

this.environmentId = props.environmentId;
this.id = props.id;
this.name = props.name;
this.description = props.description;
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

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

The constructor assigns props.provider and props.region to the instance properties, but these assignments are missing. The constructor only assigns the first 6 properties but not provider and region.

Suggested change
this.description = props.description;
this.description = props.description;
this.provider = props.provider;
this.region = props.region;

Copilot uses AI. Check for mistakes.

let message = "Failed to load Flink artifacts.";

if (isResponseError(error)) {
const status = error.response.status;
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

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

[nitpick] The variable status is extracted but could be used inline in the switch statement to reduce unnecessary variable declaration.

Suggested change
const status = error.response.status;

Copilot uses AI. Check for mistakes.

.json()
.catch((err) => {
logger.debug("Failed to parse error response as JSON", err);
});
Copy link
Preview

Copilot AI Aug 18, 2025

Choose a reason for hiding this comment

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

The error response JSON parsing is attempted but the result is not used. Consider removing this unused code or storing the result if it's needed for logging.

Suggested change
});

Copilot uses AI. Check for mistakes.

{
"command": "confluent.flink.setUDFsViewMode",
"title": "Switch to Flink UDFs",
"icon": "$(code)",
Copy link
Contributor

Choose a reason for hiding this comment

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

These icons make sense given what we have to work with, but I'm still not feeling that the functionality is obvious. Plus, as you mentioned, there was the idea of cycling through 3 modalities as well. I'll be interested to hear what design has to say

kafkaClusterSelected = "confluent.kafkaClusterSelected",
/** The user clicked a Schema Registry tree item. */
/** The user focused a Schema Registry for the Schemas view. */
Copy link
Contributor

Choose a reason for hiding this comment

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

this is for key-navigation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, these comment changes were just for clarity/accuracy since the event can fire if the "Select Kafka Cluster / Schema Registry" can be triggered from a quickpick as well as clicking on their respective tree items

@@ -407,6 +412,11 @@ async function setupContextValues() {
SCHEMA_URI_SCHEME,
MESSAGE_URI_SCHEME,
]);
// set the initial Flink artifacts view mode to "Artifacts" so the UDF mode toggle is visible
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if there's a way to set it to something like "last resource touched". Like, if the user was looking at a UDF and re-opens the sidebar, they see UDFs. Might be impossible?

Copy link
Contributor

@Cerchie Cerchie left a comment

Choose a reason for hiding this comment

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

Screenshot 2025-08-18 at 7 25 50 AM Screenshot 2025-08-18 at 7 25 44 AM

}

getChildren(element?: T): T[] {
if (!this.currentDelegate) {
Copy link
Contributor

Choose a reason for hiding this comment

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

When could this.currentDelegate ever be undefined?

{
readonly kind = "flinkArtifacts";
loggerName = "viewProviders.flinkArtifacts";
/**
Copy link
Contributor

Choose a reason for hiding this comment

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

Declare a specific type for FlinkArtifact | FlinkUdf ala:

export type ArtifactOrUdf = FlinkArtifact | FlinkUdf

simplifies a few lines.

if (!this.parent.resource) {
return [];
}
return this.parent.filterChildren(element, this.children);
Copy link
Contributor

Choose a reason for hiding this comment

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

Revise this so that ViewProviderDelegate::getChildren() just returns this.children, period, and then have MultiModeViewProvider::getChildren() responsible for making the call to get the current delegate's children, then itself making its own call to its filter.

Less intertwining that way.

super();
}

async fetchChildren(): Promise<FlinkArtifact[]> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps if the base definition of ViewProviderDelegate.fetchChildren() took either the parent as a parameter, or perhaps even more directly whatever the parameterized type for the compute pool is, then would both simplify the constructor calls for the delegates (no longer needing to pass in parent) and also reduce cross-class data member reach-ins.

That is, allows for less tight coupling between the delegator and delegate. The fetchChildren() implementations only need the current computePool, and that can be passed on the stack in the method call, and I think we gots a generic type for it in the mix already.

Bottom line: Revising to get the the delegator/delegatees to not reach into each other's data members at all, as well as to not have circular references is Good Design.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Prototype toggling between UDF and Artifacts in a single view
3 participants