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

Show project description in project list #2386

Closed
fabruex opened this issue Jan 22, 2025 · 26 comments
Closed

Show project description in project list #2386

fabruex opened this issue Jan 22, 2025 · 26 comments
Labels
type: feature New feature or request

Comments

@fabruex
Copy link
Contributor

fabruex commented Jan 22, 2025

Description

It would be nice to be able to display the project description (corresponding to the "description" field in the package.json file) next to the project name, in the workspace project list.

Motivation

In our company we have a folder for a specific category of applications that have a progressive code as their name. In this way it would be possible to immediately understand which application it is.

Suggested Implementation

I would add a parameter like "Show project description in the project list" with the following options:

  • never: never display the description
  • title or hover: show the description only when the mouse hovers over the name
  • side: show the description to the right of the name

Alternate Implementations

It could be made more flexible by directly choosing which fields of the package.json file to display, but I guess it would be more difficult to implement

@fabruex fabruex added the type: feature New feature or request label Jan 22, 2025
@MaxKless
Copy link
Collaborator

Just to check I'm understanding this correctly: You need the project descriptions in order to differentiate your projects at a glance?
Because to me the PDV would be a more natural place to show the description, not the sidebar. That would make things more noisy.

@fabruex
Copy link
Contributor Author

fabruex commented Jan 22, 2025

Thanks for your reply. This is an example of what we have inside the apps/testapps folder

Image

In the real case we have a lot of this projects and we would like to see the description directly in the list, maybe with a lighter font, and only optionally.

I agree that PDV would be a more natural place, but we should click on each project to see its description.

@MaxKless
Copy link
Collaborator

I see what you mean now. Honestly, I think this is quite a niche use-case and I don't think it's a good idea to increase the complexity & configuration surface area of nx console for this.
However, I do want to support you and your use case. There is a feature of Nx Console called "Nx Console Plugins" that allows people to write code in their repo to modify how nx console works. Currently, it only applies to the generate ui, but I've been meaning to expand it to also be able to modify the project view.
If you would be open to collaborate and help implement this, I will gladly support you and we'll create something that allows you to tweak this display exactly to your use case.

@fabruex
Copy link
Contributor Author

fabruex commented Jan 22, 2025

Thanks, It sounds interesting. Will this allow us to modify only the PDV or also the list of projects?
However, I probably won't have much time to spend on it, but if you tell me what to do and how to start I can try to take a look at it in my spare time.

@MaxKless
Copy link
Collaborator

MaxKless commented Jan 22, 2025

This would allow you to modify the list of projects. No worries if you don't have much time to spend on it. I might do it when I find the time for it but no idea when that will be.
You can look at

where we load nx console plugins from the file system.
We would need a new type of plugin called ProjectsViewProcessor or the like.

Then, when constructing the project tree, we'd have to load that plugin and pass our workspace data through it before rendering, somewhere here:

private workspaceData: NxWorkspace | undefined = undefined;

It's not trivial but definitely doable :) Let me know if you start working on it or have any further questions

@fabruex
Copy link
Contributor Author

fabruex commented Jan 23, 2025

I took a look and I think I have a pretty clear idea of how it all works. I was thinking about something like this:

add the ProjectsViewProcessor to the plugin interface, maybe with an option (this is for my case) listItemMapper, that would be a function that receives the single tree view item and return the edited item (in my case with the description property from the package.json file), and that would be called before returning items from the getChildren method, somewhere here:

return items.map((item) => new NxTreeItem(item));

I guess we would also need to add the following line here:

this.description = item.description

I think it should work even if item.description is undefined, but maybe I'm wrong.

My only question is how to pass the workspacePath parameter to the loadPlugins function within NxProjectTreeProvider class.

I don't know if there are some edge cases that I didn't consider, and, above all, I don't know if this will be too much "customized" for our case 😄. Let me know.

@MaxKless
Copy link
Collaborator

no I think this makes sense. You can look at the TreeItem interface and let the plugins override other properties than the description as well.
If the plugin is loaded, I would pass it both the tree item and the workspaceData so that we can make decisions based on global things too.
I think this is a good start. In the future I would like to be able to control other parts as well like hiding nodes and sorting but it doesn't have to be now.

@fabruex
Copy link
Contributor Author

fabruex commented Jan 23, 2025

So, if you agree, in the coming days I can try to fork the project and then create a pull request.

Can you help me understand this better:

If the plugin is loaded, I would pass it both the tree item and the workspaceData so that we can make decisions based on global things too.

And, what about this:

My only question is how to pass the workspacePath parameter to the loadPlugins function within NxProjectTreeProvider class.

Last thing: how can I test it on my local Nx workspace?

Thanks

@MaxKless
Copy link
Collaborator

If the plugin is loaded, I would pass it both the tree item and the workspaceData so that we can make decisions based on global things too.

As you can see below, the plugins are all functions that take something and return a result.

export type SchemaProcessor = (
schema: GeneratorSchema,
workspace: NxWorkspace,
lspLogger: Logger
) => GeneratorSchema;

I'm saying that the function signature for the new plugin should be something like

export type ProjectViewItemProcessor = (
  schema: NxTreeItem,
  workspace: NxWorkspace
) => NxTreeItem;

My only question is how to pass the workspacePath parameter to the loadPlugins function within NxProjectTreeProvider class.

You can simply use import { getNxWorkspacePath } from '@nx-console/vscode-configuration';

Last thing: how can I test it on my local Nx workspace?

Check out CONTRIBUTING.md even though it's a bit outdated.
Basically you want to:

  • run yarn
  • run npx nx run vscode:build:debug (<- this generates source maps so you can set breakpoints)
  • press F5 or click Launch Extension in the debug view

@fabruex
Copy link
Contributor Author

fabruex commented Jan 26, 2025

So, I made a first try, you can see it here:

master...fabruex:nx-console:projectViewItemProcessors

but I have some doubt/issue.

  1. how to import the NxTreeItem class for the plugin type definition
  2. how to import the loadPlugins function (I got the error in the comment above the line)
  3. where to exactly run the loadPlugins function (now I added it within the getChildren function so I can use the await attribute) but probably it can be done in a better way

@MaxKless
Copy link
Collaborator

MaxKless commented Feb 3, 2025

  1. I would recommend creating your own interface instead of using NxTreeItem. So something like export type ProjectViewItem = { description?: string, tooltip?: string }. We will want to implement this in IntelliJ as well in the future so having it coupled to a vscode implementation isn't a great idea. In this case you would have to apply the values from the new ProjectViewItem object to the NxTreeItem manually in getChildren. It shouldn't be a problem though.
  2. You should move the loadPlugins to the shared-nx-console-plugins lib because you can import it from there in both the language server and vscode
  3. I think the way you run the loadPlugins function right now is good :) You should make sure that it's reset to undefined on refresh just like the workspace data is.

@MaxKless
Copy link
Collaborator

MaxKless commented Feb 3, 2025

Great job so far though!

@fabruex
Copy link
Contributor Author

fabruex commented Feb 3, 2025

Thanks! So... I followed your directions:

master...fabruex:nx-console:projectViewItemProcessors

I think now it could work, but I'm not able to test it. When I run it with F5 I don't see anything in the new VSCode window, probably I'm doing something wrong, but I don't know what :)

You should make sure that it's reset to undefined on refresh just like the workspace data is

I don't understand this part. Do you mean this?

Image

I defined the description property as string | boolean to avoid TS errors, but f I add tooltip?: string I get the error in the comment above the line

Image

@MaxKless
Copy link
Collaborator

MaxKless commented Feb 4, 2025

Awesome!
You have to run the build first before running the extension development host. Just run nx run vscode:build:debug and check that something is created in dist/apps/vscode. Then press F5 or use the Launch Extension button

Image

You should make sure that it's reset to undefined on refresh just like the workspace data is

I mean this: You should make sure that whenever the projects view is refreshed (so it is rendered again from the root, so getChildren is called with undefined), you reload the plugins.
So this.plugins = await loadPlugins(getNxWorkspacePath()); should be moved right to where this.workspaceData = await getNxWorkspace(); is called.

I defined the description property as string | boolean to avoid TS errors, but f I add tooltip?: string I get the error in the comment above the line

Ah I see the problem, ProjectViewItem already exists as a class. So maybe name it something else. Then you can get the plugin results and apply them individually to the rendered NxTreeItem.

I can take over soon as well and put the last pieces together if it's not working :)

@fabruex
Copy link
Contributor Author

fabruex commented Feb 4, 2025

I finally made the debug work, now I have the following problem.

With this path:

Image

I get the error below during the import (existsSync works fine):

Image

Only URLs with a scheme in: file, data, node, and electron are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'

@MaxKless
Copy link
Collaborator

MaxKless commented Feb 5, 2025

maybe try to join the path together instead of using /? That should be more resilient across OSes

@fabruex
Copy link
Contributor Author

fabruex commented Feb 5, 2025

Looks like we did it :)

master...fabruex:nx-console:projectViewItemProcessors

It works fine, but I noticed that in this way the item processor runs for every type of item (projects, targets, etc.). Should we make it run only at project level? That's up to you

Ah I see the problem, ProjectViewItem already exists as a class. So maybe name it something else. Then you can get the plugin results and apply them individually to the rendered NxTreeItem.

Btw, this error is still there, even If I change the name (the same for tooltip). Should I assign those properties individually instead of Object.assign?

Image

@MaxKless
Copy link
Collaborator

MaxKless commented Feb 6, 2025

Nice!! I think it should run for every type of item.

Let's assign those properties individually for now. We can say description, tooltip, label, icon,...? Anything else?
This way we are in control and these are common properties that will exist in JetBrains as well.

So something like

const processed = processor(item, this.workspaceData);

if(processed.description) {
  item.description = processed.description
}

@fabruex
Copy link
Contributor Author

fabruex commented Feb 6, 2025

We can say description, tooltip, label, icon,...? Anything else?

I guess icon will be iconPath, as i see in the setIcons method, right?
I think that's all, later I will add them.

What next? Should I create a pull request or something else?

@MaxKless
Copy link
Collaborator

MaxKless commented Feb 6, 2025

Yeah that sounds right. Create a pull request and I'll go through it and try things out :)
Thank you so much for the contribution, what a pleasure!

@fabruex
Copy link
Contributor Author

fabruex commented Feb 6, 2025

So something like

const processed = processor(item, this.workspaceData);

if(processed.description) {
item.description = processed.description
}

Uhm, sorry, still some issue with that part :)

I can't assign item as first parameter to processor until types are different.

item type is NxTreeItem class but processor requires ProjectViewTreeItem which doesn't allow boolean for description and no MarkdownString for tooltip. The problem is before assign those properties individually.

I'm no expert in Typescript and maybe I'm missing something

@MaxKless
Copy link
Collaborator

MaxKless commented Feb 7, 2025

Make a PR and I'll have a look :) Maybe I can figure it out.

@fabruex
Copy link
Contributor Author

fabruex commented Feb 8, 2025

Done, I also changed a little bit the setIcons method to handle the custom iconPath.
I hope it's okay :)

@fabruex
Copy link
Contributor Author

fabruex commented Mar 12, 2025

Hi Max, I add this question here, if you think it can be doable I will move it to a new feature request.

Currently we use the Projects view just to run dev, build and lint scripts, nothing else, so it would be nice to have one of these changes (using the new plugin or not, that's up to you):

  1. the ability to customize the icons that appear when the mouse is over the project name. In our case there would be three icons, one for each script (this would be the best solution for us)

  2. Or alternately, when clicking on a project, just immediately show the available scripts without have to click again on "NPM Scripts"

I took a look at the code and I guess the first one is more difficult (or maybe impossible) to do. I saw that icons and commands are defined in the package.json file, I don't know if it can be done in another way.

Thanks

@MaxKless
Copy link
Collaborator

  1. there is no handler for hover so you're right, tricky to do.
  2. should be possible, you can extend the plugin you wrote to also include the expansion state. Then, when processing the plugin, simply read from the expansion state and apply it to the NxTreeItem

@MaxKless
Copy link
Collaborator

Feel free to make another PR, should be easier this time around :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants