My first Open Source contribution
Mark Kop
Posted on September 23, 2019
If you've met me in a tech event, you might already know that I'm an active user of Habitica, a habit tracker that applies gamification into your life. It's been helping me to keep myself organized while providing the sensation of playing an MMORPG which is something that I'm very passionate.
My profile was created in 2014, but only in 2016 I've given a try. I've engaged some other friends and it worked pretty well for some time. I even had contributed to Habitica's Portuguese Wiki with translations.
A few months ago I came back to Habitica and today I'm a Front-End Developer, so it shouldn't be hard to contribute with some code.
I've taken this good first issue and shared my progress in this post. Before started I was concerned about the main difficulties being setting up the development environment and working with VueJS (which was very curious since I've learned React)
Add "Firefox Chat Extension" to the Settings > API page #11042
The User Icon > Settings > API page contains a link to the Chrome Chat Extension. There should also be a link to the Firefox Chat Extension, which is at https://addons.mozilla.org/en-US/firefox/addon/habitica-chat-client-v2/
Both extensions do the same thing, the only difference being the browser they run on. Because of this, I think it would be most helpful if the same bullet-point entry was used for both extensions - that should make it obvious that you're not missing out on anything if you install only one of them. The bullet point line could read "Chrome Chat Extension and Firefox Chat Extension" and the paragraph under it could be changed to this:
"The Chat Extension for Habitica adds an intuitive chat box to all of habitica.com. It allows users to chat in the Tavern, their party, and any guilds they are in."
I'll leave this issue open as suggestion-discussion for a few days and then if there's no objections or changes to this approach, I'll change it help wanted. I'll mark it as good first issue since it will be ideal for a new contributor. EDIT: This is on hold while some changes are being made to the extension.
First Steps
In this first part, I simply followed this guide:
Habitica Wiki - Setting Up Habitica Locally on Linux
Since I already had Git, build-essentials, Node, npm and MongoDB installed, these were the commands I've run:
sudo npm install -g mocha
git clone https://github.com/Markkop/habitica.git
cd habitica
git remote add upstream https://github.com/HabitRPG/habitica.git
cp config.json.example config.json
npm install
sudo service mongod start
npm start
npm run client:dev
http://localhost:8080/static/home
Hurray, Habitica is running on my own machine!
The login page was a little bugged without texts, but as instructed clearing the cache fixed it.
Then I created a User and logged in.
Starting to change stuff
By following this guide we create a new git branch
Habitica Wiki - Using Your Local Install to Modify Habitica's Website and API
git fetch upstream
git checkout -b firefox-extension-link
The main goal is to add a link in the Settings page, and we can find it at website/client/components/settings/api.vue
.
This is what we want to change:
li
a(target='_blank' href='https://chrome.google.com/webstore/detail/habitrpg-chat-client/hidkdfgonpoaiannijofifhjidbnilbb') {{ $t('chromeChatExtension') }}
br
| {{ $t('chromeChatExtensionDesc') }}
But what kind of HTML is that? As hinted by <template lang="pug">
, this is the Pug Pre-Processor that takes this code and outputs HTML. The same with SASS and CSS.
Cool, so we only have to change this text and add other link.
But the thing is: all texts are actually variables because internationalization. How to access $t('chromeChatExtension')
or even how to have a single text variable with two links?
A good way out is asking for help in the Blacksmiths Guild, but looking somewhere for a similar situation also works.
By checking this api's webpage we can notice that right above there is this API Token Warning message.
that corresponds to this line in the code
p(v-html='$t("APITokenWarning", { hrefTechAssistanceEmail })')`
And by searching for APITokenWarning
inside the project, we can find how settings.json
declare this kind of variable
"APITokenWarning": "If you need a new API Token (e.g., if you accidentally shared it), email <%= hrefTechAssistanceEmail %> with your User ID and current Token. Once it is reset you will need to re-authorise everything by logging out of the website and mobile app and by providing the new Token to any other Habitica tools that you use.",
Therefore, with <%= hrefTechAssistanceEmail %>
Also, the hrefTechAssistanceEmail's value can be found in the following section
/// api.vue
...
const TECH_ASSISTANCE_EMAIL = "admin@habitica.com";
export default {
data() {
return {
newWebhook: {
url: ""
},
hrefTechAssistanceEmail: `<a href="mailto:${TECH_ASSISTANCE_EMAIL}">${TECH_ASSISTANCE_EMAIL}</a>`,
showApiToken: false
};
}
}, ...
And after some trying out, we find out the correct way to use directly:
{{ $t("APITokenWarning", { hrefTechAssistanceEmail: "myemail@lol.com" }) }}
Actually...
Ok, cool. We could just create some constants with each link and use them as the example above. However, what if someday someone had to change these links? Perhaps changing the text string directly in the settings.json
file would be easier.
Since this approach results in less code, we're going to use it instead.
We then change chromeChatExtension and chromeChatExtensionDesc to the following:
"chatExtension": "<a target='blank' href='https://chrome.google.com/webstore/detail/habitrpg-chat-client/hidkdfgonpoaiannijofifhjidbnilbb'>Chrome Chat Extension</a> and <a target='blank' href='https://addons.mozilla.org/en-US/firefox/addon/habitica-chat-client-v2/'>Firefox Chat Extension</a>",
"chatExtensionDesc": "The Chat Extension for Habitica adds an intuitive chat box to all of habitica.com. It allows users to chat in the Tavern, their party, and any guilds they are in.",
And our extensions list ends up being
ul
li
a(target='_blank' href='https://www.beeminder.com/habitica') {{ $t('beeminder') }}
br
| {{ $t('beeminderDesc') }}
li(v-html="$t('chatExtension')")
br
| {{ $t('chatExtensionDesc') }}
li
a(target='_blank' :href='`https://oldgods.net/habitica/habitrpg_user_data_display.html?uuid=` + user._id') {{ $t('dataTool') }}
br
| {{ $t('dataToolDesc') }}
li(v-html="$t('otherExtensions')")
| {{ $t('otherDesc') }}
The problem
By checking manually, we notice that chatExtensionsDesc isn't being displayed. In fact, otherDesc text isn't appearing, even on live!
After some experimenting, it seems that when tags are being created with attributes such as li(v-html="$t('otherExtensions')")
, their children tags aren't displayed. The solution is changing the child indentation so it appears just below.
(bug with Pug+Vue?)
The final code is
ul
li
a(target='_blank' href='https://www.beeminder.com/habitica') {{ $t('beeminder') }}
br
| {{ $t('beeminderDesc') }}
li(v-html="$t('chatExtension')")
| {{ $t('chatExtensionDesc') }}
li
a(target='_blank' :href='`https://oldgods.net/habitica/habitrpg_user_data_display.html?uuid=` + user._id') {{ $t('dataTool') }}
br
| {{ $t('dataToolDesc') }}
li(v-html="$t('otherExtensions')")
| {{ $t('otherDesc') }}
Conclusion
Before starting the project I thought the main difficult would be setting the project's environment, but instructions were crystal clear and I hadn't any problem.
The interesting part is that I thought it would be very simple to add another link in a single line of text, but faced several possible solutions because of Vue-i18n Plugin's internationalization.
At first the initial approach made more sense, because api.vue
would be the main file where someone would check for if they'd need to change a link.
However, by putting it in the settings.json
links could be changed to different languages as well. And changing the code would be much simpler.
The learnings in this opportunity were having my first hands-on contact with Vue, discovering the existence of HTML's pre-processors such as Pug and creating a Pull Request to a big project already in production.
Add "Firefox Chat Extension" to the Settings > API page #11375
Fixes #11042
Changes
I've added Firefox Chat Extension's link, removed Chrome Chat Extension's description and added a description about the Chat Extension
While working on it, I've also discovered a bug with Pug and/or Vue that whenever using the HTML tag with attribute such as li(v-html="$t('otherExtensions')")
, its children wouldn't be displayed, as you can notice how the text description of "Other Extensions" doesn't appear.
The fix is not putting the text as child by fixing its indentation.
This is the final result:
PS: I've mistakenly changed settings.json
indentation. Is there any problem?
UUID: 40387571-91ee-489e-960f-278bf8fd503a
Posted on September 23, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.