For Codegeist 2022 we built a new Custom UI Jira app from scratch. It is called Project Milestones for Jira. This time we didn’t have an app to migrate from server to cloud where the concept was already defined. We decided to do something new with a part of Forge we didn’t use before for the Jira apps building.
The project milestones app adds a project page to each project in Jira where users can split up their project into smaller pieces called milestones. Imagine you have a large project running for several years. Of course, you can summarize issues in epics and plan stories in sprints. But sprints usually have a length of two weeks. What about the long-term goals and steps that needed to be achieved during the project? They can be planned with the project milestones app.
The project page module in Forge was something new to us. We started with a blank page we had to fill with content. Furthermore, it is the first app where we don’t take content from Jira and modify it (like with Epic Clone), but we create our own Jira app content and store it in a project.
For that purpose, we used the Forge Properties API. Beside the project page we also add an issue panel which can display information from the project milestones in a Jira issue. That means that with this Jira app we have two Forge modules in one app for the first time.
UI implementation of Jira app
When looking at the front-end implementation of the Jira app, the most challenging part was to fill the blank page with content. We realized early on that just adding some information to the page makes it more confusing. We had to use custom styles to arrange the list of milestones appropriately. For that purpose, we used styled div and span elements loaded from a styles file where they are defined. What was new to us was that we are able to pass attributes to the styled components which change their appearance.
For example, we added the information if a milestone is complete or not to the styled components and when it is completed, it is displayed with a green background. If not completed, the background is white.
The scrolling behavior on both project page and in the issue panel was a challenge. With wrong settings, the buttons on a modal dialog suddenly moved outside of the dialog or content flowed over the borders of the page. It was tricky to find the right settings but finally we managed it for project page and modal dialogs. However, for issue view we are still not completely satisfied with the scrolling behavior. We are trying to find a way to show a select list that can be displayed also partly outside the panel borders.
For the issue view, it was a challenge to make editing possible and look good directly on the issue panel. At first, we tried to implement modal dialogs as we did it for editing on the project page. However, as we selected a small size for the panel, the dialog finally only displayed within that panel, so it wasn’t visible at all.
After searching in the community and looking into the documentation, we decided to do something else. Displaying a modal dialog from an issue panel but in front of the entire issue seemed to be too complicated. We now display the milestone select field directly on the issue panel so users can make changes directly there without a modal dialog that pops up.
Front-end implementation of the Jira app
As mentioned above, we needed two Forge modules in one Jira app, which was something new. At first, we tried to implement it by adding another static resource folder and linking it in the manifest to the issue panel module. However, this didn’t work as we got error messages saying that, for instance, certain hooks are already in use and can’t be used twice.
The display of the issue panel worked fine, but as soon as we wanted to implement a button that changes a variable via a useState hook, the error appears, and it didn’t work as expected. Looking into the community helped to find a solution here. We use the following code on top level in our App.js file to distinguish between context. When we are in the project page context, the project page code is loaded, whereas when we are on issue level, the issue view code is loaded.
Again, the community helped in this case. We weren’t the first developers with this problem.
The properties API was also something new to us we didn’t use before. We chose it instead of the storage API as we remain in the project level and don’t need to store information on top of that or information that needs to be shared across projects.
The properties API seems to be the right solution for it. We used the example app as a blueprint as it is using the same API for storage and modified the code, so it fits to our purpose. It was great that we were quite flexible in how the data we store is formatted and that we could tailor it as we need it. When you define for your app individually how data is stored, there is no surprise on what you get when you read this data on a different location (e.g. in issue view). We were able to reuse code from the project level on issue view as it was the same data we read from the storage.
Compared to Epic Clone, the focus for the project milestones Jira app was on the front-end. The back-end part was new to us, but it wasn’t as complex as it was for other apps we have built.
We hope you found this series about Forge app development helpful. Reach out to me with any questions or feedback: email@example.com.