DEV Community

Uday Rana
Uday Rana

Posted on

Jumping Into The Deep End

For my third contribution to open source, I worked on the project ghostfolio, which is an investment portfolio management suite.

GitHub logo ghostfolio / ghostfolio

Open Source Wealth Management Software. Angular + NestJS + Prisma + Nx + TypeScript ๐Ÿค

Ghostfolio logo

Ghostfolio

Open Source Wealth Management Software

Ghostfol.io | Live Demo | Ghostfolio Premium | FAQ | Blog | Slack | X

Shield: Buy me a coffee Shield: Contributions Welcome Shield: Docker Pulls Shield: License: AGPL v3

Ghostfolio is an open source wealth management software built with web technology. The application empowers busy people to keep track of stocks, ETFs or cryptocurrencies and make solid, data-driven investment decisions. The software is designed for personal use in continuous operation.

Preview image of the Ghostfolio video trailer

Ghostfolio Premium

Our official Ghostfolio Premium cloud offering is the easiest way to get started. Due to the time it saves, this will be the best option for most people. Revenue is used to cover the costs of the hosting infrastructure and to fund ongoing development.

If you prefer to run Ghostfolio on your own infrastructure, please find further instructions in the Self-hosting section.

Why Ghostfolio?

Ghostfolio is for you if you are...

  • ๐Ÿ’ผ trading stocks, ETFs or cryptocurrencies on multiple platforms
  • ๐Ÿฆ pursuing a buy & holdโ€ฆ

[Feature] Set up tooltip in treemap chart component #3808

The goal of this issue is to set up a tooltip in the treemap chart component which is based on chart.js.

  • Pass [baseCurrency]="user?.settings?.baseCurrency" to <gf-treemap-chart /> in home-holdings.html
  • The tooltip should display valueInBaseCurrency from holdings if available along with the user's currency (baseCurrency)
  • Try to use getTooltipOptions() for the style

While looking for open issues to work on on GitHub, I came across this one. I'd been wanting to step my game up and work on a feature this time, so I decided this would be a good issue to try and work on. I signed up for it without looking into it too much. I later saw it was an Angular issue, which further piqued my interest because I was curious about learning Angular.

Although I signed up for it, I wasn't able to work on it for a while - school assignments and life got in the way. A week passed, and I decided I should get to work, so I started with reading the contributing docs, and saw they used Docker. I thought "perfect, my other course teaches Docker this week, so I'm set". I forked and cloned the repo and tried installing the dependencies and instantly ran into issues - something to do with peer dependency conflicts. The app wouldn't even start even though I'd followed the instructions. This scared me off of working on it for another week.

When I tried again, I cloned my fork again, and got the app to build this time, but some tests were failing before I'd even begun. I thought to reach out in the project's Slack to ask if it was just on my end, and the maintainer responded saying the build in CI was passing. Once again, I was scared away from working on the project.

Eventually, the maintainer commented on the issue asking for an update. I decided I couldn't put it off any longer and got ready to spend a good while trying to work this out.

I pulled in changes from upstream and cloned my fork again, but the tests were still failing. When starting the app, the server would log a warning saying some imports were failing, so I decided to look into it. The project used a technology for managing the monorepo called Nx, and the issue seemed related, so I spent a while looking into what it did. They also used something called Storybook, which they mentioned how to start in the contributing doc, but didn't bother explaining what it was. I decided to check it out and found out it was for developing components by rendering them in isolation. When I started Storybook up, it wouldn't work either and would give me import errors. I spent a little while trying to debug the import issues, but then realized I could just work on my issue without dealing with them, so I decided to just ignore them and got to work.

It took me a while to figure out what I was even supposed to do and what the scope of the issue was. The original issue was fairly cryptic in hindsight despite being labelled "good first issue". I suppose different projects have different ideas for what makes a good first issue. I started by looking through the files to find the component I was supposed to work on.

I tried looking for the chart component I was supposed to work on in the UI, but it wasn't visible in it's parent component. I left a comment asking the maintainer, but then figured it out right away. I saw some initialization functions in the chart component and it's parent component, so I wrote console.log(this) inside them to see what I was working with, and that's when I realized the chart component wasn't even being rendered. I went digging through the settings in the client and found an experimental features toggle, which I figured out by looking at the HTML template for the component and seeing that it was hidden behind a conditional statement.

After I could actually see the thing I was working on, things became a bit easier. The project used chart.js for their charts, so I went to it's documentation to see how tooltips work. Since they had a helper function specifically for tooltips I thought to myself "Okay, let's see how they use tooltips in other charts in the app". I started looking at some other components that used tooltips and looking at what they had in common with the component I was working on, i.e. how they passed configuration options to the tooltip and such. I noted how they set up the tooltip in the other components and tried to replicate it, and it worked! I had a working tooltip! After two weeks! ...Which still didn't show the right data! But it was progress nevertheless! Suddenly, the issue seemed a lot more doable. Instead of being scared by the massive monorepo I was able to zero in on the exact things I needed to work on, and that was all I needed to worry about.

I struggled a bit more with trying to find out how to pass data to the tooltip. After looking closer at how the component I was copying passed data to the tooltip, I realized it wouldn't work for the one I was working on. It received and processed data in a different way than mine, which I realized when I noticed it was in apps/client/src/app/components/, while my component was in libs/ui/src/lib. I figured a component in a completely different part of the monorepo is probably designed to work differently, so I searched for other components that used tooltips, and luckily, I found one in the same directory as my component.

I initially had to turn off type safety for the parameters of the function I added to configure the tooltip, because the object I was getting the options from had properties I needed to access which weren't defined for it's type. I was going to ask the maintainer about this, but when I found a component that worked closer to mine, I realized I didn't need any parameters at all. Instead of defining parameters, they used the context object automatically passed to the label callback function on the tooltip object, so I did the same thing. Even though I didn't need a parameter anymore, I ran into a problem where other configuration options would become undefined when I tried removing the parameter. At first I wasn't sure what was going on, but it started working after a while, so I guess the compiler was just lagging behind my changes (maybe I forgot to save the file?).

So I was able to get the necessary data into the tooltip, but I still had to format it. I once again looked to the other component to see how they did it. They passed values from the context object to Number.toLocaleString() and the result was rendered in the tooltip, so I did the same thing and it came out looking nice and clean, and so my PR was ready.

Feature/Set up tooltip in treemap chart component #3897

Fixes #3808.

I based my implementation off of the tooltip in portfolio-proportion-chart.component.ts. Please let me know if you'd like any changes.

image

I marked my PR ready for review and got feedback on some formatting changes. Turns out I should use a lot more line breaks in my code because everything was smooshed together, which I only noticed after the maintainer pointed it out.

I made the requested changes but didn't hear back for a couple days which made me nervous. Fortunately the maintainer eventually got back to me and merged the changes.

Even better, the maintainer commented to let me know about a follow-up issue I could work on for adding more data to the tooltip. Since I now knew how the project was set up, knew a little bit more about Angular, and about tooltips in Chart.js, this issue looked a lot easier compared to when the first one. Sure enough, this issue only took me an hour or so, and after a review that one was merged too.

[FEATURE] Extend tooltip in treemap chart component by name #3904

The goal of this issue is to extend the tooltip in the treemap chart component by adding the name (or symbol as a fallback):

return [
  // `${name ?? symbol}`,
  // value or percentage as before
];

Get inspired by the GfPortfolioProportionChartComponent.

Feature/Extend tooltip in treemap chart component by name #3907

Fixes #3904.

This PR adds the name (and symbol as a fallback) to the label for the tooltip in GfTreemapChartComponent.

It should also be possible to display the name/symbol as the tooltip title instead if preferred, but GfPortfolioProportionChartComponent puts them in the label so I decided to keep it consistent.

image

Working on this issue massively boosted my confidence in jumping into unknown code. Although it was incredibly stressful at first, once I focused on what I actually needed to do, I was able to accomplish my task, even though I went in with zero knowledge of Angular, or Nx, or Chart.js.

That's all for this post. I have one more pull request to work on for Hacktoberfest so expect to see another blog post soon!

Top comments (0)