diff --git a/website/client/src/components/auth/registerLoginReset.vue b/website/client/src/components/auth/registerLoginReset.vue
index 820933b101..d15dc690cd 100644
--- a/website/client/src/components/auth/registerLoginReset.vue
+++ b/website/client/src/components/auth/registerLoginReset.vue
@@ -745,6 +745,7 @@ export default {
watch: {
$route: {
handler () {
+ this.setTitle();
if (this.resetPasswordSetNewOne) {
const { query } = this.$route;
const { code } = query;
@@ -760,7 +761,6 @@ export default {
this.$router.push({ name: 'login' });
return;
}
-
this.resetPasswordSetNewOneData.code = query.code;
this.resetPasswordSetNewOneData.hasError = hasError;
}
@@ -898,6 +898,18 @@ export default {
window.location.href = redirectTo;
}
},
+ setTitle () {
+ if (this.resetPasswordSetNewOne) {
+ return;
+ }
+ let title = 'login';
+ if (this.registering) {
+ title = 'register';
+ }
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t(title),
+ });
+ },
handleSubmit () {
if (this.registering) {
this.register();
diff --git a/website/client/src/components/challenges/challengeDetail.vue b/website/client/src/components/challenges/challengeDetail.vue
index 3a6addfeea..023db6c5cf 100644
--- a/website/client/src/components/challenges/challengeDetail.vue
+++ b/website/client/src/components/challenges/challengeDetail.vue
@@ -384,6 +384,16 @@ export default {
memberResults: [],
};
},
+ watch: {
+ 'challenge.name': {
+ handler (newVal) {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('challenge'),
+ subSection: newVal.name,
+ });
+ },
+ },
+ },
computed: {
...mapState({ user: 'user.data' }),
isMember () {
@@ -433,6 +443,10 @@ export default {
this.$router.push('/challenges/findChallenges');
return;
}
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.challenge.name,
+ section: this.$t('challenges'),
+ });
const tasks = await this.$store.dispatch('tasks:getChallengeTasks', { challengeId: this.searchId });
this.tasksByType = {
habit: [],
diff --git a/website/client/src/components/challenges/findChallenges.vue b/website/client/src/components/challenges/findChallenges.vue
index 7c4342af78..620d788122 100644
--- a/website/client/src/components/challenges/findChallenges.vue
+++ b/website/client/src/components/challenges/findChallenges.vue
@@ -175,6 +175,10 @@ export default {
},
},
mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('findChallenges'),
+ section: this.$t('challenges'),
+ });
this.loadChallenges();
},
methods: {
diff --git a/website/client/src/components/challenges/myChallenges.vue b/website/client/src/components/challenges/myChallenges.vue
index 986d491574..34d3e66817 100644
--- a/website/client/src/components/challenges/myChallenges.vue
+++ b/website/client/src/components/challenges/myChallenges.vue
@@ -218,6 +218,10 @@ export default {
},
},
mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('myChallenges'),
+ section: this.$t('challenges'),
+ });
this.loadChallenges();
},
methods: {
diff --git a/website/client/src/components/group-plans/taskInformation.vue b/website/client/src/components/group-plans/taskInformation.vue
index 85af3d7a2f..98cf8035cd 100644
--- a/website/client/src/components/group-plans/taskInformation.vue
+++ b/website/client/src/components/group-plans/taskInformation.vue
@@ -224,7 +224,10 @@ export default {
this.group = await this.$store.dispatch('guilds:getGroup', {
groupId: this.searchId,
});
-
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.group.name,
+ section: this.$t('group'),
+ });
const members = await this.$store.dispatch('members:getGroupMembers', { groupId: this.searchId });
this.group.members = members;
diff --git a/website/client/src/components/groups/discovery.vue b/website/client/src/components/groups/discovery.vue
index 909453acf9..2a82b9c17a 100644
--- a/website/client/src/components/groups/discovery.vue
+++ b/website/client/src/components/groups/discovery.vue
@@ -155,6 +155,12 @@ export default {
return this.guilds.filter(guild => filterGuild(guild, filters, search, user));
},
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('guildsDiscovery'),
+ section: this.$t('guilds'),
+ });
+ },
methods: {
async updateSearch (eventData) {
// this.search = eventData.searchTerm; @TODO: Probably don't need this anymore
diff --git a/website/client/src/components/groups/group.vue b/website/client/src/components/groups/group.vue
index 5f8d46adbb..ae64637e20 100644
--- a/website/client/src/components/groups/group.vue
+++ b/website/client/src/components/groups/group.vue
@@ -500,7 +500,10 @@ export default {
if (this.isParty) this.searchId = 'party';
if (!this.searchId) this.searchId = this.groupId;
await this.fetchGuild();
-
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('groupPlans'),
+ subSection: this.group.name,
+ });
this.$root.$on('updatedGroup', this.onGroupUpdate);
},
beforeDestroy () {
@@ -508,7 +511,6 @@ export default {
},
beforeRouteUpdate (to, from, next) {
this.$set(this, 'searchId', to.params.groupId);
-
next();
},
methods: {
@@ -518,6 +520,10 @@ export default {
onGroupUpdate (group) {
const updatedGroup = extend(this.group, group);
this.$set(this.group, updatedGroup);
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('groupPlans'),
+ subSection: group.name,
+ });
},
/**
diff --git a/website/client/src/components/groups/groupPlan.vue b/website/client/src/components/groups/groupPlan.vue
index ace068724b..e90a61514f 100644
--- a/website/client/src/components/groups/groupPlan.vue
+++ b/website/client/src/components/groups/groupPlan.vue
@@ -486,6 +486,9 @@ export default {
},
mounted () {
this.activePage = this.PAGES.BENEFITS;
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('groupPlans'),
+ });
},
methods: {
launchModal () {
diff --git a/website/client/src/components/groups/myGuilds.vue b/website/client/src/components/groups/myGuilds.vue
index 1934bffaf8..a60cd6ab60 100644
--- a/website/client/src/components/groups/myGuilds.vue
+++ b/website/client/src/components/groups/myGuilds.vue
@@ -165,6 +165,12 @@ export default {
});
},
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('myGuilds'),
+ section: this.$t('guilds'),
+ });
+ },
created () {
this.fetchGuilds();
},
diff --git a/website/client/src/components/groups/tavern.vue b/website/client/src/components/groups/tavern.vue
index 26a7adaec3..8d00006a54 100644
--- a/website/client/src/components/groups/tavern.vue
+++ b/website/client/src/components/groups/tavern.vue
@@ -843,6 +843,10 @@ export default {
},
},
async mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('tavern'),
+ section: this.$t('guilds'),
+ });
this.group = await this.$store.dispatch('guilds:getGroup', { groupId: TAVERN_ID });
},
methods: {
diff --git a/website/client/src/components/inventory/equipment/index.vue b/website/client/src/components/inventory/equipment/index.vue
index 0be161765f..a22db13257 100644
--- a/website/client/src/components/inventory/equipment/index.vue
+++ b/website/client/src/components/inventory/equipment/index.vue
@@ -508,6 +508,11 @@ export default {
this.costumeMode = getLocalSetting(
CONSTANTS.keyConstants.CURRENT_EQUIPMENT_DRAWER_TAB,
) === CONSTANTS.equipmentDrawerTabValues.COSTUME_TAB;
+
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('equipment'),
+ section: this.$t('inventory'),
+ });
},
methods: {
selectDrawerTab (tabName) {
diff --git a/website/client/src/components/inventory/items/index.vue b/website/client/src/components/inventory/items/index.vue
index 35ff9a1633..5157d0e76b 100644
--- a/website/client/src/components/inventory/items/index.vue
+++ b/website/client/src/components/inventory/items/index.vue
@@ -491,6 +491,12 @@ export default {
return this.groups.some(g => g.selected);
},
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('items'),
+ section: this.$t('inventory'),
+ });
+ },
watch: {
searchText: throttle(function throttleSearch () {
this.searchTextThrottled = this.searchText.toLowerCase();
diff --git a/website/client/src/components/inventory/stable/index.vue b/website/client/src/components/inventory/stable/index.vue
index d0415b9f78..f6e3e85a5a 100644
--- a/website/client/src/components/inventory/stable/index.vue
+++ b/website/client/src/components/inventory/stable/index.vue
@@ -645,6 +645,12 @@ export default {
return Object.values(this.viewOptions).some(g => g.selected);
},
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('stable'),
+ section: this.$t('inventory'),
+ });
+ },
watch: {
searchText: _throttle(function throttleSearch () {
const search = this.searchText.toLowerCase();
diff --git a/website/client/src/components/settings/api.vue b/website/client/src/components/settings/api.vue
index e47c278ba5..f361096f6b 100644
--- a/website/client/src/components/settings/api.vue
+++ b/website/client/src/components/settings/api.vue
@@ -154,6 +154,10 @@ export default {
},
},
mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('settings'),
+ subSection: this.$t('API'),
+ });
window.addEventListener('message', this.receiveMessage, false);
},
destroy () {
diff --git a/website/client/src/components/settings/dataExport.vue b/website/client/src/components/settings/dataExport.vue
index e80987b893..b439483cf5 100644
--- a/website/client/src/components/settings/dataExport.vue
+++ b/website/client/src/components/settings/dataExport.vue
@@ -13,3 +13,14 @@
+
+
diff --git a/website/client/src/components/settings/notifications.vue b/website/client/src/components/settings/notifications.vue
index 1d1caf25e5..057aeb9dd8 100644
--- a/website/client/src/components/settings/notifications.vue
+++ b/website/client/src/components/settings/notifications.vue
@@ -105,6 +105,10 @@ export default {
...mapState({ user: 'user.data' }),
},
async mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('settings'),
+ subSection: this.$t('notifications'),
+ });
// If ?unsubFrom param is passed with valid email type,
// automatically unsubscribe users from that email and
// show an alert
diff --git a/website/client/src/components/settings/promoCode.vue b/website/client/src/components/settings/promoCode.vue
index 71bbea8c75..02fce4732a 100644
--- a/website/client/src/components/settings/promoCode.vue
+++ b/website/client/src/components/settings/promoCode.vue
@@ -87,6 +87,12 @@ export default {
return '/api/v4/coupons';
},
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('settings'),
+ subSection: this.$t('promoCode'),
+ });
+ },
methods: {
generateCodes () {
// $http.post(ApiUrl.get() + '/api/v2/coupons/generate/
diff --git a/website/client/src/components/settings/site.vue b/website/client/src/components/settings/site.vue
index dcc984dee0..d29cef0fb2 100644
--- a/website/client/src/components/settings/site.vue
+++ b/website/client/src/components/settings/site.vue
@@ -678,6 +678,11 @@ export default {
this.emailUpdates.newEmail = this.user.auth.local.email || null;
this.localAuth.username = this.user.auth.local.username || null;
this.soundIndex = 0;
+
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('settings'),
+ });
+
hello.init({
facebook: process.env.FACEBOOK_KEY, // eslint-disable-line no-process-env
google: process.env.GOOGLE_CLIENT_ID, // eslint-disable-line no-process-env
diff --git a/website/client/src/components/settings/subscription.vue b/website/client/src/components/settings/subscription.vue
index 5ba3ffbfb5..334a45b6cf 100644
--- a/website/client/src/components/settings/subscription.vue
+++ b/website/client/src/components/settings/subscription.vue
@@ -720,6 +720,12 @@ export default {
return moment(this.user.purchased.plan.dateTerminated).format('MM/DD/YYYY');
},
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('settings'),
+ subSection: this.$t('subscription'),
+ });
+ },
methods: {
async applyCoupon (coupon) {
const response = await axios.post(`/api/v4/coupons/validate/${coupon}`);
diff --git a/website/client/src/components/shops/market/index.vue b/website/client/src/components/shops/market/index.vue
index 9d9bbed3c6..0dfe675f4b 100644
--- a/website/client/src/components/shops/market/index.vue
+++ b/website/client/src/components/shops/market/index.vue
@@ -304,6 +304,10 @@ export default {
}, 250),
},
async mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('market'),
+ section: this.$t('shops'),
+ });
await this.$store.dispatch('worldState:getWorldState');
},
methods: {
diff --git a/website/client/src/components/shops/quests/index.vue b/website/client/src/components/shops/quests/index.vue
index fad01ef6ae..8f22454c57 100644
--- a/website/client/src/components/shops/quests/index.vue
+++ b/website/client/src/components/shops/quests/index.vue
@@ -544,6 +544,10 @@ export default {
}, 250),
},
async mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('quests'),
+ section: this.$t('shops'),
+ });
await this.$store.dispatch('worldState:getWorldState');
},
methods: {
diff --git a/website/client/src/components/shops/seasonal/index.vue b/website/client/src/components/shops/seasonal/index.vue
index 948420713d..95d3008f92 100644
--- a/website/client/src/components/shops/seasonal/index.vue
+++ b/website/client/src/components/shops/seasonal/index.vue
@@ -517,6 +517,11 @@ export default {
}, 250),
},
async mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('seasonalShop'),
+ section: this.$t('shops'),
+ });
+
this.$root.$on('buyModal::boughtItem', () => {
this.backgroundUpdate = new Date();
});
diff --git a/website/client/src/components/shops/timeTravelers/index.vue b/website/client/src/components/shops/timeTravelers/index.vue
index 6bb70047f6..8976f15581 100644
--- a/website/client/src/components/shops/timeTravelers/index.vue
+++ b/website/client/src/components/shops/timeTravelers/index.vue
@@ -399,6 +399,10 @@ export default {
}, 250),
},
mounted () {
+ this.$store.dispatch('common:setTitle', {
+ subSection: this.$t('timeTravelers'),
+ section: this.$t('shops'),
+ });
this.$root.$on('buyModal::boughtItem', () => {
this.backgroundUpdate = new Date();
});
diff --git a/website/client/src/components/static/contact.vue b/website/client/src/components/static/contact.vue
index d10973d024..188e5e27f1 100644
--- a/website/client/src/components/static/contact.vue
+++ b/website/client/src/components/static/contact.vue
@@ -67,5 +67,10 @@ export default {
goToModForm(this.user);
},
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('contactUs'),
+ });
+ },
};
diff --git a/website/client/src/components/static/faq.vue b/website/client/src/components/static/faq.vue
index b8af7f25d1..501e917b01 100644
--- a/website/client/src/components/static/faq.vue
+++ b/website/client/src/components/static/faq.vue
@@ -112,6 +112,12 @@ export default {
// "webFaqStillNeedHelp": "If you have a question that isn't on this list or on the [Wiki FAQ](http://habitica.fandom.com/wiki/FAQ), come ask in the <%= linkStart %>Habitica Help guild<%= linkEnd %>! We're happy to help."
};
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('help'),
+ subSection: this.$t('faq'),
+ });
+ },
methods: {
isVisible (heading) {
return this.visible && this.visible === heading;
diff --git a/website/client/src/components/static/features.vue b/website/client/src/components/static/features.vue
index 706ae64305..747051fb6b 100644
--- a/website/client/src/components/static/features.vue
+++ b/website/client/src/components/static/features.vue
@@ -137,6 +137,11 @@ export default {
directives: {
markdown: markdownDirective,
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('features'),
+ });
+ },
methods: {
playButtonClick () {
this.$router.push('/register');
diff --git a/website/client/src/components/static/groupPlans.vue b/website/client/src/components/static/groupPlans.vue
index e2011defe7..08ad15317e 100644
--- a/website/client/src/components/static/groupPlans.vue
+++ b/website/client/src/components/static/groupPlans.vue
@@ -274,6 +274,9 @@ export default {
// Load external scripts after the app has been rendered
setupPayments();
});
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('groupPlans'),
+ });
},
methods: {
goToNewGroupPage () {
diff --git a/website/client/src/components/static/home.vue b/website/client/src/components/static/home.vue
index 9f62600332..9c11bd6175 100644
--- a/website/client/src/components/static/home.vue
+++ b/website/client/src/components/static/home.vue
@@ -909,6 +909,9 @@ export default {
// windows: WINDOWS_CLIENT_ID,
google: process.env.GOOGLE_CLIENT_ID, // eslint-disable-line
});
+ this.$store.dispatch('common:setTitle', {
+ fullTitle: 'Habitica - Gamify Your Life',
+ });
},
methods: {
// eslint-disable-next-line func-names
diff --git a/website/client/src/components/static/pressKit.vue b/website/client/src/components/static/pressKit.vue
index 47c5a071da..74c7645b75 100644
--- a/website/client/src/components/static/pressKit.vue
+++ b/website/client/src/components/static/pressKit.vue
@@ -172,5 +172,10 @@ export default {
],
});
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('presskit'),
+ });
+ },
};
diff --git a/website/client/src/components/tasks/user.vue b/website/client/src/components/tasks/user.vue
index 97c252b2f6..30669ea80d 100644
--- a/website/client/src/components/tasks/user.vue
+++ b/website/client/src/components/tasks/user.vue
@@ -491,6 +491,11 @@ export default {
return tagsByType;
},
},
+ mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('tasks'),
+ });
+ },
watch: {
searchText: throttle(function throttleSearch () {
this.searchTextThrottled = this.searchText.toLowerCase();
diff --git a/website/client/src/components/userMenu/profile.vue b/website/client/src/components/userMenu/profile.vue
index b1ebb40271..667b2effd8 100644
--- a/website/client/src/components/userMenu/profile.vue
+++ b/website/client/src/components/userMenu/profile.vue
@@ -893,6 +893,10 @@ export default {
selectPage (page) {
this.selectedPage = page || 'profile';
window.history.replaceState(null, null, '');
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('user'),
+ subSection: this.$t(this.startingPage),
+ });
},
getProgressDisplay () {
// let currentLoginDay = Content.loginIncentives[this.user.loginIncentives];
diff --git a/website/client/src/pages/private-messages.vue b/website/client/src/pages/private-messages.vue
index 7194b114ae..f2f87d2a2b 100644
--- a/website/client/src/pages/private-messages.vue
+++ b/website/client/src/pages/private-messages.vue
@@ -781,6 +781,9 @@ export default {
},
},
async mounted () {
+ this.$store.dispatch('common:setTitle', {
+ section: this.$t('messages'),
+ });
// notification click to refresh
this.$root.$on(EVENTS.PM_REFRESH, async () => {
await this.reload();
diff --git a/website/client/src/router/index.js b/website/client/src/router/index.js
index 0f95cd54fd..9db7348ec7 100644
--- a/website/client/src/router/index.js
+++ b/website/client/src/router/index.js
@@ -107,6 +107,8 @@ const router = new VueRouter({
return { x: 0, y: 0 };
},
// requiresLogin is true by default, isStatic false
+ // NOTE: when adding a new route entry make sure to implement the `common:setTitle` action
+ // in the route component to set a specific subtitle for the page.
routes: [
{
name: 'register', path: '/register', component: RegisterLoginReset, meta: { requiresLogin: false },
diff --git a/website/client/src/store/actions/common.js b/website/client/src/store/actions/common.js
index 394f48c51b..a19a0cc488 100644
--- a/website/client/src/store/actions/common.js
+++ b/website/client/src/store/actions/common.js
@@ -23,6 +23,16 @@ export function hatch (store, params) {
// .catch((err) => console.error('equip', err));
}
+export function setTitle (store, params) {
+ if (params.subSection && params.section) {
+ store.state.title = `${params.subSection} | ${params.section} | Habitica`;
+ } else if (params.section) {
+ store.state.title = `${params.section} | Habitica`;
+ } else if (params.fullTitle) {
+ store.state.title = params.fullTitle;
+ }
+}
+
export async function feed (store, params) {
const user = store.state.user.data;
feedOp(user, { params });
diff --git a/website/common/locales/en/front.json b/website/common/locales/en/front.json
index 8c2e0511b1..2d01e32560 100644
--- a/website/common/locales/en/front.json
+++ b/website/common/locales/en/front.json
@@ -15,7 +15,6 @@
"emailNewPass": "Email a Password Reset Link",
"forgotPasswordSteps": "Enter the email address you used to register your Habitica account.",
"sendLink": "Send Link",
- "featuredIn": "Featured in",
"footerDevs": "Developers",
"footerCommunity": "Community",
"footerCompany": "Company",
diff --git a/website/common/locales/en/groups.json b/website/common/locales/en/groups.json
index f84bbda756..84e8c1451b 100644
--- a/website/common/locales/en/groups.json
+++ b/website/common/locales/en/groups.json
@@ -48,6 +48,7 @@
"memberList": "Member List",
"invited": "Invited",
"name": "Name",
+ "features": "Features",
"description": "Description",
"public": "Public",
"inviteOnly": "Invite Only",
@@ -136,7 +137,6 @@
"gemGiftsAreOptional": "Please note that Habitica will never require you to gift gems to other players. Begging people for gems is a violation of the Community Guidelines, and all such instances should be reported to <%= hrefTechAssistanceEmail %>.",
"battleWithFriends": "Battle Monsters With Friends",
"startAParty": "Start a Party",
- "possessiveParty": "<%= name %>'s Party",
"partyUpName": "Party Up",
"partyOnName": "Party On",
"partyUpText": "Joined a Party with another person! Have fun battling monsters and supporting each other.",