Compare commits

..

186 Commits

Author SHA1 Message Date
SabreCat 6e8e7318f3 4.238.0 2022-08-02 10:09:31 -05:00
SabreCat 1c3d4a6fd5 Revert "Revert "chore(content): add August 2022 Backgrounds and Enchanted Armoire Items (#14149)""
This reverts commit 9a2b49b4bf.
2022-08-02 10:09:02 -05:00
SabreCat 9ed2359c77 4.237.1 2022-08-01 08:51:49 -05:00
SabreCat 0dc21fa868 fix(css): redo sprites compile 2022-08-01 08:51:44 -05:00
SabreCat b87527bcea 4.237.0 2022-07-29 16:26:29 -05:00
SabreCat 0adfc9f756 chore(subproject): update habitica-images 2022-07-29 16:26:15 -05:00
SabreCat 9a2b49b4bf Revert "chore(content): add August 2022 Backgrounds and Enchanted Armoire Items (#14149)"
This reverts commit 2748455f16.
2022-07-29 16:25:14 -05:00
SabreCat 750a02053c feat(content): August 2022 subscriber items
Code by @CuriousMagpie
2022-07-29 16:24:32 -05:00
Natalie L 2748455f16 chore(content): add August 2022 Backgrounds and Enchanted Armoire Items (#14149)
* chore(submodule): add August 2022 Mystery Items

* chore(content): August 2022 Backgrounds and Enchanted Armoire Items

* chore(submodule): August 2022 Backgrounds and Enchanted Armoire images

* fix(typo): space

* fix(whitespace): spaces

Co-authored-by: Sabe Jones <sabrecat@gmail.com>
2022-07-29 16:21:20 -05:00
SabreCat cc0e807609 4.236.3 2022-07-21 15:36:17 -05:00
SabreCat bbc5a54a3e Merge branch 'develop' into release 2022-07-21 15:36:13 -05:00
Sabe Jones 8e717de039 Server setting to disallow chat from new accounts (#13952)
* feat(chat): server setting to disallow chat from new accounts

* fix(tests): many adjustments to handle chat minimum age

* fix(tests): address issues outside of chat posting

* chore(analytics): add incident logging

* fix(config): allow instant chat for dev purposes

* fix(test): finely age one more user

* fix(test): member not leader

Co-authored-by: SabreCat <sabe@habitica.com>
2022-07-21 15:32:28 -05:00
Natalie L ce18e614be Gifting modal design - amazonModal.vue update (#14131)
* update selectUserModal.vue

* more updates to selectUserModal.vue, typo fix in subscriber.json

* remove exact sizing for selectUserModal.vue

* update to size for selectUserModal.vue

* added sendGiftModal.vue file

* updates to selectUser & sendGift modals

* making the modals go & position cursor

* working working working

* added a return to method

* avatar display & placeholder profile.name and username

* subscription-options added

* added menu row & started on gem options

* Added selectPage function, have not tested.

* updated habitica-images

* state changes

* bringing in gem counter

* arranging elements

* state changes, gem input boxes

* styling sendGiftModal.vue

* more sendGiftModal.vue styling and new close.svg icon

* more styling!

* and more styling of send own gems part of page

* images update

* more styling of own gems & some attempts to adjust :class on the menu

* styling styling styling

* replace +/- svg, styling

* styling, mostly

* new SVGs

* stylin'

* reverting svg changes

* no more stylin'

* finally got the +/- icons to show up...but they're the wrong color

* solved svg icon color problem! :)

* habitica-images

* working on sendGift part of button

* trying to make it do math, failing

* more attempts at math

* +/- buttons work on gem pages & cost calculation on buyGems

* trying to get hover colors working on +/- svgs

* formatted dollar amount as currency

* css/html for subscription-options & payments-buttons simplified

* swag at payments-buttons parameter (not tested)

* send gems from own balance works!

* working on starting page

* increment gem amount limited to maxGems and not < 0

* uncommented onHide()

* got bg color on sub options to work! yay!

* payment buttons!

* making g1g1 look good

* position modal on page properly & code clean-up

* Changes as requested!

* small color update

* fixed ternary function

* chore(html): indentation and comments

* fix(fn): correct catch for under-0

* chore(json): whitespace

* update gem styling; add linebreak to notifications.vue bc linter

* updating subscriptionOptions

* snackbar css fix

* reverting commit e16c12f

* removing merge conflict markers

* just a little comment

* fixed some navigation, clear input field on selectPage, cleaned up code; another try at subscriptionOption.vue

* merge upstream/develop

* update selectPage() to disable Gems menu items when on 'ownGems' or 'buyGems' states

* working on subscriptionOptions.vue logic

* fix(script): changed props & added updateSubscriptionData()

* fix(script): forgot to call updateSubscriptionData()

* fix(scripts): corrected :userReceivingGift on sendGiftModal.vue

* fix(scripts): correct props userReceivingGift to an Object

* fix(scripts): corrected v-if & revised props

* fix(style/html/whitespace): updated css for close.svg and added missing </div>

* style(radio-buttons): updated focus states and added hover states

* style(radio-buttons): refined focus and hover states

* fix(function): changed buyGemsLink to buyGems; still working on menu

* style(radio buttons): ensured consistent display of radio buttons through-out site; still struggling with hover states

* style(radio buttons): updated focus/active/hover to match design & removed unnecessary code

* fix: set default subscription option to 1 month

* fix(function): add default amounts to gem states when modal selected from user profile

* fix(build): use develop package json

* fix: SCSS commenting & abstracted setGemsDefault()

* fix(packages): revert to develop

* fix: remove unnecessary console.log statement

* fix(payments): storePaymentStatusAndReload() modified

Co-authored-by: SabreCat <sabe@habitica.com>
2022-07-21 14:06:50 -05:00
dependabot[bot] 58c27c2610 build(deps): bump apidoc from 0.51.1 to 0.52.0 (#14126)
Bumps [apidoc](https://github.com/apidoc/apidoc) from 0.51.1 to 0.52.0.
- [Release notes](https://github.com/apidoc/apidoc/releases)
- [Changelog](https://github.com/apidoc/apidoc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/apidoc/apidoc/compare/0.51.1...0.52.0)

---
updated-dependencies:
- dependency-name: apidoc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-18 17:03:16 -04:00
dependabot[bot] 220dd51f85 build(deps): bump core-js from 3.23.4 to 3.23.5 in /website/client (#14127)
Bumps [core-js](https://github.com/zloirock/core-js) from 3.23.4 to 3.23.5.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.23.4...v3.23.5)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-18 17:02:59 -04:00
Vi Mio 3b1407f529 feat: prevent user from purchasing a quest if prerequisites are not met (#14073)
* feat: prevent user from purchasing a quest if prerequisites are not met

* test: fail to buy quest if not all prerequisites are met

* test: modify to check all quest prerequisites
2022-07-14 15:24:52 -05:00
SabreCat be7b3076eb 4.236.2 2022-07-13 14:52:10 -05:00
negue 2b4ffdf27f filter out bank challenge if is not userSupport 2022-07-13 14:52:05 -05:00
negue e0dc608fd8 Transaction Logs - Backend Changes 2022-07-13 14:51:56 -05:00
negue 0b4059aab0 Transaction Logs - Backend Changes (#14113)
* Transaction Logs - Backend Changes

* filter out bank challenge if is not userSupport
2022-07-13 14:18:59 -05:00
Natalie L 3aa7b8b447 Gifting modal design (#14124)
* update selectUserModal.vue

* more updates to selectUserModal.vue, typo fix in subscriber.json

* remove exact sizing for selectUserModal.vue

* update to size for selectUserModal.vue

* added sendGiftModal.vue file

* updates to selectUser & sendGift modals

* making the modals go & position cursor

* working working working

* added a return to method

* avatar display & placeholder profile.name and username

* subscription-options added

* added menu row & started on gem options

* Added selectPage function, have not tested.

* updated habitica-images

* state changes

* bringing in gem counter

* arranging elements

* state changes, gem input boxes

* styling sendGiftModal.vue

* more sendGiftModal.vue styling and new close.svg icon

* more styling!

* and more styling of send own gems part of page

* images update

* more styling of own gems & some attempts to adjust :class on the menu

* styling styling styling

* replace +/- svg, styling

* styling, mostly

* new SVGs

* stylin'

* reverting svg changes

* no more stylin'

* finally got the +/- icons to show up...but they're the wrong color

* solved svg icon color problem! :)

* habitica-images

* working on sendGift part of button

* trying to make it do math, failing

* more attempts at math

* +/- buttons work on gem pages & cost calculation on buyGems

* trying to get hover colors working on +/- svgs

* formatted dollar amount as currency

* css/html for subscription-options & payments-buttons simplified

* swag at payments-buttons parameter (not tested)

* send gems from own balance works!

* working on starting page

* increment gem amount limited to maxGems and not < 0

* uncommented onHide()

* got bg color on sub options to work! yay!

* payment buttons!

* making g1g1 look good

* position modal on page properly & code clean-up

* Changes as requested!

* small color update

* fixed ternary function

* chore(html): indentation and comments

* fix(fn): correct catch for under-0

* chore(json): whitespace

* update gem styling; add linebreak to notifications.vue bc linter

* updating subscriptionOptions

* snackbar css fix

* reverting commit e16c12f

* removing merge conflict markers

* just a little comment

* fixed some navigation, clear input field on selectPage, cleaned up code; another try at subscriptionOption.vue

* merge upstream/develop

* update selectPage() to disable Gems menu items when on 'ownGems' or 'buyGems' states

* working on subscriptionOptions.vue logic

* fix(script): changed props & added updateSubscriptionData()

* fix(script): forgot to call updateSubscriptionData()

* fix(scripts): corrected :userReceivingGift on sendGiftModal.vue

* fix(scripts): correct props userReceivingGift to an Object

* fix(scripts): corrected v-if & revised props

* fix(style/html/whitespace): updated css for close.svg and added missing </div>

* style(radio-buttons): updated focus states and added hover states

* style(radio-buttons): refined focus and hover states

* fix(function): changed buyGemsLink to buyGems; still working on menu

* style(radio buttons): ensured consistent display of radio buttons through-out site; still struggling with hover states

* style(radio buttons): updated focus/active/hover to match design & removed unnecessary code

* fix: set default subscription option to 1 month

* fix(function): add default amounts to gem states when modal selected from user profile

* fix(build): use develop package json

* fix: SCSS commenting & abstracted setGemsDefault()

* fix(packages): revert to develop

* fix: remove unnecessary console.log statement

Co-authored-by: SabreCat <sabe@habitica.com>
2022-07-13 14:17:28 -05:00
dependabot[bot] 94b9bb1036 build(deps): bump image-size from 1.0.1 to 1.0.2 (#14123)
Bumps [image-size](https://github.com/image-size/image-size) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/image-size/image-size/releases)
- [Commits](https://github.com/image-size/image-size/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: image-size
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-13 12:11:38 -04:00
dependabot[bot] a2f169ab76 build(deps): bump core-js from 3.23.3 to 3.23.4 in /website/client (#14114)
Bumps [core-js](https://github.com/zloirock/core-js) from 3.23.3 to 3.23.4.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.23.3...v3.23.4)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-13 12:10:45 -04:00
SabreCat 6d345740ff Merge branch 'release' into develop 2022-07-12 10:06:07 -05:00
SabreCat 294cc63fef 4.236.1 2022-07-12 10:05:09 -05:00
SabreCat 9a879d566e fix(content): correct availability range for Seafoam 2022-07-12 10:05:02 -05:00
Scott Coffrin 8ecb0f45b5 Modal responsive improvements (#14087)
* stack profile actions on smaller screens

* stack avatar and stats for even smaller screens

* remove unnecessary classes to keep profile nav on the same line

* adjust media query width

* refactor stats removing unnecessary classes and simplifying with less elements and relying more on flexbox

* adjust breakpoints for modal vs pofile page

* more margin for avatar

* handle allocation on middle size more gracefully

Co-authored-by: scoffrin <scoffrin@indeed.com>
2022-07-08 15:49:22 -05:00
darkarchana b04df06a37 Fix no response when password changed (#14054)
* Fix no response when password changed

* Update website/client/src/components/settings/site.vue

update the spacing in website/client/src/components/settings/site.vue

Co-authored-by: Panu Valtanen <p4nu@users.noreply.github.com>

* Update website/client/src/components/settings/site.vue

change to single quote

* Fix success change password response using internationalization

* fix(i18n): remove translations other than US English
Partial revert of #1a198677bd

Co-authored-by: Panu Valtanen <p4nu@users.noreply.github.com>
Co-authored-by: SabreCat <sabe@habitica.com>
2022-07-08 15:42:18 -05:00
bbqben 706cffa71d 🐛 Update fetch language call to not retrieve from cache (#14099)
Co-authored-by: Ben Tran <bentran@Bens-Intel-MacBook-Pro.local>
2022-07-06 15:32:07 -05:00
dependabot[bot] 00b8f4fef5 build(deps): bump moment from 2.29.3 to 2.29.4 (#14111)
Bumps [moment](https://github.com/moment/moment) from 2.29.3 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.3...2.29.4)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-06 15:28:28 -05:00
dependabot[bot] 5ea675b8a5 build(deps): bump async from 2.6.3 to 2.6.4 in /website/client (#14109)
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-06 15:28:12 -05:00
dependabot[bot] 78f0c71387 build(deps): bump moment from 2.29.3 to 2.29.4 in /website/client (#14112)
Bumps [moment](https://github.com/moment/moment) from 2.29.3 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.3...2.29.4)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-06 15:28:01 -05:00
SabreCat e674ef4035 Merge branch 'release' into develop 2022-07-06 14:34:24 -05:00
SabreCat 1655e2e03a 4.236.0 2022-07-06 14:32:58 -05:00
Natalie L 0d444a9d6a chore(content): prebuild July Enchanted Armoire and Backgrounds (#14108) 2022-07-06 14:30:40 -05:00
dependabot[bot] de331f5e76 build(deps-dev): bump @babel/plugin-proposal-optional-chaining (#14105)
Bumps [@babel/plugin-proposal-optional-chaining](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-optional-chaining) from 7.17.12 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-plugin-proposal-optional-chaining)

---
updated-dependencies:
- dependency-name: "@babel/plugin-proposal-optional-chaining"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 16:06:03 -04:00
dependabot[bot] c48043ec90 build(deps): bump @vue/cli-plugin-eslint in /website/client (#14106)
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.18 to 4.5.19.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.19/packages/@vue/cli-plugin-eslint)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-eslint"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 16:03:41 -04:00
dependabot[bot] ac4d148170 build(deps): bump winston from 3.8.0 to 3.8.1 (#14103)
Bumps [winston](https://github.com/winstonjs/winston) from 3.8.0 to 3.8.1.
- [Release notes](https://github.com/winstonjs/winston/releases)
- [Changelog](https://github.com/winstonjs/winston/blob/master/CHANGELOG.md)
- [Commits](https://github.com/winstonjs/winston/compare/v3.8.0...v3.8.1)

---
updated-dependencies:
- dependency-name: winston
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 16:01:03 -04:00
dependabot[bot] ca49e995be build(deps): bump @babel/preset-env from 7.18.2 to 7.18.6 (#14098)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.18.2 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-05 15:43:56 -04:00
SabreCat d47a867149 Merge branch 'release' into develop 2022-07-05 14:34:30 -05:00
SabreCat f4d9c6271b 4.235.1 2022-07-05 14:34:17 -05:00
Natalie L 0e458683fd chore(content): add splashySkins for Summer Gala event (#14107)
* chore(content): add splashySkins for Summer Gala event

* fix(content): use date string, not Boolean, for range start

Co-authored-by: SabreCat <sabe@habitica.com>
2022-07-05 14:33:50 -05:00
Alys 76ab93f501 add deilann to moderators in Tavern and Community Guidelines
Note that his picture is still needed in the Community Guidelines
and when that's done, the "(not yet pictured)" text should be removed
2022-07-02 14:04:09 +10:00
Alys 5d4600f5c7 add banned words - TRIGGER / CONTENT WARNING: assault, slurs, swearwords, etc 2022-07-01 20:55:34 +10:00
dependabot[bot] 13c4a726c7 build(deps): bump @babel/core from 7.18.5 to 7.18.6 (#14097)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.5 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 13:45:15 -04:00
dependabot[bot] 43122805fb build(deps): bump @babel/register from 7.17.7 to 7.18.6 (#14096)
Bumps [@babel/register](https://github.com/babel/babel/tree/HEAD/packages/babel-register) from 7.17.7 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-register)

---
updated-dependencies:
- dependency-name: "@babel/register"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 13:44:55 -04:00
dependabot[bot] 1262d8f36e build(deps): bump core-js from 3.23.1 to 3.23.3 in /website/client (#14094)
Bumps [core-js](https://github.com/zloirock/core-js) from 3.23.1 to 3.23.3.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.23.1...v3.23.3)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 13:42:41 -04:00
dependabot[bot] 2b1635ff62 build(deps): bump winston from 3.7.2 to 3.8.0 (#14093)
Bumps [winston](https://github.com/winstonjs/winston) from 3.7.2 to 3.8.0.
- [Release notes](https://github.com/winstonjs/winston/releases)
- [Changelog](https://github.com/winstonjs/winston/blob/master/CHANGELOG.md)
- [Commits](https://github.com/winstonjs/winston/compare/v3.7.2...v3.8.0)

---
updated-dependencies:
- dependency-name: winston
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 13:42:19 -04:00
dependabot[bot] e1664d2f87 build(deps): bump amplitude-js from 8.18.4 to 8.18.5 in /website/client (#14089)
Bumps [amplitude-js](https://github.com/amplitude/amplitude-javascript) from 8.18.4 to 8.18.5.
- [Release notes](https://github.com/amplitude/amplitude-javascript/releases)
- [Changelog](https://github.com/amplitude/Amplitude-JavaScript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/amplitude/amplitude-javascript/compare/v8.18.4...v8.18.5)

---
updated-dependencies:
- dependency-name: amplitude-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-30 13:39:42 -04:00
SabreCat 6975b6061b Merge branch 'release' into develop 2022-06-29 14:04:39 -05:00
SabreCat 695a5cc24d 4.235.0 2022-06-29 14:04:28 -05:00
Natalie L dcced2debb chore(content): July 2022 Mystery Items (#14095)
* merge upstream/release into release

* chore(content): Added July 2022 Mystery Items
2022-06-29 14:02:46 -05:00
SabreCat 88af9c13a8 4.234.2 2022-06-27 16:35:20 -05:00
SabreCat d5926ef7f1 fix(auth): null string validation error on unique email conflict 2022-06-27 16:35:13 -05:00
SabreCat e9222e4f7c fix(strings): revise text because left-handedness confuses people 2022-06-27 16:11:23 -05:00
SabreCat cd0278c6b3 fix(strings): cherry-pick update by @CuriousMagpie 2022-06-24 15:44:48 -05:00
Natalie L 9680c94087 fix(strings): removed extra word in headSpecialSummer2022WarriorNotes (#14088)
* fix(string): questVice1Notes html changed to a mobile-device friendly format

* fix(strings): updated limited.json with "dateEnd" & "monthYYYY" months & put in chronological order

* fix(string): remove extra word from headSpecialSummer2022WarriorNotes

* fix(string): corrected armorSpecialSummer2022MageNotes
2022-06-24 15:43:38 -05:00
Weblate 76de241675 Added translation using Weblate (Cebuano)
Added translation using Weblate (Cebuano)

Added translation using Weblate (Cebuano)

Added translation using Weblate (Cebuano)

Merge branch 'origin/develop' into Weblate.

Translated using Weblate (Portuguese)

Currently translated at 83.9% (115 of 137 strings)

Translated using Weblate (Portuguese)

Currently translated at 83.9% (115 of 137 strings)

Translated using Weblate (Portuguese)

Currently translated at 83.9% (115 of 137 strings)

Translated using Weblate (Greek)

Currently translated at 75.0% (6 of 8 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2607 of 2607 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2607 of 2607 strings)

Translated using Weblate (Filipino)

Currently translated at 43.8% (1139 of 2597 strings)

Translated using Weblate (Filipino)

Currently translated at 43.7% (1137 of 2597 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (2607 of 2607 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (704 of 704 strings)

Translated using Weblate (Dutch)

Currently translated at 90.6% (2363 of 2607 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (704 of 704 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 98.5% (135 of 137 strings)

Translated using Weblate (French)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (German)

Currently translated at 100.0% (755 of 755 strings)

Co-authored-by: Benoit Hetru <me+hbtc@gahanka.net>
Co-authored-by: Céu <marcel.ufscar@gmail.com>
Co-authored-by: Hexe des Windes (she/her) <krausanna1@gmail.com>
Co-authored-by: Lucifer <selmanreyhan@gmail.com>
Co-authored-by: Mara S. (Dolichotis) <marascherzer@gmail.com>
Co-authored-by: Martim Pinto Paiva <pintopaivam@gmail.com>
Co-authored-by: Nathan Monteiro <nathanspeeds1@outlook.com>
Co-authored-by: Panagiotis Zachos <panzaxos@gmail.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: SunshineRain <suusykraft@gmail.com>
Co-authored-by: Vince Vilan <vincemorel.vilan.889@my.csun.edu>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/it/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/overview/el/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Gear
Translation: Habitica/Overview
Translation: Habitica/Questscontent
2022-06-22 21:18:17 +02:00
SabreCat 3ba6b4a209 feat(language): initialize Cebuano for translation 2022-06-22 14:04:51 -05:00
SabreCat b101d43e62 Merge branch 'release' into develop 2022-06-21 13:50:35 -05:00
SabreCat 59a1a2783c 4.234.1 2022-06-21 13:50:22 -05:00
Natalie L 517fbc3c8e fix(strings): error and omissions corrected (#14085)
* build(deps): bump @storybook/addons in /website/client (#14066)

Bumps [@storybook/addons](https://github.com/storybookjs/storybook/tree/HEAD/lib/addons) from 6.5.8 to 6.5.9.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.9/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.9/lib/addons)

---
updated-dependencies:
- dependency-name: "@storybook/addons"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump jpeg-js from 0.4.3 to 0.4.4 (#14071)

Bumps [jpeg-js](https://github.com/eugeneware/jpeg-js) from 0.4.3 to 0.4.4.
- [Release notes](https://github.com/eugeneware/jpeg-js/releases)
- [Commits](https://github.com/eugeneware/jpeg-js/compare/v0.4.3...v0.4.4)

---
updated-dependencies:
- dependency-name: jpeg-js
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix(string): questVice1Notes html changed to a mobile-device friendly format

* fix(strings): updated limited.json with "dateEnd" & "monthYYYY" months & put in chronological order

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-21 13:48:26 -05:00
dependabot[bot] c0e8d80966 build(deps): bump @vue/cli-plugin-eslint in /website/client (#14084)
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.17 to 4.5.18.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.18/packages/@vue/cli-plugin-eslint)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-eslint"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-21 13:02:34 -04:00
dependabot[bot] afacd497d7 build(deps): bump core-js from 3.22.8 to 3.23.1 in /website/client (#14082)
Bumps [core-js](https://github.com/zloirock/core-js) from 3.22.8 to 3.23.1.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.22.8...v3.23.1)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-21 13:02:07 -04:00
SabreCat dc744de4a9 Merge branch 'release' into develop 2022-06-21 09:33:35 -05:00
SabreCat b042d4b899 4.234.0 2022-06-21 09:33:22 -05:00
Natalie L f0c25dab05 2022 Summer Gala Content (#14067)
* merge upstream/release into origin/release

* Revert "merge upstream/release into origin/release"

This reverts commit 902ed08cc3.

* Summer Splash 2022 Content

* added magic hatching potions

* updated events for testing

* fix whitespace

* various corrections

* fix(gear): mage set, healer set, event start date

* update: habitica-images

* fix(events): include normal/empty season data outside of gala

* fix(string): missing attribute and event verbiage for warrior item

Co-authored-by: SabreCat <sabe@habitica.com>
2022-06-21 09:29:53 -05:00
dependabot[bot] f44bebb573 build(deps): bump jpeg-js from 0.4.3 to 0.4.4 (#14071)
Bumps [jpeg-js](https://github.com/eugeneware/jpeg-js) from 0.4.3 to 0.4.4.
- [Release notes](https://github.com/eugeneware/jpeg-js/releases)
- [Commits](https://github.com/eugeneware/jpeg-js/compare/v0.4.3...v0.4.4)

---
updated-dependencies:
- dependency-name: jpeg-js
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-17 13:26:08 -04:00
dependabot[bot] 8ccf701aec build(deps): bump @storybook/addons in /website/client (#14066)
Bumps [@storybook/addons](https://github.com/storybookjs/storybook/tree/HEAD/lib/addons) from 6.5.8 to 6.5.9.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.9/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.9/lib/addons)

---
updated-dependencies:
- dependency-name: "@storybook/addons"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-16 16:18:59 -04:00
SabreCat 170146f91e 4.233.3 2022-06-16 14:08:50 -05:00
SabreCat 239821a321 Merge branch 'sabrecat/teams-hotfixes' into release 2022-06-16 14:08:41 -05:00
SabreCat d0dd16c797 Merge branch 'develop' into release 2022-06-16 13:35:33 -05:00
Weblate 8c3517caab Merge branch 'origin/develop' into Weblate. 2022-06-16 20:34:16 +02:00
Weblate 4c2c1c29a3 Translated using Weblate (Dutch)
Currently translated at 96.5% (729 of 755 strings)

Translated using Weblate (Filipino)

Currently translated at 43.7% (1136 of 2597 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (211 of 211 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (704 of 704 strings)

Translated using Weblate (Italian)

Currently translated at 99.0% (209 of 211 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 97.5% (2542 of 2607 strings)

Translated using Weblate (Portuguese)

Currently translated at 91.0% (641 of 704 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (198 of 198 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.7% (215 of 220 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.0% (212 of 214 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Romanian)

Currently translated at 73.8% (520 of 704 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (704 of 704 strings)

Translated using Weblate (Portuguese)

Currently translated at 90.7% (639 of 704 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.0% (133 of 137 strings)

Translated using Weblate (German)

Currently translated at 100.0% (220 of 220 strings)

Translated using Weblate (German)

Currently translated at 100.0% (111 of 111 strings)

Translated using Weblate (German)

Currently translated at 100.0% (704 of 704 strings)

Translated using Weblate (German)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (German)

Currently translated at 99.0% (697 of 704 strings)

Translated using Weblate (German)

Currently translated at 99.0% (697 of 704 strings)

Translated using Weblate (German)

Currently translated at 99.0% (697 of 704 strings)

Translated using Weblate (German)

Currently translated at 99.0% (697 of 704 strings)

Translated using Weblate (Croatian)

Currently translated at 59.4% (66 of 111 strings)

Translated using Weblate (Croatian)

Currently translated at 39.6% (44 of 111 strings)

Translated using Weblate (Filipino)

Currently translated at 43.5% (1131 of 2597 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Filipino)

Currently translated at 43.3% (1126 of 2597 strings)

Translated using Weblate (Catalan)

Currently translated at 91.4% (193 of 211 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (137 of 137 strings)

Translated using Weblate (Spanish)

Currently translated at 99.0% (209 of 211 strings)

Translated using Weblate (Spanish)

Currently translated at 97.8% (134 of 137 strings)

Translated using Weblate (German)

Currently translated at 100.0% (365 of 365 strings)

Translated using Weblate (German)

Currently translated at 100.0% (365 of 365 strings)

Translated using Weblate (Spanish)

Currently translated at 99.4% (751 of 755 strings)

Translated using Weblate (German)

Currently translated at 100.0% (127 of 127 strings)

Translated using Weblate (German)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Spanish)

Currently translated at 97.0% (133 of 137 strings)

Translated using Weblate (German)

Currently translated at 100.0% (137 of 137 strings)

Translated using Weblate (German)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (German)

Currently translated at 99.2% (136 of 137 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2607 of 2607 strings)

Translated using Weblate (German)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Filipino)

Currently translated at 43.2% (1122 of 2597 strings)

Translated using Weblate (Filipino)

Currently translated at 43.2% (1122 of 2597 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (199 of 199 strings)

Translated using Weblate (Dutch)

Currently translated at 90.4% (2359 of 2607 strings)

Translated using Weblate (French)

Currently translated at 99.8% (2604 of 2607 strings)

Translated using Weblate (Dutch)

Currently translated at 96.5% (729 of 755 strings)

Translated using Weblate (Dutch)

Currently translated at 96.5% (729 of 755 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (137 of 137 strings)

Translated using Weblate (Ukrainian)

Currently translated at 98.8% (178 of 180 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (137 of 137 strings)

Translated using Weblate (Arabic)

Currently translated at 87.5% (113 of 129 strings)

Translated using Weblate (Arabic)

Currently translated at 87.5% (113 of 129 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (2607 of 2607 strings)

Translated using Weblate (Italian)

Currently translated at 99.8% (2604 of 2607 strings)

Translated using Weblate (Spanish)

Currently translated at 98.2% (2562 of 2607 strings)

Translated using Weblate (Filipino)

Currently translated at 43.2% (1122 of 2597 strings)

Translated using Weblate (Filipino)

Currently translated at 43.1% (1121 of 2597 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (137 of 137 strings)

Translated using Weblate (French)

Currently translated at 100.0% (137 of 137 strings)

Translated using Weblate (Italian)

Currently translated at 98.5% (135 of 137 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (German)

Currently translated at 100.0% (220 of 220 strings)

Translated using Weblate (German)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (German)

Currently translated at 100.0% (15 of 15 strings)

Translated using Weblate (German)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (German)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2597 of 2597 strings)

Translated using Weblate (French)

Currently translated at 100.0% (199 of 199 strings)

Translated using Weblate (French)

Currently translated at 100.0% (2597 of 2597 strings)

Translated using Weblate (Filipino)

Currently translated at 43.1% (1120 of 2597 strings)

Translated using Weblate (Filipino)

Currently translated at 95.9% (358 of 373 strings)

Translated using Weblate (German)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (German)

Currently translated at 100.0% (129 of 129 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2597 of 2597 strings)

Translated using Weblate (German)

Currently translated at 100.0% (127 of 127 strings)

Translated using Weblate (German)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (German)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (German)

Currently translated at 100.0% (199 of 199 strings)

Translated using Weblate (German)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (German)

Currently translated at 99.8% (2593 of 2597 strings)

Translated using Weblate (Filipino)

Currently translated at 42.9% (1116 of 2597 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Spanish)

Currently translated at 98.5% (132 of 134 strings)

Co-authored-by: Benoit Hetru <me+hbtc@gahanka.net>
Co-authored-by: CaveMobster <cavemobster@gmail.com>
Co-authored-by: Céu <marcel.ufscar@gmail.com>
Co-authored-by: Daniela Fernberg <martina_kloster@web.de>
Co-authored-by: Fharid Solis <cfharidsq@gmail.com>
Co-authored-by: Hexe des Windes (she/her) <krausanna1@gmail.com>
Co-authored-by: Ike Osenberg <ike.osenberg@gmail.com>
Co-authored-by: JoanZeppeli <x17501668978@163.com>
Co-authored-by: Lucifer <selmanreyhan@gmail.com>
Co-authored-by: Madeline Perray <maperray@gmail.com>
Co-authored-by: Mara S. (Dolichotis) <marascherzer@gmail.com>
Co-authored-by: Natalie Luhrs <eilatan@gmail.com>
Co-authored-by: Nazar Paruna <nazarparuna@gmail.com>
Co-authored-by: Quim Martínez Lara <quimml60@gmail.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: Sara López <sarayupy@gmail.com>
Co-authored-by: Simon Fischer <simon.pascal.fischer@gmail.com>
Co-authored-by: Tobias Welti <tobias.welti@gmail.com>
Co-authored-by: Vince Vilan <vincemorel.vilan.889@my.csun.edu>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: William Madgin <wmadgin.cnf@gmail.com>
Co-authored-by: xioxi <potentiallytyler@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es_419/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/it/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/it/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ro/
Translate-URL: https://translate.habitica.com/projects/habitica/character/de/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/de/
Translate-URL: https://translate.habitica.com/projects/habitica/content/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/de/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/es/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/es_419/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/death/de/
Translate-URL: https://translate.habitica.com/projects/habitica/front/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/de/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/de/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/de/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/de/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/de/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ca/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/it/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/de/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/hr/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Character
Translation: Habitica/Communityguidelines
Translation: Habitica/Content
Translation: Habitica/Contrib
Translation: Habitica/Death
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Generic
Translation: Habitica/Groups
Translation: Habitica/Limited
Translation: Habitica/Npc
Translation: Habitica/Pets
Translation: Habitica/Questscontent
Translation: Habitica/Settings
Translation: Habitica/Subscriber
Translation: Habitica/Tasks
2022-06-16 20:33:41 +02:00
SabreCat fb086bb654 4.233.2 2022-06-16 13:31:16 -05:00
SabreCat db6310f8ab Merge branch 'sabrecat/privately-naughty' into develop 2022-06-16 13:30:57 -05:00
SabreCat 08288db1ef chore(words): allow mild oaths and troublesome streamer as discussed 2022-06-16 13:30:34 -05:00
SabreCat 4a3a7db52a Merge develop 2022-06-16 13:25:56 -05:00
SabreCat 0f8ed2c06a Merge branch 'release' into develop 2022-06-14 14:38:29 -05:00
SabreCat 0ceb0fd844 4.233.1 2022-06-14 14:34:31 -05:00
SabreCat 285fcbd71f fix(content): add event field for countdown 2022-06-14 14:34:25 -05:00
CuriousMagpie 36d82a1d39 June 2022 Pet Quest Bundle 2022-06-14 14:33:53 -05:00
dependabot[bot] 3dd3639964 build(deps): bump @babel/core from 7.18.2 to 7.18.5 (#14064)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.18.2 to 7.18.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.5/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 17:21:23 -04:00
dependabot[bot] 5b20961908 build(deps): bump @storybook/addons in /website/client (#14062)
Bumps [@storybook/addons](https://github.com/storybookjs/storybook/tree/HEAD/lib/addons) from 6.5.7 to 6.5.8.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.8/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.8/lib/addons)

---
updated-dependencies:
- dependency-name: "@storybook/addons"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 16:44:20 -04:00
dependabot[bot] f4fd5e221e build(deps): bump @storybook/addon-links in /website/client (#14061)
Bumps [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/addons/links) from 6.5.7 to 6.5.8.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.8/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.8/addons/links)

---
updated-dependencies:
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 16:44:07 -04:00
dependabot[bot] 4be863de99 build(deps): bump @storybook/addon-actions in /website/client (#14060)
Bumps [@storybook/addon-actions](https://github.com/storybookjs/storybook/tree/HEAD/addons/actions) from 6.5.7 to 6.5.8.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.8/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.8/addons/actions)

---
updated-dependencies:
- dependency-name: "@storybook/addon-actions"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 16:43:52 -04:00
dependabot[bot] 905d749e7b build(deps): bump jwks-rsa from 2.1.3 to 2.1.4 (#14057)
Bumps [jwks-rsa](https://github.com/auth0/node-jwks-rsa) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/auth0/node-jwks-rsa/releases)
- [Changelog](https://github.com/auth0/node-jwks-rsa/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jwks-rsa/compare/v2.1.3...v2.1.4)

---
updated-dependencies:
- dependency-name: jwks-rsa
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-13 16:41:36 -04:00
Phillip Thelen 65d2eac4c3 Correctly handle google accounts with multiple subscriptions (#13982) 2022-06-10 14:07:36 -05:00
sau226 a0884b5d24 Remove QR code feature (#14038) 2022-06-10 14:06:25 -05:00
sau226 4d10c53216 Further transition from HTTP to HTTPS (#14039) 2022-06-10 14:02:58 -05:00
Jennifer Aldover 4da6467486 update apidoc exportUserAvatarHtml description (#14040) 2022-06-10 13:59:17 -05:00
dependabot[bot] bb37adb97b build(deps): bump core-js from 3.22.7 to 3.22.8 in /website/client (#14046)
Bumps [core-js](https://github.com/zloirock/core-js) from 3.22.7 to 3.22.8.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.22.7...v3.22.8)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-10 13:50:07 -04:00
SabreCat 02fef2d0d9 fix(test): add missing helper to v4 2022-06-09 15:50:43 -05:00
SabreCat d668fd8920 fix(tests): missed alt test suite versions 2022-06-09 15:22:23 -05:00
SabreCat 85c7c7ea57 fix(tests): create test teams properly, adjust expectations 2022-06-09 15:06:51 -05:00
SabreCat 0b1907fe07 fix(group-plans): shared completion, URL exploit 2022-06-08 16:46:22 -05:00
SabreCat 87944c45c3 Merge branch 'release' into develop 2022-06-08 14:55:59 -05:00
SabreCat 86068f42d4 4.233.0 2022-06-07 15:04:38 -05:00
dependabot[bot] 2fe1ac75d2 build(deps): bump @storybook/addon-links in /website/client (#14048)
Bumps [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/addons/links) from 6.5.6 to 6.5.7.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.7/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.7/addons/links)

---
updated-dependencies:
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 16:35:34 -04:00
dependabot[bot] c0be7c77d1 build(deps): bump @storybook/addons in /website/client (#14047)
Bumps [@storybook/addons](https://github.com/storybookjs/storybook/tree/HEAD/lib/addons) from 6.4.19 to 6.5.7.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.7/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.7/lib/addons)

---
updated-dependencies:
- dependency-name: "@storybook/addons"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 16:35:19 -04:00
dependabot[bot] 37ff1c2c5c build(deps): bump @storybook/addon-actions in /website/client (#14045)
Bumps [@storybook/addon-actions](https://github.com/storybookjs/storybook/tree/HEAD/addons/actions) from 6.5.6 to 6.5.7.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.7/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.7/addons/actions)

---
updated-dependencies:
- dependency-name: "@storybook/addon-actions"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 16:34:57 -04:00
dependabot[bot] 1ccd0e8f70 build(deps): bump superagent from 7.1.3 to 7.1.6 (#14042)
Bumps [superagent](https://github.com/visionmedia/superagent) from 7.1.3 to 7.1.6.
- [Release notes](https://github.com/visionmedia/superagent/releases)
- [Changelog](https://github.com/visionmedia/superagent/blob/master/HISTORY.md)
- [Commits](https://github.com/visionmedia/superagent/compare/v7.1.3...v7.1.6)

---
updated-dependencies:
- dependency-name: superagent
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 16:34:20 -04:00
dependabot[bot] 82977e893b build(deps): bump gulp.spritesmith from 6.12.1 to 6.13.0 (#14041)
Bumps [gulp.spritesmith](https://github.com/twolfson/gulp.spritesmith) from 6.12.1 to 6.13.0.
- [Release notes](https://github.com/twolfson/gulp.spritesmith/releases)
- [Changelog](https://github.com/twolfson/gulp.spritesmith/blob/master/CHANGELOG.md)
- [Commits](https://github.com/twolfson/gulp.spritesmith/compare/6.12.1...6.13.0)

---
updated-dependencies:
- dependency-name: gulp.spritesmith
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 16:33:58 -04:00
dependabot[bot] 84046df884 build(deps): bump nconf from 0.11.3 to 0.12.0 in /website/client (#14006)
Bumps [nconf](https://github.com/flatiron/nconf) from 0.11.3 to 0.12.0.
- [Release notes](https://github.com/flatiron/nconf/releases)
- [Changelog](https://github.com/indexzero/nconf/blob/master/CHANGELOG.md)
- [Commits](https://github.com/flatiron/nconf/compare/v0.11.3...v0.12.0)

---
updated-dependencies:
- dependency-name: nconf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 16:32:13 -04:00
dependabot[bot] 46cbd6cf0d build(deps): bump @babel/core from 7.17.10 to 7.18.2 (#14024)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.17.10 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 16:31:50 -04:00
SabreCat 2cb724e6b2 Merge branch 'release' into develop 2022-06-06 15:14:36 -05:00
SabreCat d76d5f2cf1 Merge branch 'sabrecat/sanitize-redirect' into release 2022-06-06 15:03:30 -05:00
Natalie L 2d1bf74858 June 2022 Backgrounds and Enchanted Armoire (#14049) 2022-06-06 14:55:38 -05:00
SabreCat 986ba1b8ba chore(sprites): compile 2022-06-06 12:42:35 -05:00
SabreCat d68cacdc1d Merge branch 'release' into develop 2022-06-06 12:37:49 -05:00
Emiel Popelier c9671b5319 Styling Bugfix: 13772 (#13983) 2022-06-03 15:41:46 -05:00
SabreCat 6d2db6693c Merge branch 'develop' into release 2022-06-03 15:13:56 -05:00
SabreCat cd9e3aeab3 Revert "build(deps): bump passport from 0.5.0 to 0.6.0 (#13987)"
This reverts commit dd978b664b.
2022-06-03 15:13:41 -05:00
Sabe Jones 341517083e Record local email for social users where possible (#14029)
* fix(auth): record local email for social users where possible

* fix(auth): Apple emails are junk, prefer Google

* fix(auth): correct placement of logic to save local email

* fix(auth): run full function in both workflows to avoid conflicts

Co-authored-by: SabreCat <sabe@habitica.com>
2022-06-03 15:06:40 -05:00
Natalie L d726b88a86 Content: Beta Groups Testing Achievement (#14014)
* content: beta Groups testing achievement

* resolving merge conflict
2022-06-03 15:04:27 -05:00
SabreCat afc7b1218a 4.232.2 2022-06-03 14:04:49 -05:00
SabreCat 2c311952c8 chore(packages): update locks 2022-06-03 14:04:45 -05:00
Weblate 85a85b7173 Merge branch 'origin/develop' into Weblate. 2022-06-03 20:54:11 +02:00
Weblate 556d1e49ce Translated using Weblate (Italian)
Currently translated at 100.0% (199 of 199 strings)

Translated using Weblate (Swedish)

Currently translated at 83.4% (630 of 755 strings)

Translated using Weblate (Swedish)

Currently translated at 95.4% (356 of 373 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2562 of 2597 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Swedish)

Currently translated at 84.6% (11 of 13 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.0% (197 of 203 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.5% (132 of 134 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2562 of 2597 strings)

Translated using Weblate (Japanese)

Currently translated at 99.8% (2593 of 2597 strings)

Translated using Weblate (Filipino)

Currently translated at 43.3% (1125 of 2597 strings)

Translated using Weblate (Russian)

Currently translated at 99.2% (749 of 755 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 96.6% (2509 of 2597 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (2597 of 2597 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (366 of 366 strings)

Translated using Weblate (Ukrainian)

Currently translated at 98.3% (177 of 180 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (212 of 212 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (Arabic)

Currently translated at 69.3% (77 of 111 strings)

Translated using Weblate (Arabic)

Currently translated at 87.3% (117 of 134 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (22 of 22 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 97.5% (198 of 203 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (Filipino)

Currently translated at 47.8% (1240 of 2593 strings)

Translated using Weblate (Hebrew)

Currently translated at 71.6% (96 of 134 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (Russian)

Currently translated at 99.2% (749 of 755 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (212 of 212 strings)

Translated using Weblate (Hungarian)

Currently translated at 51.4% (69 of 134 strings)

Translated using Weblate (Filipino)

Currently translated at 54.3% (1409 of 2593 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Japanese)

Currently translated at 99.5% (202 of 203 strings)

Translated using Weblate (Hebrew)

Currently translated at 84.0% (79 of 94 strings)

Translated using Weblate (Hebrew)

Currently translated at 22.7% (5 of 22 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (Hebrew)

Currently translated at 93.3% (14 of 15 strings)

Translated using Weblate (Hebrew)

Currently translated at 75.4% (570 of 755 strings)

Translated using Weblate (Hebrew)

Currently translated at 86.0% (321 of 373 strings)

Translated using Weblate (Hebrew)

Currently translated at 86.0% (321 of 373 strings)

Translated using Weblate (Hebrew)

Currently translated at 73.6% (137 of 186 strings)

Translated using Weblate (Hebrew)

Currently translated at 73.6% (137 of 186 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (98 of 98 strings)

Translated using Weblate (Hebrew)

Currently translated at 70.8% (95 of 134 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (Dutch)

Currently translated at 90.7% (2354 of 2593 strings)

Translated using Weblate (Dutch)

Currently translated at 90.6% (2351 of 2593 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (German)

Currently translated at 99.0% (201 of 203 strings)

Translated using Weblate (German)

Currently translated at 100.0% (366 of 366 strings)

Translated using Weblate (German)

Currently translated at 100.0% (2593 of 2593 strings)

Translated using Weblate (German)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (German)

Currently translated at 99.7% (2587 of 2593 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (German)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (German)

Currently translated at 99.2% (133 of 134 strings)

Translated using Weblate (Arabic)

Currently translated at 90.6% (194 of 214 strings)

Translated using Weblate (French)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Filipino)

Currently translated at 60.6% (1572 of 2593 strings)

Translated using Weblate (Russian)

Currently translated at 98.1% (2545 of 2593 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (Swedish)

Currently translated at 98.5% (132 of 134 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Russian)

Currently translated at 97.8% (2537 of 2593 strings)

Translated using Weblate (Russian)

Currently translated at 97.1% (206 of 212 strings)

Translated using Weblate (Russian)

Currently translated at 97.1% (206 of 212 strings)

Translated using Weblate (Russian)

Currently translated at 91.0% (193 of 212 strings)

Translated using Weblate (Russian)

Currently translated at 91.0% (193 of 212 strings)

Translated using Weblate (Russian)

Currently translated at 97.7% (2535 of 2593 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (180 of 180 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Russian)

Currently translated at 88.6% (188 of 212 strings)

Translated using Weblate (Russian)

Currently translated at 88.2% (187 of 212 strings)

Translated using Weblate (Russian)

Currently translated at 88.2% (187 of 212 strings)

Translated using Weblate (Filipino)

Currently translated at 62.7% (1628 of 2593 strings)

Translated using Weblate (Indonesian)

Currently translated at 64.5% (131 of 203 strings)

Translated using Weblate (Russian)

Currently translated at 97.7% (2534 of 2593 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (15 of 15 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (French)

Currently translated at 100.0% (203 of 203 strings)

Translated using Weblate (French)

Currently translated at 100.0% (366 of 366 strings)

Translated using Weblate (French)

Currently translated at 100.0% (2593 of 2593 strings)

Translated using Weblate (French)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (French)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (French)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Japanese)

Currently translated at 99.0% (201 of 203 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2562 of 2593 strings)

Translated using Weblate (Dutch)

Currently translated at 90.4% (2346 of 2593 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (127 of 127 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (212 of 212 strings)

Translated using Weblate (Filipino)

Currently translated at 65.0% (1688 of 2593 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Korean)

Currently translated at 100.0% (111 of 111 strings)

Translated using Weblate (Korean)

Currently translated at 58.1% (118 of 203 strings)

Translated using Weblate (Korean)

Currently translated at 81.9% (77 of 94 strings)

Translated using Weblate (Korean)

Currently translated at 88.5% (324 of 366 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2558 of 2593 strings)

Translated using Weblate (Filipino)

Currently translated at 68.3% (1773 of 2593 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (220 of 220 strings)

Translated using Weblate (Turkish)

Currently translated at 88.2% (323 of 366 strings)

Translated using Weblate (Turkish)

Currently translated at 95.5% (172 of 180 strings)

Translated using Weblate (Russian)

Currently translated at 99.4% (179 of 180 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Turkish)

Currently translated at 71.6% (91 of 127 strings)

Translated using Weblate (Turkish)

Currently translated at 88.5% (116 of 131 strings)

Translated using Weblate (Turkish)

Currently translated at 88.5% (116 of 131 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (203 of 203 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (366 of 366 strings)

Translated using Weblate (Russian)

Currently translated at 98.8% (178 of 180 strings)

Translated using Weblate (Russian)

Currently translated at 98.9% (747 of 755 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (127 of 127 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (373 of 373 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2558 of 2593 strings)

Translated using Weblate (Russian)

Currently translated at 98.5% (744 of 755 strings)

Translated using Weblate (Russian)

Currently translated at 98.5% (744 of 755 strings)

Translated using Weblate (Dutch)

Currently translated at 94.7% (715 of 755 strings)

Translated using Weblate (Dutch)

Currently translated at 93.7% (119 of 127 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2558 of 2593 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Dutch)

Currently translated at 93.7% (708 of 755 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (203 of 203 strings)

Translated using Weblate (Dutch)

Currently translated at 97.5% (198 of 203 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (129 of 129 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (220 of 220 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (366 of 366 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (180 of 180 strings)

Translated using Weblate (Dutch)

Currently translated at 96.4% (54 of 56 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (373 of 373 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (98 of 98 strings)

Translated using Weblate (Dutch)

Currently translated at 94.5% (659 of 697 strings)

Translated using Weblate (Dutch)

Currently translated at 99.2% (130 of 131 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (94 of 94 strings)

Translated using Weblate (Latin)

Currently translated at 53.1% (117 of 220 strings)

Translated using Weblate (Filipino)

Currently translated at 66.9% (1737 of 2593 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (203 of 203 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (203 of 203 strings)

Co-authored-by: Agoston Merkovics <agome10x@lis-student.se>
Co-authored-by: Andreway <watermelontvandreway2@gmail.com>
Co-authored-by: Anfasa Rabbany <lelcraft96@gmail.com>
Co-authored-by: Benoit Hetru <me+hbtc@gahanka.net>
Co-authored-by: Chap <chalda82+nogravatar@gmail.com>
Co-authored-by: Céu <marcel.ufscar@gmail.com>
Co-authored-by: Dmitry <basdim21@gmail.com>
Co-authored-by: Hexe des Windes (she/her) <krausanna1@gmail.com>
Co-authored-by: Ike Osenberg <ike.osenberg@gmail.com>
Co-authored-by: John Collins <munmedia9865@gmail.com>
Co-authored-by: Justin Cho <jcho93@umd.edu>
Co-authored-by: KanI <twinklingnerd@gmail.com>
Co-authored-by: Lucifer <selmanreyhan@gmail.com>
Co-authored-by: Madeline Perray <maperray@gmail.com>
Co-authored-by: Mazer Time <mazer.time@gmail.com>
Co-authored-by: Moa Davou <moa.davou99@gmail.com>
Co-authored-by: Nazar Paruna <nazarparuna@gmail.com>
Co-authored-by: Omer I.S <omeritzicschwartz@gmail.com>
Co-authored-by: Razi H <razi.haj@gmail.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: Simon Coast <shimmumah@mailfence.com>
Co-authored-by: Teymur <timbl4@gmail.com>
Co-authored-by: Vince Vilan <vincemorel.vilan.889@my.csun.edu>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: YV <tiger_eye_9@hotmail.com>
Co-authored-by: Zarah Lundberg <sar_lun@hotmail.com>
Co-authored-by: blacksheep47 <1760906326@qq.com>
Co-authored-by: mattya 226 <worldworld1114@gmail.com>
Co-authored-by: Артём Вячеславович Холопов <holopow.art@yandex.ru>
Co-authored-by: Виктория Андриенко <hymera_555@mail.ru>
Co-authored-by: Естай <akseleu@yahoo.com>
Co-authored-by: そら <comi4work@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/he/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/it/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/sv/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/it/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/he/
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/character/he/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/content/he/
Translate-URL: https://translate.habitica.com/projects/habitica/content/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/content/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/content/sv/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/death/he/
Translate-URL: https://translate.habitica.com/projects/habitica/death/id/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/front/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/front/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/front/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/front/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/de/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ko/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/la/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/he/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/overview/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/he/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/ko/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/he/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/sv/
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/sv/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/de/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/id/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/it/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ko/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/he/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/nl/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Challenge
Translation: Habitica/Character
Translation: Habitica/Communityguidelines
Translation: Habitica/Content
Translation: Habitica/Contrib
Translation: Habitica/Death
Translation: Habitica/Faq
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Generic
Translation: Habitica/Groups
Translation: Habitica/Limited
Translation: Habitica/Loginincentives
Translation: Habitica/Npc
Translation: Habitica/Overview
Translation: Habitica/Pets
Translation: Habitica/Quests
Translation: Habitica/Questscontent
Translation: Habitica/Rebirth
Translation: Habitica/Settings
Translation: Habitica/Subscriber
Translation: Habitica/Tasks
2022-06-03 20:53:57 +02:00
dependabot[bot] 19c1484928 build(deps): bump amplitude-js from 8.17.0 to 8.18.4 in /website/client (#14034)
Bumps [amplitude-js](https://github.com/amplitude/amplitude-javascript) from 8.17.0 to 8.18.4.
- [Release notes](https://github.com/amplitude/amplitude-javascript/releases)
- [Changelog](https://github.com/amplitude/Amplitude-JavaScript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/amplitude/amplitude-javascript/compare/v8.17.0...v8.18.4)

---
updated-dependencies:
- dependency-name: amplitude-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:34:35 -04:00
dependabot[bot] 9f135782ef build(deps): bump vue-router from 3.5.3 to 3.5.4 in /website/client (#14027)
Bumps [vue-router](https://github.com/vuejs/router) from 3.5.3 to 3.5.4.
- [Release notes](https://github.com/vuejs/router/releases)
- [Changelog](https://github.com/vuejs/router/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/router/commits)

---
updated-dependencies:
- dependency-name: vue-router
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:30:51 -04:00
dependabot[bot] ad0907274b build(deps): bump @babel/preset-env from 7.17.10 to 7.18.2 (#14022)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.17.10 to 7.18.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.2/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:30:05 -04:00
dependabot[bot] 9eb959840b build(deps): bump @storybook/addon-actions in /website/client (#14028)
Bumps [@storybook/addon-actions](https://github.com/storybookjs/storybook/tree/HEAD/addons/actions) from 6.4.19 to 6.5.6.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.6/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.6/addons/actions)

---
updated-dependencies:
- dependency-name: "@storybook/addon-actions"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:26:24 -04:00
dependabot[bot] 7d11b22da0 build(deps): bump @storybook/addon-links in /website/client (#14025)
Bumps [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/addons/links) from 6.4.18 to 6.5.6.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.6/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.6/addons/links)

---
updated-dependencies:
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:26:00 -04:00
dependabot[bot] f3495ba4e1 build(deps): bump jwks-rsa from 2.1.2 to 2.1.3 (#13985)
Bumps [jwks-rsa](https://github.com/auth0/node-jwks-rsa) from 2.1.2 to 2.1.3.
- [Release notes](https://github.com/auth0/node-jwks-rsa/releases)
- [Changelog](https://github.com/auth0/node-jwks-rsa/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jwks-rsa/compare/v2.1.2...v2.1.3)

---
updated-dependencies:
- dependency-name: jwks-rsa
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:25:10 -04:00
dependabot[bot] dd978b664b build(deps): bump passport from 0.5.0 to 0.6.0 (#13987)
Bumps [passport](https://github.com/jaredhanson/passport) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/jaredhanson/passport/releases)
- [Changelog](https://github.com/jaredhanson/passport/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jaredhanson/passport/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: passport
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:24:41 -04:00
dependabot[bot] 84011f36b2 build(deps): bump moment from 2.29.1 to 2.29.3 in /website/client (#13994)
Bumps [moment](https://github.com/moment/moment) from 2.29.1 to 2.29.3.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/2.29.3/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.1...2.29.3)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:24:17 -04:00
dependabot[bot] b9389f8430 build(deps): bump intro.js from 5.0.0 to 5.1.0 in /website/client (#13999)
Bumps [intro.js](https://github.com/usablica/intro.js) from 5.0.0 to 5.1.0.
- [Release notes](https://github.com/usablica/intro.js/releases)
- [Commits](https://github.com/usablica/intro.js/compare/v5.0.0...v5.1.0)

---
updated-dependencies:
- dependency-name: intro.js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:23:55 -04:00
dependabot[bot] 266ea01bc8 build(deps): bump @vue/cli-plugin-eslint in /website/client (#14000)
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.15 to 4.5.17.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.17/packages/@vue/cli-plugin-eslint)

---
updated-dependencies:
- dependency-name: "@vue/cli-plugin-eslint"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:23:35 -04:00
dependabot[bot] c170edae92 build(deps): bump bootstrap-vue from 2.21.2 to 2.22.0 in /website/client (#14002)
Bumps [bootstrap-vue](https://github.com/bootstrap-vue/bootstrap-vue) from 2.21.2 to 2.22.0.
- [Release notes](https://github.com/bootstrap-vue/bootstrap-vue/releases)
- [Changelog](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.21.2...v2.22.0)

---
updated-dependencies:
- dependency-name: bootstrap-vue
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:23:13 -04:00
dependabot[bot] 324076438c build(deps): bump core-js from 3.21.0 to 3.22.7 in /website/client (#14004)
Bumps [core-js](https://github.com/zloirock/core-js) from 3.21.0 to 3.22.7.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.21.0...v3.22.7)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:22:30 -04:00
dependabot[bot] 77791e186f build(deps-dev): bump @babel/plugin-proposal-optional-chaining (#14009)
Bumps [@babel/plugin-proposal-optional-chaining](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-optional-chaining) from 7.16.7 to 7.17.12.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.12/packages/babel-plugin-proposal-optional-chaining)

---
updated-dependencies:
- dependency-name: "@babel/plugin-proposal-optional-chaining"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:19:40 -04:00
dependabot[bot] b3a9e79f0d build(deps): bump smartbanner.js in /website/client (#14011)
Bumps [smartbanner.js](https://github.com/ain/smartbanner.js) from 1.17.0 to 1.19.0.
- [Release notes](https://github.com/ain/smartbanner.js/releases)
- [Commits](https://github.com/ain/smartbanner.js/compare/v1.17.0...v1.19.0)

---
updated-dependencies:
- dependency-name: smartbanner.js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-03 14:18:56 -04:00
SabreCat ce67f06bab fix(chat): test expectation, short circuit if no group 2022-06-02 16:43:14 -05:00
SabreCat 219bdc088b feat(chat): don't check for slurs in private chats 2022-06-02 16:16:40 -05:00
dependabot[bot] ac972fb481 build(deps): bump eventsource from 1.1.0 to 1.1.1 in /website/client (#14031)
Bumps [eventsource](https://github.com/EventSource/eventsource) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/EventSource/eventsource/releases)
- [Changelog](https://github.com/EventSource/eventsource/blob/master/HISTORY.md)
- [Commits](https://github.com/EventSource/eventsource/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: eventsource
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-01 15:41:31 -04:00
SabreCat 5a0813fe7f fix(lint): line length 2022-05-31 15:34:44 -05:00
SabreCat d3673349a9 Merge branch 'release' into develop 2022-05-31 13:58:07 -05:00
SabreCat 8125bea89f 4.232.1 2022-05-31 10:38:29 -05:00
SabreCat e16c12fc7f Revert "Gifting Modal Redesign (#13964)"
This reverts commit 761d70ec55.
2022-05-31 10:38:14 -05:00
SabreCat 90e03653ce 4.232.0 2022-05-30 15:58:29 -05:00
Natalie L dd5066ab72 2022-06 Subscriber Items (#14016)
* 2022-06 Subscriber Items

* chore(mystery): compile sprites, tidy up whitespace

Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-30 15:56:50 -05:00
Tressley Cahill ec0be8d91f Adjust z-index for notifications
Fixes #14015
2022-05-25 11:09:43 -04:00
SabreCat 331c64a83a Merge branch 'release' into develop 2022-05-24 09:38:40 -05:00
SabreCat f8c6a859bf 4.231.0 2022-05-24 09:37:35 -05:00
Natalie L 8040d14c28 code for reptacular rumble achievement (#13981) 2022-05-23 15:39:51 -05:00
SabreCat 8358da227d fix(quests): hide offseason quests, again
Also tidy up some Reptacular Rumble issues
2022-05-23 15:38:16 -05:00
SabreCat 74b59d2324 chore(packages): lock cleanup 2022-05-23 14:59:15 -05:00
CuriousMagpie 5fa705c390 code for reptacular rumble achievement 2022-05-23 14:58:17 -05:00
SabreCat 5bcfdbe066 fix(login): catch double-slash exploit 2022-05-20 14:29:15 -05:00
dependabot[bot] 0e7f98ad14 build(deps): bump jwks-rsa from 2.1.1 to 2.1.2 (#13976)
Bumps [jwks-rsa](https://github.com/auth0/node-jwks-rsa) from 2.1.1 to 2.1.2.
- [Release notes](https://github.com/auth0/node-jwks-rsa/releases)
- [Changelog](https://github.com/auth0/node-jwks-rsa/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jwks-rsa/compare/v2.1.1...v2.1.2)

---
updated-dependencies:
- dependency-name: jwks-rsa
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-19 15:43:21 -05:00
Vanathi G 9ba0bd7c06 Keys to kennel issue (#13978)
* Fix selection highlight in avatar editor

* Fix error message on using Keys to the Kennel
2022-05-19 15:37:15 -05:00
dependabot[bot] 5d78fce468 build(deps): bump glob from 8.0.1 to 8.0.3 (#13974)
Bumps [glob](https://github.com/isaacs/node-glob) from 8.0.1 to 8.0.3.
- [Release notes](https://github.com/isaacs/node-glob/releases)
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v8.0.1...v8.0.3)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-19 15:33:41 -05:00
Sabe Jones 31385b3e7b fix(auth): take best guess when multiple accts with same email (#13980)
Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-19 15:32:03 -05:00
SabreCat 1863a965c7 4.230.3 2022-05-19 14:55:09 -05:00
Weblate 1f2c926a54 Translated using Weblate (Japanese)
Currently translated at 98.5% (200 of 203 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (Latin)

Currently translated at 19.4% (35 of 180 strings)

Translated using Weblate (Latin)

Currently translated at 99.2% (130 of 131 strings)

Translated using Weblate (Latin)

Currently translated at 87.5% (7 of 8 strings)

Translated using Weblate (Latin)

Currently translated at 42.3% (47 of 111 strings)

Translated using Weblate (Latin)

Currently translated at 42.3% (47 of 111 strings)

Translated using Weblate (Latin)

Currently translated at 19.4% (35 of 180 strings)

Translated using Weblate (Latin)

Currently translated at 98.3% (60 of 61 strings)

Translated using Weblate (Italian)

Currently translated at 99.0% (201 of 203 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (366 of 366 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (366 of 366 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Japanese)

Currently translated at 99.7% (695 of 697 strings)

Translated using Weblate (English (United Kingdom))

Currently translated at 97.7% (128 of 131 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Croatian)

Currently translated at 12.6% (14 of 111 strings)

Co-authored-by: Altariel <altariel.habitica@gmail.com>
Co-authored-by: Simon Coast <shimmumah@mailfence.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: mattya 226 <worldworld1114@gmail.com>
Co-authored-by: xioxi <potentiallytyler@gmail.com>
Co-authored-by: そら <comi4work@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en_GB/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/la/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/front/la/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/it/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/la/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/la/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/la/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/it/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Faq
Translation: Habitica/Front
Translation: Habitica/Groups
Translation: Habitica/Inventory
Translation: Habitica/Messages
Translation: Habitica/Pets
Translation: Habitica/Questscontent
Translation: Habitica/Subscriber
2022-05-19 17:49:48 +02:00
SabreCat e7f60cb68f fix(achievements): TigerCub not Tiger, sigh 2022-05-18 14:43:10 -05:00
SabreCat d1cb86a428 revert package updates 2022-05-18 14:40:35 -05:00
SabreCat 6f6c981c92 chore(packages): update gulp.spritesmith and istanbul 2022-05-17 15:56:37 -05:00
Weblate 63bb2b31bc Merge branch 'origin/develop' into Weblate. 2022-05-17 16:41:00 +02:00
Weblate b42ac207b2 Translated using Weblate (Croatian)
Currently translated at 19.8% (26 of 131 strings)

Translated using Weblate (Filipino)

Currently translated at 66.2% (1718 of 2593 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (134 of 134 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (2593 of 2593 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2558 of 2593 strings)

Translated using Weblate (Filipino)

Currently translated at 65.1% (1690 of 2593 strings)

Translated using Weblate (Japanese)

Currently translated at 99.8% (2589 of 2593 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2558 of 2593 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 96.7% (674 of 697 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (697 of 697 strings)

Translated using Weblate (Croatian)

Currently translated at 68.5% (37 of 54 strings)

Translated using Weblate (Filipino)

Currently translated at 62.6% (1625 of 2593 strings)

Translated using Weblate (Croatian)

Currently translated at 38.8% (21 of 54 strings)

Translated using Weblate (Filipino)

Currently translated at 62.9% (1632 of 2593 strings)

Co-authored-by: Céu <marcel.ufscar@gmail.com>
Co-authored-by: Ike Osenberg <ike.osenberg@gmail.com>
Co-authored-by: JMFO16 <fournier.olivera.jm@gmail.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: Vince Vilan <vincemorel.vilan.889@my.csun.edu>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: mattya 226 <worldworld1114@gmail.com>
Co-authored-by: xioxi <potentiallytyler@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/it/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/es_419/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Defaulttasks
Translation: Habitica/Gear
Translation: Habitica/Tasks
2022-05-17 16:35:38 +02:00
SabreCat c0e22377d1 Merge branch 'release' into develop 2022-05-17 09:33:45 -05:00
SabreCat 5a13231027 4.230.2 2022-05-17 09:33:34 -05:00
Natalie L 4e78d72cee May 2022 Magic Hatching Potions and Quest Bundle (#13979)
* May 2022 magic hatching potions and quest bundle

* fix(string): typo

* fix(content): add and use event

Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-17 09:32:50 -05:00
SabreCat 980e35880f fix(login): sanitize redirect 2022-05-16 15:36:09 -05:00
Megan Searles 5bc544c481 for locking items in market, special overrides available set. fixes #13798 (#13817)
* for locking items, special overrides available

* fix(market): allow purchase of broken item

Co-authored-by: Megan Shepherd <meg.d.shep@gmail.com>
Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-13 16:11:49 -05:00
SabreCat 1a74d2b3b0 refactor(achievements): crush down to much fewer notification types
most work by @CuriousMagpie
2022-05-12 15:25:40 -05:00
John Li d132b057eb Fix XML Data Export Error by Modifying XML Format (#13942)
* Added XML code to parse json + convert formatting before exporting as XML + XML Marshall tests

* Add linting fixes

linting errors still present in xmlMarshaller.test.js but, certain keys starting with digits (for example '800ed0') must be enclosed in quotes , so to maintain consistency within the test file I kept all keys enclosed by single quotes.

* fix(lint): unquote, EOF

Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-12 15:24:17 -05:00
Natalie L 761d70ec55 Gifting Modal Redesign (#13964)
* update selectUserModal.vue

* more updates to selectUserModal.vue, typo fix in subscriber.json

* remove exact sizing for selectUserModal.vue

* update to size for selectUserModal.vue

* added sendGiftModal.vue file

* updates to selectUser & sendGift modals

* making the modals go & position cursor

* working working working

* added a return to method

* avatar display & placeholder profile.name and username

* subscription-options added

* added menu row & started on gem options

* Added selectPage function, have not tested.

* updated habitica-images

* state changes

* bringing in gem counter

* arranging elements

* state changes, gem input boxes

* styling sendGiftModal.vue

* more sendGiftModal.vue styling and new close.svg icon

* more styling!

* and more styling of send own gems part of page

* images update

* more styling of own gems & some attempts to adjust :class on the menu

* styling styling styling

* replace +/- svg, styling

* styling, mostly

* new SVGs

* stylin'

* reverting svg changes

* no more stylin'

* finally got the +/- icons to show up...but they're the wrong color

* solved svg icon color problem! :)

* habitica-images

* working on sendGift part of button

* trying to make it do math, failing

* more attempts at math

* +/- buttons work on gem pages & cost calculation on buyGems

* trying to get hover colors working on +/- svgs

* formatted dollar amount as currency

* css/html for subscription-options & payments-buttons simplified

* swag at payments-buttons parameter (not tested)

* send gems from own balance works!

* working on starting page

* increment gem amount limited to maxGems and not < 0

* uncommented onHide()

* got bg color on sub options to work! yay!

* payment buttons!

* making g1g1 look good

* position modal on page properly & code clean-up

* Changes as requested!

* small color update

* fixed ternary function

* chore(html): indentation and comments

* fix(fn): correct catch for under-0

* chore(json): whitespace

Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-12 15:14:56 -05:00
Sabe Jones a0de2dab49 fix(tasks): don't send delta around as an array (#13967)
Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-12 14:56:05 -05:00
SabreCat aa2458d564 4.230.1 2022-05-12 13:55:59 -05:00
Weblate a1a3022392 Translated using Weblate (Japanese)
Currently translated at 99.6% (2585 of 2593 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2558 of 2593 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (690 of 690 strings)

Translated using Weblate (Lithuanian)

Currently translated at 6.8% (9 of 131 strings)

Translated using Weblate (Filipino)

Currently translated at 64.8% (1681 of 2593 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (220 of 220 strings)

Translated using Weblate (Ukrainian)

Currently translated at 78.9% (2048 of 2593 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (2593 of 2593 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2558 of 2593 strings)

Translated using Weblate (Ukrainian)

Currently translated at 93.3% (168 of 180 strings)

Translated using Weblate (Korean)

Currently translated at 90.1% (193 of 214 strings)

Translated using Weblate (Filipino)

Currently translated at 65.9% (1709 of 2593 strings)

Translated using Weblate (Korean)

Currently translated at 31.6% (57 of 180 strings)

Translated using Weblate (Korean)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Spanish)

Currently translated at 98.6% (2558 of 2593 strings)

Co-authored-by: Elena Balionyte <ziuze15spam@gmail.com>
Co-authored-by: Ike Osenberg <ike.osenberg@gmail.com>
Co-authored-by: Jerry Chen <minecjraft@qq.com>
Co-authored-by: Justin Cho <jcho93@umd.edu>
Co-authored-by: Nazar Paruna <nazarparuna@gmail.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: Vince Vilan <vincemorel.vilan.889@my.csun.edu>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: mattya 226 <worldworld1114@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/lt/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/character/ko/
Translate-URL: https://translate.habitica.com/projects/habitica/front/ko/
Translate-URL: https://translate.habitica.com/projects/habitica/front/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ko/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/uk/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Character
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Generic
Translation: Habitica/Limited
2022-05-12 20:48:18 +02:00
dependabot[bot] 91fdeb0e51 build(deps): bump jwks-rsa from 2.1.0 to 2.1.1 (#13972)
Bumps [jwks-rsa](https://github.com/auth0/node-jwks-rsa) from 2.1.0 to 2.1.1.
- [Release notes](https://github.com/auth0/node-jwks-rsa/releases)
- [Changelog](https://github.com/auth0/node-jwks-rsa/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jwks-rsa/compare/v2.1.0...v2.1.1)

---
updated-dependencies:
- dependency-name: jwks-rsa
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-11 12:13:36 -04:00
dependabot[bot] 3a8fbbe394 build(deps): bump stripe from 8.219.0 to 8.222.0 (#13970)
Bumps [stripe](https://github.com/stripe/stripe-node) from 8.219.0 to 8.222.0.
- [Release notes](https://github.com/stripe/stripe-node/releases)
- [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-node/compare/v8.219.0...v8.222.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-11 12:13:20 -04:00
SabreCat bc1708be14 Merge branch 'release' into develop 2022-05-10 13:57:33 -05:00
Weblate 75ce44e6d9 Translated using Weblate (Filipino)
Currently translated at 66.1% (1715 of 2593 strings)

Translated using Weblate (Japanese)

Currently translated at 99.8% (2583 of 2587 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2558 of 2587 strings)

Translated using Weblate (Filipino)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Filipino)

Currently translated at 66.1% (1711 of 2587 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2558 of 2587 strings)

Translated using Weblate (Filipino)

Currently translated at 96.1% (126 of 131 strings)

Translated using Weblate (German)

Currently translated at 100.0% (198 of 198 strings)

Translated using Weblate (German)

Currently translated at 99.9% (2585 of 2587 strings)

Translated using Weblate (Filipino)

Currently translated at 90.8% (119 of 131 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2558 of 2587 strings)

Translated using Weblate (Russian)

Currently translated at 98.1% (677 of 690 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Filipino)

Currently translated at 66.0% (1708 of 2587 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2558 of 2587 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Filipino)

Currently translated at 66.0% (1708 of 2587 strings)

Translated using Weblate (Filipino)

Currently translated at 65.8% (1704 of 2587 strings)

Translated using Weblate (German)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (German)

Currently translated at 100.0% (690 of 690 strings)

Co-authored-by: Anton Kapustinsky <anton.kap02@mail.ru>
Co-authored-by: Ike Osenberg <ike.osenberg@gmail.com>
Co-authored-by: Mara S. (Dolichotis) <marascherzer@gmail.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: Vince Vilan <vincemorel.vilan.889@my.csun.edu>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: mattya 226 <worldworld1114@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/de/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/it/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/de/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Contrib
Translation: Habitica/Gear
Translation: Habitica/Questscontent
Translation: Habitica/Subscriber
2022-05-10 14:02:46 +02:00
Natalie L d317bd1c41 May 2022 Backgrounds and Enchanted Armoire (#13966)
* 2022-05 backgrounds and enchanted armoire images

* 2022-05 backgrounds and enchanted

* chore(sprites): compile
also fix a few string typos

Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-09 14:21:25 -05:00
Alys 1a920d6e17 Hall of Heroes / Contributors: fix hasPermissions bug, merge Name and User ID columns (#13968)
* fix bug in hasPermissions call to stop normal users seeing UserID column

* merge User ID column into Name column in Hall of Heroes
2022-05-09 13:55:52 -05:00
Natalie L 5e12b7b042 Fix: Inconsistent Quest Unlock Behavior (#13734)
* remove quest refactoring, created new branch for that task

* remove quest refactoring, created new branch for that task

* More trying to figure out how buying a quest actually works

* rolling back changes

* updated shops/quests/index.vue to disable clicking on locked quests

* removed console.log(item)

* misc fixes per review comments

* changes as requested

* incorporated quest refactors updates

* removing a couple lines of code
2022-05-05 16:51:47 -05:00
Skander KRATOU de4ebbac7b Habit streak Fix (#13947)
* Fixes Issue13749

* If a value is at 0 the other value won't show a +/-

* Fix for the negative habits

* Fix : Habits values will always have signs except if the habit is one sided or the values are null

* fix(tasks): tighten margen when 0 as well

Co-authored-by: SabreCat <sabe@habitica.com>
2022-05-05 16:50:50 -05:00
dependabot[bot] ea3b27ff17 build(deps): bump @babel/preset-env from 7.16.11 to 7.17.10 (#13960)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.11 to 7.17.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.10/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-05 15:54:30 -04:00
dependabot[bot] 8c3c4c1d49 build(deps): bump express from 4.17.3 to 4.18.1 (#13961)
Bumps [express](https://github.com/expressjs/express) from 4.17.3 to 4.18.1.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.3...4.18.1)

---
updated-dependencies:
- dependency-name: express
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-05 15:53:59 -04:00
dependabot[bot] 50577fa39b build(deps): bump remove-markdown from 0.3.0 to 0.5.0 (#13962)
Bumps [remove-markdown](https://github.com/stiang/remove-markdown) from 0.3.0 to 0.5.0.
- [Release notes](https://github.com/stiang/remove-markdown/releases)
- [Commits](https://github.com/stiang/remove-markdown/commits)

---
updated-dependencies:
- dependency-name: remove-markdown
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-05 15:53:21 -04:00
dependabot[bot] 30c4dd86df build(deps-dev): bump axios from 0.26.1 to 0.27.2 (#13959)
Bumps [axios](https://github.com/axios/axios) from 0.26.1 to 0.27.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.26.1...v0.27.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-05 15:52:56 -04:00
Weblate f9857efbac Merge branch 'origin/develop' into Weblate. 2022-05-05 20:57:21 +02:00
Weblate 1a7b264958 Translated using Weblate (French)
Currently translated at 100.0% (198 of 198 strings)

Translated using Weblate (French)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (198 of 198 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 96.9% (2507 of 2587 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2558 of 2587 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (127 of 127 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 96.5% (2499 of 2587 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 96.5% (2499 of 2587 strings)

Translated using Weblate (Filipino)

Currently translated at 65.8% (1703 of 2587 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 97.7% (738 of 755 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (198 of 198 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (198 of 198 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.0% (2537 of 2587 strings)

Translated using Weblate (Filipino)

Currently translated at 65.6% (1698 of 2587 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 97.0% (733 of 755 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 95.3% (2466 of 2587 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 95.3% (2466 of 2587 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 92.9% (118 of 127 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 96.6% (205 of 212 strings)

Translated using Weblate (Japanese)

Currently translated at 99.8% (2583 of 2587 strings)

Translated using Weblate (Spanish)

Currently translated at 98.8% (2558 of 2587 strings)

Translated using Weblate (Filipino)

Currently translated at 65.4% (1694 of 2587 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 94.8% (2454 of 2587 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (180 of 180 strings)

Translated using Weblate (Filipino)

Currently translated at 100.0% (15 of 15 strings)

Translated using Weblate (Filipino)

Currently translated at 87.3% (97 of 111 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 94.7% (2450 of 2587 strings)

Translated using Weblate (German)

Currently translated at 99.8% (2584 of 2587 strings)

Translated using Weblate (German)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (French)

Currently translated at 100.0% (2587 of 2587 strings)

Translated using Weblate (French)

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Ukrainian)

Currently translated at 82.6% (105 of 127 strings)

Translated using Weblate (Filipino)

Currently translated at 76.5% (85 of 111 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (365 of 365 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (2587 of 2587 strings)

Translated using Weblate (Filipino)

Currently translated at 69.3% (77 of 111 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 94.4% (2440 of 2583 strings)

Co-authored-by: Benoit Hetru <me+hbtc@gahanka.net>
Co-authored-by: Céu <marcel.ufscar@gmail.com>
Co-authored-by: Erick Diego Castillo Chavez <erick.diego.c.c@gmail.com>
Co-authored-by: Heitor Menezes Gomes <heitorgmenezes@gmail.com>
Co-authored-by: Hexe des Windes (she/her) <krausanna1@gmail.com>
Co-authored-by: Ike Osenberg <ike.osenberg@gmail.com>
Co-authored-by: JoanZeppeli <x17501668978@163.com>
Co-authored-by: José Wellington Carneiro <wellingtonjco@gmail.com>
Co-authored-by: Kedr <sergeysamori.ua@gmail.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: Vince Vilan <vincemorel.vilan.889@my.csun.edu>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: mattya 226 <worldworld1114@gmail.com>
Co-authored-by: そら <comi4work@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es_419/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/death/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/front/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es_419/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/it/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/
Translation: Habitica/Communityguidelines
Translation: Habitica/Contrib
Translation: Habitica/Death
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Groups
Translation: Habitica/Pets
Translation: Habitica/Questscontent
Translation: Habitica/Settings
Translation: Habitica/Subscriber
2022-05-05 20:57:10 +02:00
324 changed files with 8231 additions and 5647 deletions
+1
View File
@@ -1,4 +1,5 @@
{
"ACCOUNT_MIN_CHAT_AGE": "0",
"ADMIN_EMAIL": "you@example.com",
"AMAZON_PAYMENTS_CLIENT_ID": "CLIENT_ID",
"AMAZON_PAYMENTS_MODE": "sandbox",
@@ -119,7 +119,7 @@ function path(obj, path, def) {
* @param {String} path dot separated
* @param {*} def default value ( if result undefined )
* @returns {*}
* http://stackoverflow.com/a/16190716
* https://stackoverflow.com/a/16190716
* Usage: console.log(path(someObject, pathname));
*/
for(var i = 0,path = path.split('.'),len = path.length; i < len; i++){
@@ -2,7 +2,7 @@
// TODO it might be better we just find() and save() all user objects using mongoose, and rely on our defined pre('save')
// and default values to "migrate" users. This way we can make sure those parts are working properly too
// @see http://stackoverflow.com/questions/14867697/mongoose-full-collection-scan
// @see https://stackoverflow.com/questions/14867697/mongoose-full-collection-scan
// Also, what do we think of a Mongoose Migration module? something like https://github.com/madhums/mongoose-migrate
// IMPORTANT NOTE: this migration was written when we were using version 3 of lodash.
@@ -19,7 +19,7 @@ const Timer = require('./utils/timer');
const connectToDb = require('./utils/connect').connectToDb;
const closeDb = require('./utils/connect').closeDb;
const message = '`This party\'s collection quest has been made easier! For details, refer to http://habitica.fandom.com/wiki/User_blog:LadyAlys/Collection_Quests_are_Now_Easier`';
const message = '`This party\'s collection quest has been made easier! For details, refer to https://habitica.fandom.com/wiki/User_blog:LadyAlys/Collection_Quests_are_Now_Easier`';
const timer = new Timer();
@@ -0,0 +1,128 @@
/* eslint-disable no-console */
const MIGRATION_NAME = '20220524_pet_group_achievements';
import { model as User } from '../../../website/server/models/user';
const progressCount = 1000;
let count = 0;
async function updateUser (user) {
count++;
const set = {
migration: MIGRATION_NAME,
};
if (user && user.items && user.items.pets) {
const pets = user.items.pets;
if (pets['Alligator-Base']
&& pets['Alligator-CottonCandyBlue']
&& pets['Alligator-CottonCandyPink']
&& pets['Alligator-Desert']
&& pets['Alligator-Golden']
&& pets['Alligator-Red']
&& pets['Alligator-Shade']
&& pets['Alligator-Skeleton']
&& pets['Alligator-White']
&& pets['Alligator-Zombie']
&& pets['Snake-Base']
&& pets['Snake-CottonCandyBlue']
&& pets['Snake-CottonCandyPink']
&& pets['Snake-Desert']
&& pets['Snake-Golden']
&& pets['Snake-Red']
&& pets['Snake-Shade']
&& pets['Snake-Skeleton']
&& pets['Snake-White']
&& pets['Snake-Zombie']
&& pets['Triceratops-Base']
&& pets['Triceratops-CottonCandyBlue']
&& pets['Triceratops-CottonCandyPink']
&& pets['Triceratops-Desert']
&& pets['Triceratops-Golden']
&& pets['Triceratops-Red']
&& pets['Triceratops-Shade']
&& pets['Triceratops-Skeleton']
&& pets['Triceratops-White']
&& pets['Triceratops-Zombie']
&& pets['TRex-Base']
&& pets['TRex-CottonCandyBlue']
&& pets['TRex-CottonCandyPink']
&& pets['TRex-Desert']
&& pets['TRex-Golden']
&& pets['TRex-Red']
&& pets['TRex-Shade']
&& pets['TRex-Skeleton']
&& pets['TRex-White']
&& pets['TRex-Zombie']
&& pets['Pterodactyl-Base']
&& pets['Pterodactyl-CottonCandyBlue']
&& pets['Pterodactyl-CottonCandyPink']
&& pets['Pterodactyl-Desert']
&& pets['Pterodactyl-Golden']
&& pets['Pterodactyl-Red']
&& pets['Pterodactyl-Shade']
&& pets['Pterodactyl-Skeleton']
&& pets['Pterodactyl-White']
&& pets['Pterodactyl-Zombie']
&& pets['Turtle-Base']
&& pets['Turtle-CottonCandyBlue']
&& pets['Turtle-CottonCandyPink']
&& pets['Turtle-Desert']
&& pets['Turtle-Golden']
&& pets['Turtle-Red']
&& pets['Turtle-Shade']
&& pets['Turtle-Skeleton']
&& pets['Turtle-White']
&& pets['Turtle-Zombie']
&& pets['Velociraptor-Base']
&& pets['Velociraptor-CottonCandyBlue']
&& pets['Velociraptor-CottonCandyPink']
&& pets['Velociraptor-Desert']
&& pets['Velociraptor-Golden']
&& pets['Velociraptor-Red']
&& pets['Velociraptor-Shade']
&& pets['Velociraptor-Skeleton']
&& pets['Velociraptor-White']
&& pets['Velociraptor-Zombie']) {
set['achievements.reptacularRumble'] = true;
}
}
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return await User.update({ _id: user._id }, { $set: set }).exec();
}
export default async function processUsers () {
let query = {
// migration: { $ne: MIGRATION_NAME },
'auth.timestamps.loggedin': { $gt: new Date('2022-01-01') },
};
const fields = {
_id: 1,
items: 1,
};
while (true) { // eslint-disable-line no-constant-condition
const users = await User // eslint-disable-line no-await-in-loop
.find(query)
.limit(250)
.sort({_id: 1})
.select(fields)
.lean()
.exec();
if (users.length === 0) {
console.warn('All appropriate users found and modified.');
console.warn(`\n${count} users processed\n`);
break;
} else {
query._id = {
$gt: users[users.length - 1]._id,
};
}
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
}
};
+1 -1
View File
@@ -16,7 +16,7 @@ AWS.config.update({
const BUCKET_NAME = config.S3.bucket;
const s3 = new AWS.S3();
// Adapted from http://stackoverflow.com/a/22210077/2601552
// Adapted from https://stackoverflow.com/a/22210077/2601552
function uploadFile (buffer, fileName) {
return new Promise((resolve, reject) => {
s3.putObject({
@@ -2,7 +2,7 @@
// For some reason people often to contact me to cancel their sub,
// rather than do it online. Even when I point them to
// the FAQ (http://goo.gl/1uoPGQ) they insist...
// the FAQ (https://habitica.fandom.com/wiki/FAQ) they insist...
db.users.update(
{ _id: '' },
+1246 -1270
View File
File diff suppressed because it is too large Load Diff
+16 -16
View File
@@ -1,19 +1,19 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
"version": "4.230.0",
"version": "4.238.0",
"main": "./website/server/index.js",
"dependencies": {
"@babel/core": "^7.17.10",
"@babel/preset-env": "^7.16.11",
"@babel/register": "^7.17.7",
"@babel/core": "^7.18.6",
"@babel/preset-env": "^7.18.6",
"@babel/register": "^7.18.6",
"@google-cloud/trace-agent": "^5.1.6",
"@parse/node-apn": "^5.1.3",
"@slack/webhook": "^6.1.0",
"accepts": "^1.3.8",
"amazon-payments": "^0.2.9",
"amplitude": "^6.0.0",
"apidoc": "^0.51.1",
"apidoc": "^0.52.0",
"apple-auth": "^1.0.7",
"bcrypt": "^5.0.1",
"body-parser": "^1.20.0",
@@ -27,27 +27,27 @@
"eslint": "^6.8.0",
"eslint-config-habitrpg": "^6.2.0",
"eslint-plugin-mocha": "^5.0.0",
"express": "^4.17.3",
"express": "^4.18.1",
"express-basic-auth": "^1.2.1",
"express-validator": "^5.2.0",
"glob": "^8.0.1",
"glob": "^8.0.3",
"got": "^11.8.3",
"gulp": "^4.0.0",
"gulp-babel": "^8.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-nodemon": "^2.5.0",
"gulp.spritesmith": "^6.12.1",
"gulp.spritesmith": "^6.13.0",
"habitica-markdown": "^3.0.0",
"helmet": "^4.6.0",
"image-size": "^1.0.1",
"image-size": "^1.0.2",
"in-app-purchase": "^1.11.3",
"js2xmlparser": "^4.0.2",
"jsonwebtoken": "^8.5.1",
"jwks-rsa": "^2.1.0",
"jwks-rsa": "^2.1.4",
"lodash": "^4.17.21",
"merge-stream": "^2.0.0",
"method-override": "^3.0.0",
"moment": "^2.29.3",
"moment": "^2.29.4",
"moment-recur": "^1.0.7",
"mongoose": "^5.13.7",
"morgan": "^1.10.0",
@@ -64,17 +64,17 @@
"rate-limiter-flexible": "^2.3.7",
"redis": "^3.1.2",
"regenerator-runtime": "^0.13.9",
"remove-markdown": "^0.3.0",
"remove-markdown": "^0.5.0",
"rimraf": "^3.0.2",
"short-uuid": "^4.2.0",
"stripe": "^8.219.0",
"superagent": "^7.1.3",
"stripe": "^8.222.0",
"superagent": "^7.1.6",
"universal-analytics": "^0.5.3",
"useragent": "^2.1.9",
"uuid": "^8.3.2",
"validator": "^13.7.0",
"vinyl-buffer": "^1.0.1",
"winston": "^3.7.2",
"winston": "^3.8.1",
"winston-loggly-bulk": "^3.2.1",
"xml2js": "^0.4.23"
},
@@ -110,7 +110,7 @@
"apidoc": "gulp apidoc"
},
"devDependencies": {
"axios": "^0.26.1",
"axios": "^0.27.2",
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"chai-moment": "^0.1.0",
@@ -326,6 +326,36 @@ describe('Google Payments', () => {
});
});
it('should cancel a user subscription with multiple inactive subscriptions', async () => {
const laterDate = moment.utc().add(7, 'days');
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{ expirationDate, autoRenewing: false },
{ expirationDate: laterDate, autoRenewing: false },
]);
await googlePayments.cancelSubscribe(user, headers);
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledWith(iap.GOOGLE, {
data: receipt,
signature,
});
expect(iapIsValidatedStub).to.be.calledOnce;
expect(iapIsValidatedStub).to.be.calledWith({
expirationDate,
});
expect(iapGetPurchaseDataStub).to.be.calledOnce;
expect(paymentCancelSubscriptionSpy).to.be.calledOnce;
expect(paymentCancelSubscriptionSpy).to.be.calledWith({
user,
paymentMethod: googlePayments.constants.PAYMENT_METHOD_GOOGLE,
nextBill: laterDate.toDate(),
headers,
});
});
it('should not cancel a user subscription with autorenew', async () => {
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
@@ -346,5 +376,28 @@ describe('Google Payments', () => {
expect(paymentCancelSubscriptionSpy).to.not.be.called;
});
it('should not cancel a user subscription with multiple subscriptions with one autorenew', async () => {
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{ expirationDate, autoRenewing: false },
{ autoRenewing: true },
{ expirationDate, autoRenewing: false }]);
await googlePayments.cancelSubscribe(user, headers);
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledWith(iap.GOOGLE, {
data: receipt,
signature,
});
expect(iapIsValidatedStub).to.be.calledOnce;
expect(iapIsValidatedStub).to.be.calledWith({
expirationDate,
});
expect(iapGetPurchaseDataStub).to.be.calledOnce;
expect(paymentCancelSubscriptionSpy).to.not.be.called;
});
});
});
+106
View File
@@ -42,3 +42,109 @@ describe('xml marshaller marshalls user data', () => {
</user>`);
});
});
describe('xml marshaller marshalls user data (with purchases)', () => {
const minimumUser = {
pinnedItems: [],
unpinnedItems: [],
inbox: {},
};
function userDataWith (fields) {
return { ...minimumUser, ...fields };
}
it('maps the purchases field with data that begins with a number', () => {
const userData = userDataWith({
purchased: {
ads: false,
txnCount: 0,
skin: {
eb052b: true,
'0ff591': true,
'2b43f6': true,
d7a9f7: true,
'800ed0': true,
rainbow: true,
},
},
});
const xml = xmlMarshaller.marshallUserData(userData);
expect(xml).to.equal(`<user>
<inbox/>
<purchased>
<ads>false</ads>
<txnCount>0</txnCount>
<skin>eb052b</skin>
<skin>0ff591</skin>
<skin>2b43f6</skin>
<skin>d7a9f7</skin>
<skin>800ed0</skin>
<skin>rainbow</skin>
</purchased>
</user>`);
});
});
describe('xml marshaller marshalls user data (with purchases nested)', () => {
const minimumUser = {
pinnedItems: [],
unpinnedItems: [],
inbox: {},
};
function userDataWith (fields) {
return { ...minimumUser, ...fields };
}
it('maps the purchases field with data that begins with a number and nested objects', () => {
const userData = userDataWith({
purchased: {
ads: false,
txnCount: 0,
skin: {
eb052b: true,
'0ff591': true,
'2b43f6': true,
d7a9f7: true,
'800ed0': true,
rainbow: true,
},
plan: {
consecutive: {
count: 0,
offset: 0,
gemCapExtra: 0,
trinkets: 0,
},
},
},
});
const xml = xmlMarshaller.marshallUserData(userData);
expect(xml).to.equal(`<user>
<inbox/>
<purchased>
<ads>false</ads>
<txnCount>0</txnCount>
<skin>eb052b</skin>
<skin>0ff591</skin>
<skin>2b43f6</skin>
<skin>d7a9f7</skin>
<skin>800ed0</skin>
<skin>rainbow</skin>
<plan>
<item>
<count>0</count>
<offset>0</offset>
<gemCapExtra>0</gemCapExtra>
<trinkets>0</trinkets>
</item>
</plan>
</purchased>
</user>`);
});
});
+4 -4
View File
@@ -634,7 +634,7 @@ describe('User Model', () => {
user = await user.save();
// verify that it's been awarded
expect(user.achievements.beastMaster).to.equal(true);
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_BEAST_MASTER')).to.exist;
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_STABLE')).to.exist;
// reset the user
user.achievements.beastMasterCount = 0;
@@ -683,9 +683,9 @@ describe('User Model', () => {
user = await user.save();
// verify that it's been awarded
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_BEAST_MASTER')).to.exist;
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_MOUNT_MASTER')).to.exist;
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_TRIAD_BINGO')).to.exist;
expect(user.notifications.find(
notification => notification.type === 'ACHIEVEMENT_STABLE',
)).to.exist;
});
context('manage unallocated stats points notifications', () => {
@@ -15,6 +15,10 @@ describe('DELETE /groups/:groupId/chat/:chatId', () => {
type: 'guild',
privacy: 'public',
},
leaderDetails: {
'auth.timestamps.created': new Date('2022-01-01'),
balance: 10,
},
});
groupWithChat = group;
@@ -117,7 +117,9 @@ describe('POST /chat/:chatId/flag', () => {
});
it('Flags a chat when the author\'s account was deleted', async () => {
const deletedUser = await generateUser();
const deletedUser = await generateUser({
'auth.timestamps.created': new Date('2022-01-01'),
});
const { message } = await deletedUser.post(`/groups/${group._id}/chat`, { message: TEST_MESSAGE });
await deletedUser.del('/user', {
password: 'password',
@@ -18,11 +18,16 @@ describe('POST /chat/:chatId/like', () => {
privacy: 'public',
},
members: 1,
leaderDetails: {
'auth.timestamps.created': new Date('2022-01-01'),
balance: 10,
},
});
user = groupLeader;
groupWithChat = group;
anotherUser = members[0]; // eslint-disable-line prefer-destructuring
await anotherUser.update({ 'auth.timestamps.created': new Date('2022-01-01') });
});
it('Returns an error when chat message is not found', async () => {
+44 -41
View File
@@ -38,10 +38,15 @@ describe('POST /chat', () => {
members: 2,
});
user = groupLeader;
await user.update({ 'contributor.level': SPAM_MIN_EXEMPT_CONTRIB_LEVEL }); // prevent tests accidentally throwing messageGroupChatSpam
await user.update({
'contributor.level': SPAM_MIN_EXEMPT_CONTRIB_LEVEL,
'auth.timestamps.created': new Date('2022-01-01'),
}); // prevent tests accidentally throwing messageGroupChatSpam
groupWithChat = group;
member = members[0]; // eslint-disable-line prefer-destructuring
additionalMember = members[1]; // eslint-disable-line prefer-destructuring
await member.update({ 'auth.timestamps.created': new Date('2022-01-01') });
await additionalMember.update({ 'auth.timestamps.created': new Date('2022-01-01') });
});
it('Returns an error when no message is provided', async () => {
@@ -104,7 +109,10 @@ describe('POST /chat', () => {
});
const privateGuildMemberWithChatsRevoked = members[0];
await privateGuildMemberWithChatsRevoked.update({ 'flags.chatRevoked': true });
await privateGuildMemberWithChatsRevoked.update({
'flags.chatRevoked': true,
'auth.timestamps.created': new Date('2022-01-01'),
});
const message = await privateGuildMemberWithChatsRevoked.post(`/groups/${group._id}/chat`, { message: testMessage });
@@ -122,7 +130,10 @@ describe('POST /chat', () => {
});
const privatePartyMemberWithChatsRevoked = members[0];
await privatePartyMemberWithChatsRevoked.update({ 'flags.chatRevoked': true });
await privatePartyMemberWithChatsRevoked.update({
'flags.chatRevoked': true,
'auth.timestamps.created': new Date('2022-01-01'),
});
const message = await privatePartyMemberWithChatsRevoked.post(`/groups/${group._id}/chat`, { message: testMessage });
@@ -183,7 +194,10 @@ describe('POST /chat', () => {
});
const userWithChatShadowMuted = members[0];
await userWithChatShadowMuted.update({ 'flags.chatShadowMuted': true });
await userWithChatShadowMuted.update({
'flags.chatShadowMuted': true,
'auth.timestamps.created': new Date('2022-01-01'),
});
const message = await userWithChatShadowMuted.post(`/groups/${group._id}/chat`, { message: testMessage });
@@ -202,7 +216,10 @@ describe('POST /chat', () => {
});
const userWithChatShadowMuted = members[0];
await userWithChatShadowMuted.update({ 'flags.chatShadowMuted': true });
await userWithChatShadowMuted.update({
'flags.chatShadowMuted': true,
'auth.timestamps.created': new Date('2022-01-01'),
});
const message = await userWithChatShadowMuted.post(`/groups/${group._id}/chat`, { message: testMessage });
@@ -312,6 +329,7 @@ describe('POST /chat', () => {
},
members: 1,
});
await members[0].update({ 'auth.timestamps.created': new Date('2022-01-01') });
const message = await members[0].post(`/groups/${group._id}/chat`, { message: testBannedWordMessage });
@@ -330,6 +348,7 @@ describe('POST /chat', () => {
// Update the bannedWordsAllowed property for the group
group.update({ bannedWordsAllowed: true });
await members[0].update({ 'auth.timestamps.created': new Date('2022-01-01') });
const message = await members[0].post(`/groups/${group._id}/chat`, { message: testBannedWordMessage });
@@ -345,6 +364,7 @@ describe('POST /chat', () => {
},
members: 1,
});
await members[0].update({ 'auth.timestamps.created': new Date('2022-01-01') });
const message = await members[0].post(`/groups/${group._id}/chat`, { message: testBannedWordMessage });
@@ -402,7 +422,7 @@ describe('POST /chat', () => {
});
});
it('does not allow slurs in private groups', async () => {
it('allows slurs in private groups', async () => {
const { group, members } = await createAndPopulateGroup({
groupDetails: {
name: 'Party',
@@ -411,43 +431,11 @@ describe('POST /chat', () => {
},
members: 1,
});
await members[0].update({ 'auth.timestamps.created': new Date('2022-01-01') });
await expect(members[0].post(`/groups/${group._id}/chat`, { message: testSlurMessage })).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: t('bannedSlurUsed'),
});
const message = await members[0].post(`/groups/${group._id}/chat`, { message: testSlurMessage });
// Email sent to mods
await sleep(0.5);
expect(email.sendTxn).to.be.calledThrice;
expect(email.sendTxn.args[2][1]).to.eql('slur-report-to-mods');
// Slack message to mods
expect(IncomingWebhook.prototype.send).to.be.calledOnce;
/* eslint-disable camelcase */
expect(IncomingWebhook.prototype.send).to.be.calledWith({
text: `${members[0].profile.name} (${members[0].id}) tried to post a slur`,
attachments: [{
fallback: 'Slur Message',
color: 'danger',
author_name: `@${members[0].auth.local.username} ${members[0].profile.name} (${members[0].auth.local.email}; ${members[0]._id})`,
title: 'Slur in Party - (private party)',
title_link: undefined,
text: testSlurMessage,
mrkdwn_in: [
'text',
],
}],
});
/* eslint-enable camelcase */
// Chat privileges are revoked
await expect(members[0].post(`/groups/${groupWithChat._id}/chat`, { message: testMessage })).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('chatPrivilegesRevoked'),
});
expect(message.message.id).to.exist;
});
it('errors when slur is typed in mixed case', async () => {
@@ -463,6 +451,16 @@ describe('POST /chat', () => {
});
});
it('errors when user account is too young', async () => {
const brandNewUser = await generateUser();
await expect(brandNewUser.post('/groups/habitrpg/chat', { message: 'hi im new' }))
.to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: t('chatTemporarilyUnavailable'),
});
});
it('creates a chat', async () => {
const newMessage = await user.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage });
const groupMessages = await user.get(`/groups/${groupWithChat._id}/chat`);
@@ -525,6 +523,7 @@ describe('POST /chat', () => {
'items.currentMount': mount,
'items.currentPet': pet,
'preferences.style': style,
'auth.timestamps.created': new Date('2022-01-01'),
});
await userWithStyle.sync();
@@ -550,6 +549,7 @@ describe('POST /chat', () => {
};
const backer = await generateUser({
backer: backerInfo,
'auth.timestamps.created': new Date('2022-01-01'),
});
const message = await backer.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage });
@@ -620,6 +620,9 @@ describe('POST /chat', () => {
privacy: 'private',
},
members: 1,
leaderDetails: {
'auth.timestamps.created': new Date('2022-01-01'),
},
});
const message = await groupLeader.post(`/groups/${group._id}/chat`, { message: testMessage });
@@ -15,6 +15,10 @@ describe('POST /groups/:id/chat/seen', () => {
privacy: 'public',
},
members: 1,
leaderDetails: {
'auth.timestamps.created': new Date('2022-01-01'),
balance: 10,
},
});
guild = group;
@@ -51,6 +55,9 @@ describe('POST /groups/:id/chat/seen', () => {
privacy: 'private',
},
members: 1,
leaderDetails: {
'auth.timestamps.created': new Date('2022-01-01'),
},
});
party = group;
@@ -18,6 +18,10 @@ describe('POST /groups/:id/chat/:id/clearflags', () => {
type: 'guild',
privacy: 'public',
},
leaderDetails: {
'auth.timestamps.created': new Date('2022-01-01'),
balance: 10,
},
});
groupWithChat = group;
@@ -65,6 +69,7 @@ describe('POST /groups/:id/chat/:id/clearflags', () => {
members: 1,
});
await members[0].update({ 'auth.timestamps.created': new Date('2022-01-01') });
let privateMessage = await members[0].post(`/groups/${group._id}/chat`, { message: 'Some message' });
privateMessage = privateMessage.message;
@@ -7,7 +7,7 @@ import {
describe('POST /group/:groupId/remove-manager', () => {
let leader; let nonLeader; let
groupToUpdate;
const groupName = 'Test Public Guild';
const groupName = 'Test Private Guild';
const groupType = 'guild';
let nonManager;
@@ -20,9 +20,10 @@ describe('POST /group/:groupId/remove-manager', () => {
groupDetails: {
name: groupName,
type: groupType,
privacy: 'public',
privacy: 'private',
},
members: 2,
upgradeToGroupPlan: true,
});
groupToUpdate = group;
@@ -83,7 +84,7 @@ describe('POST /group/:groupId/remove-manager', () => {
await nonLeader.sync();
expect(nonLeader.notifications.length).to.equal(0);
expect(nonLeader.notifications.length).to.equal(1); // user gets mystery items
expect(updatedGroup.managers[nonLeader._id]).to.not.exist;
});
});
@@ -37,6 +37,7 @@ describe('POST /groups/:groupId/leave', () => {
leader = groupLeader;
member = members[0]; // eslint-disable-line prefer-destructuring
memberCount = group.memberCount;
await members[0].update({ 'auth.timestamps.created': new Date('2022-01-01') });
});
it('prevents non members from leaving', async () => {
@@ -152,6 +153,10 @@ describe('POST /groups/:groupId/leave', () => {
type: 'guild',
},
invites: 1,
leaderDetails: {
'auth.timestamps.created': new Date('2022-01-01'),
balance: 10,
},
});
privateGuild = group;
@@ -153,6 +153,7 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => {
},
invites: 1,
members: 2,
leaderDetails: { 'auth.timestamps.created': new Date('2022-01-01') },
});
party = group;
@@ -25,6 +25,7 @@ describe('Prevent multiple notifications', () => {
for (let i = 0; i < 4; i += 1) {
for (let memberIndex = 0; memberIndex < partyMembers.length; memberIndex += 1) {
await partyMembers[memberIndex].update({ 'auth.timestamps.created': new Date('2022-01-01') }); // eslint-disable-line no-await-in-loop
multipleChatMessages.push(
partyMembers[memberIndex].post(`/groups/${party._id}/chat`, { message: `Message ${i}_${memberIndex}` }),
);
@@ -1,33 +0,0 @@
import superagent from 'superagent';
import nconf from 'nconf';
import {
generateUser,
translate as t,
} from '../../../../helpers/api-integration/v3';
const API_TEST_SERVER_PORT = nconf.get('PORT');
xdescribe('GET /qr-code/user/:memberId', () => {
let user;
before(async () => {
user = await generateUser();
});
it('validates req.params.memberId', async () => {
await expect(user.get('/qr-code/user/invalidUUID')).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: t('invalidReqParams'),
});
});
it('redirects to profile page', async () => {
const url = `http://localhost:${API_TEST_SERVER_PORT}/qr-code/user/${user._id}`;
const response = await superagent.get(url).end((err, res) => {
expect(err).to.be(undefined);
return res;
});
expect(response.status).to.eql(200);
expect(response.request.url).to.eql(`http://localhost:${API_TEST_SERVER_PORT}/static/front/#?memberId=${user._id}`);
});
});
@@ -134,6 +134,7 @@ describe('GET /tasks/:id', () => {
type: 'guild',
},
members: 1,
upgradeToGroupPlan: true,
});
group = groupData.group;
@@ -7,7 +7,11 @@ import {
describe('POST /tasks/clearCompletedTodos', () => {
it('deletes all completed todos except the ones from a challenge and group', async () => {
const user = await generateUser({ balance: 1 });
const guild = await generateGroup(user);
const guild = await generateGroup(
user,
{},
{ 'purchased.plan.customerId': 'group-unlimited' },
);
const challenge = await generateChallenge(user, guild);
await user.post(`/challenges/${challenge._id}/join`);
@@ -19,6 +19,7 @@ describe('Groups DELETE /tasks/:id', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -77,18 +78,18 @@ describe('Groups DELETE /tasks/:id', () => {
await user.sync();
await member2.sync();
expect(user.notifications.length).to.equal(2);
expect(user.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
expect(member2.notifications.length).to.equal(2);
expect(member2.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
expect(user.notifications.length).to.equal(3); // mystery items
expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
expect(member2.notifications.length).to.equal(3);
expect(member2.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
await member2.del(`/tasks/${task._id}`);
await user.sync();
await member2.sync();
expect(user.notifications.length).to.equal(1);
expect(member2.notifications.length).to.equal(1);
expect(user.notifications.length).to.equal(2);
expect(member2.notifications.length).to.equal(2);
});
it('deletes task from assigned user', async () => {
@@ -18,6 +18,7 @@ describe('GET /approvals/group/:groupId', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -36,7 +36,7 @@ describe('GET /tasks/group/:groupId', () => {
before(async () => {
user = await generateUser();
group = await generateGroup(user);
group = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' });
});
it('returns error when group is not found', async () => {
@@ -19,6 +19,7 @@ describe('POST /tasks/:id/approve/:userId', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -63,9 +64,9 @@ describe('POST /tasks/:id/approve/:userId', () => {
await member.sync();
expect(member.notifications.length).to.equal(2);
expect(member.notifications[1].type).to.equal('GROUP_TASK_APPROVED');
expect(member.notifications[1].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text }));
expect(member.notifications.length).to.equal(3);
expect(member.notifications[2].type).to.equal('GROUP_TASK_APPROVED');
expect(member.notifications[2].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text }));
memberTasks = await member.get('/tasks/user');
syncedTask = find(memberTasks, findAssignedTask);
@@ -89,9 +90,9 @@ describe('POST /tasks/:id/approve/:userId', () => {
await member2.post(`/tasks/${task._id}/approve/${member._id}`);
await member.sync();
expect(member.notifications.length).to.equal(2);
expect(member.notifications[1].type).to.equal('GROUP_TASK_APPROVED');
expect(member.notifications[1].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text }));
expect(member.notifications.length).to.equal(3);
expect(member.notifications[2].type).to.equal('GROUP_TASK_APPROVED');
expect(member.notifications[2].data.message).to.equal(t('yourTaskHasBeenApproved', { taskText: task.text }));
memberTasks = await member.get('/tasks/user');
syncedTask = find(memberTasks, findAssignedTask);
@@ -113,18 +114,18 @@ describe('POST /tasks/:id/approve/:userId', () => {
await user.sync();
await member2.sync();
expect(user.notifications.length).to.equal(2);
expect(user.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
expect(member2.notifications.length).to.equal(1);
expect(member2.notifications[0].type).to.equal('GROUP_TASK_APPROVAL');
expect(user.notifications.length).to.equal(3);
expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
expect(member2.notifications.length).to.equal(2);
expect(member2.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
await member2.post(`/tasks/${task._id}/approve/${member._id}`);
await user.sync();
await member2.sync();
expect(user.notifications.length).to.equal(1);
expect(member2.notifications.length).to.equal(0);
expect(user.notifications.length).to.equal(2);
expect(member2.notifications.length).to.equal(1);
});
it('prevents double approval on a task', async () => {
@@ -19,6 +19,7 @@ describe('POST /tasks/:id/needs-work/:userId', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -72,7 +73,7 @@ describe('POST /tasks/:id/needs-work/:userId', () => {
expect(syncedTask.group.approval.requestedDate).to.equal(undefined);
// Check that the notification is correct
expect(member.notifications.length).to.equal(initialNotifications + 2);
expect(member.notifications.length).to.equal(initialNotifications + 3);
const notification = member.notifications[member.notifications.length - 1];
expect(notification.type).to.equal('GROUP_TASK_NEEDS_WORK');
@@ -121,7 +122,7 @@ describe('POST /tasks/:id/needs-work/:userId', () => {
expect(syncedTask.group.approval.requested).to.equal(false);
expect(syncedTask.group.approval.requestedDate).to.equal(undefined);
expect(member.notifications.length).to.equal(initialNotifications + 2);
expect(member.notifications.length).to.equal(initialNotifications + 3);
const notification = member.notifications[member.notifications.length - 1];
expect(notification.type).to.equal('GROUP_TASK_NEEDS_WORK');
@@ -19,6 +19,7 @@ describe('POST /tasks/:id/score/:direction', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -53,15 +54,15 @@ describe('POST /tasks/:id/score/:direction', () => {
await user.sync();
expect(user.notifications.length).to.equal(2);
expect(user.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
expect(user.notifications[1].data.message).to.equal(t('userHasRequestedTaskApproval', {
expect(user.notifications.length).to.equal(3);
expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
expect(user.notifications[2].data.message).to.equal(t('userHasRequestedTaskApproval', {
user: member.auth.local.username,
taskName: updatedTask.text,
taskId: updatedTask._id,
direction,
}, 'cs')); // This test only works if we have the notification translated
expect(user.notifications[1].data.groupId).to.equal(guild._id);
expect(user.notifications[2].data.groupId).to.equal(guild._id);
expect(updatedTask.group.approval.requested).to.equal(true);
expect(updatedTask.group.approval.requestedDate).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
@@ -80,25 +81,25 @@ describe('POST /tasks/:id/score/:direction', () => {
await user.sync();
await member2.sync();
expect(user.notifications.length).to.equal(2);
expect(user.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
expect(user.notifications[1].data.message).to.equal(t('userHasRequestedTaskApproval', {
expect(user.notifications.length).to.equal(3);
expect(user.notifications[2].type).to.equal('GROUP_TASK_APPROVAL');
expect(user.notifications[2].data.message).to.equal(t('userHasRequestedTaskApproval', {
user: member.auth.local.username,
taskName: updatedTask.text,
taskId: updatedTask._id,
direction,
}));
expect(user.notifications[1].data.groupId).to.equal(guild._id);
expect(user.notifications[2].data.groupId).to.equal(guild._id);
expect(member2.notifications.length).to.equal(1);
expect(member2.notifications[0].type).to.equal('GROUP_TASK_APPROVAL');
expect(member2.notifications[0].data.message).to.equal(t('userHasRequestedTaskApproval', {
expect(member2.notifications.length).to.equal(2);
expect(member2.notifications[1].type).to.equal('GROUP_TASK_APPROVAL');
expect(member2.notifications[1].data.message).to.equal(t('userHasRequestedTaskApproval', {
user: member.auth.local.username,
taskName: updatedTask.text,
taskId: updatedTask._id,
direction,
}));
expect(member2.notifications[0].data.groupId).to.equal(guild._id);
expect(member2.notifications[1].data.groupId).to.equal(guild._id);
});
it('errors when approval has already been requested', async () => {
@@ -26,6 +26,7 @@ describe('POST /tasks/group/:groupid', () => {
privacy: 'private',
},
members: 1,
upgradeToGroupPlan: true,
});
guild = group;
@@ -21,6 +21,7 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -103,14 +104,14 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
await member2.sync();
const groupTask = await user.get(`/tasks/group/${guild._id}`);
expect(user.notifications.length).to.equal(2); // includes Guild Joined achievement
expect(user.notifications[1].type).to.equal('GROUP_TASK_CLAIMED');
expect(user.notifications[1].data.taskId).to.equal(groupTask[0]._id);
expect(user.notifications[1].data.groupId).to.equal(guild._id);
expect(member2.notifications.length).to.equal(1);
expect(member2.notifications[0].type).to.equal('GROUP_TASK_CLAIMED');
expect(member2.notifications[0].data.taskId).to.equal(groupTask[0]._id);
expect(member2.notifications[0].data.groupId).to.equal(guild._id);
expect(user.notifications.length).to.equal(3); // includes Guild Joined achievement
expect(user.notifications[2].type).to.equal('GROUP_TASK_CLAIMED');
expect(user.notifications[2].data.taskId).to.equal(groupTask[0]._id);
expect(user.notifications[2].data.groupId).to.equal(guild._id);
expect(member2.notifications.length).to.equal(2);
expect(member2.notifications[1].type).to.equal('GROUP_TASK_CLAIMED');
expect(member2.notifications[1].data.taskId).to.equal(groupTask[0]._id);
expect(member2.notifications[1].data.groupId).to.equal(guild._id);
});
it('assigns a task to a user', async () => {
@@ -130,9 +131,9 @@ describe('POST /tasks/:taskId/assign/:memberId', () => {
const groupTask = await user.get(`/tasks/group/${guild._id}`);
expect(member.notifications.length).to.equal(1);
expect(member.notifications[0].type).to.equal('GROUP_TASK_ASSIGNED');
expect(member.notifications[0].taskId).to.equal(groupTask._id);
expect(member.notifications.length).to.equal(2);
expect(member.notifications[1].type).to.equal('GROUP_TASK_ASSIGNED');
expect(member.notifications[1].taskId).to.equal(groupTask._id);
});
it('assigns a task to multiple users', async () => {
@@ -9,7 +9,7 @@ describe('POST group-tasks/:taskId/move/to/:position', () => {
beforeEach(async () => {
user = await generateUser({ balance: 1 });
guild = await generateGroup(user, { type: 'guild' });
guild = await generateGroup(user, { type: 'guild' }, { 'purchased.plan.customerId': 'group-unlimited' });
});
it('can move task to new position', async () => {
@@ -21,6 +21,7 @@ describe('POST /tasks/:taskId/unassign/:memberId', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -91,7 +92,7 @@ describe('POST /tasks/:taskId/unassign/:memberId', () => {
await user.post(`/tasks/${task._id}/unassign/${member._id}`);
await member.sync();
expect(member.notifications.length).to.equal(0);
expect(member.notifications.length).to.equal(1); // mystery items
});
it('unassigns a user and only that user from a task', async () => {
@@ -22,6 +22,7 @@ describe('PUT /tasks/:id', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -15,6 +15,7 @@ describe('DELETE group /tasks/:taskId/checklist/:itemId', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -15,6 +15,7 @@ describe('POST group /tasks/:taskId/checklist/', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -15,6 +15,7 @@ describe('PUT group /tasks/:taskId/checklist/:itemId', () => {
type: 'guild',
},
members: 2,
upgradeToGroupPlan: true,
});
guild = group;
@@ -139,7 +139,7 @@ describe('POST /user/class/cast/:spellId', () => {
});
it('returns an error if a group task was targeted', async () => {
const { group, groupLeader } = await createAndPopulateGroup();
const { group, groupLeader } = await createAndPopulateGroup({ upgradeToGroupPlan: true });
const groupTask = await groupLeader.post(`/tasks/group/${group._id}`, {
text: 'todo group',
@@ -266,7 +266,7 @@ describe('POST /user/class/cast/:spellId', () => {
});
it('searing brightness does not affect challenge or group tasks', async () => {
const guild = await generateGroup(user);
const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' });
const challenge = await generateChallenge(user, guild);
await user.post(`/challenges/${challenge._id}/join`);
await user.post(`/tasks/challenge/${challenge._id}`, {
@@ -88,7 +88,7 @@ describe('POST /user/reset', () => {
});
it('does not delete challenge or group tasks', async () => {
const guild = await generateGroup(user);
const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' });
const challenge = await generateChallenge(user, guild);
await user.post(`/challenges/${challenge._id}/join`);
await user.post(`/tasks/challenge/${challenge._id}`, {
@@ -39,25 +39,38 @@ describe('POST /user/buy-quest/:key', () => {
}));
});
it('returns an error if quest prerequisites are not met', async () => {
const key = 'dilatoryDistress2';
it('returns an error if not all quest prerequisites are met', async () => {
const prerequisites = ['dilatoryDistress1', 'dilatoryDistress2'];
const key = 'dilatoryDistress3';
const achievementName1 = `achievements.quests.${prerequisites[0]}`;
await user.update({
[achievementName1]: true,
'stats.gp': 9999,
});
await expect(user.post(`/user/buy-quest/${key}`))
.to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('mustComplete', { quest: 'dilatoryDistress1' }),
message: t('mustComplete', { quest: prerequisites[1] }),
});
});
it('allows purchase of a quest if prerequisites are met', async () => {
const prerequisite = 'dilatoryDistress1';
const key = 'dilatoryDistress2';
const prerequisites = ['dilatoryDistress1', 'dilatoryDistress2'];
const key = 'dilatoryDistress3';
const item = content.quests[key];
const achievementName = `achievements.quests.${prerequisite}`;
const achievementName1 = `achievements.quests.${prerequisites[0]}`;
const achievementName2 = `achievements.quests.${prerequisites[1]}`;
await user.update({ [achievementName]: true, 'stats.gp': 9999 });
await user.update({
[achievementName1]: true,
[achievementName2]: true,
'stats.gp': 9999,
});
const res = await user.post(`/user/buy-quest/${key}`);
await user.sync();
@@ -124,7 +124,7 @@ describe('POST /user/class/cast/:spellId', () => {
});
it('returns an error if a group task was targeted', async () => {
const { group, groupLeader } = await createAndPopulateGroup();
const { group, groupLeader } = await createAndPopulateGroup({ upgradeToGroupPlan: true });
const groupTask = await groupLeader.post(`/tasks/group/${group._id}`, {
text: 'todo group',
@@ -234,7 +234,7 @@ describe('POST /user/class/cast/:spellId', () => {
});
it('searing brightness does not affect challenge or group tasks', async () => {
const guild = await generateGroup(user);
const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' });
const challenge = await generateChallenge(user, guild);
await user.post(`/challenges/${challenge._id}/join`);
await user.post(`/tasks/challenge/${challenge._id}`, {
+1 -1
View File
@@ -88,7 +88,7 @@ describe('POST /user/reset', () => {
});
it('does not delete challenge or group tasks', async () => {
const guild = await generateGroup(user);
const guild = await generateGroup(user, {}, { 'purchased.plan.customerId': 'group-unlimited' });
const challenge = await generateChallenge(user, guild);
await user.post(`/challenges/${challenge._id}/join`);
await user.post(`/tasks/challenge/${challenge._id}`, {
+24 -2
View File
@@ -33,7 +33,7 @@ describe('shared.ops.buyQuestGems', () => {
pinnedGearUtils.removeItemByPath.restore();
});
context('successful purchase', () => {
context('single purchase', () => {
const userGemAmount = 10;
before(() => {
@@ -44,7 +44,7 @@ describe('shared.ops.buyQuestGems', () => {
user.pinnedItems.push({ type: 'quests', key: 'gryphon' });
});
it('purchases quests', async () => {
it('successfully purchases quest', async () => {
const key = 'gryphon';
await buyQuest(user, { params: { key } });
@@ -58,6 +58,28 @@ describe('shared.ops.buyQuestGems', () => {
await buyQuest(user, { params: { key } });
expect(user.items.quests[key]).to.equal(1);
expect(pinnedGearUtils.removeItemByPath.notCalled).to.equal(true);
});
it('errors if the user has not completed prerequisite quests', async () => {
const key = 'atom3';
user.achievements.quests.atom1 = 1;
try {
await buyQuest(user, { params: { key } });
} catch (err) {
expect(err).to.be.an.instanceof(NotAuthorized);
expect(err.message).to.equal(i18n.t('mustComplete', { quest: 'atom2' }));
expect(user.items.quests[key]).to.eql(undefined);
}
});
it('successfully purchases quest if user has completed all prerequisite quests', async () => {
const key = 'atom3';
user.achievements.quests.atom1 = 1;
user.achievements.quests.atom2 = 1;
await buyQuest(user, { params: { key } });
expect(user.items.quests[key]).to.equal(1);
expect(pinnedGearUtils.removeItemByPath.notCalled).to.equal(true);
});
+21 -1
View File
@@ -162,7 +162,9 @@ describe('shared.ops.buyQuest', () => {
}
});
it('does not buy a quest without completing previous quests', async () => {
it('returns error if user has not completed all prerequisite quests', async () => {
user.stats.gp = 9999;
user.achievements.quests.dilatoryDistress1 = 1;
try {
await buyQuest(user, {
params: {
@@ -175,4 +177,22 @@ describe('shared.ops.buyQuest', () => {
expect(user.items.quests).to.eql({});
}
});
it('successfully purchases quest if user has completed all prerequisite quests', async () => {
user.stats.gp = 500;
user.achievements.quests.dilatoryDistress1 = 1;
user.achievements.quests.dilatoryDistress2 = 1;
await buyQuest(user, {
params: {
key: 'dilatoryDistress3',
},
}, analytics);
expect(user.items.quests).to.eql({
dilatoryDistress3: 1,
});
expect(user.stats.gp).to.equal(100);
expect(analytics.track).to.be.calledOnce;
});
});
@@ -28,7 +28,7 @@ app.post('/webhooks/:id', (req, res) => {
});
// Helps close down server from within mocha test
// See http://stackoverflow.com/a/37054753/2601552
// See https://stackoverflow.com/a/37054753/2601552
const sockets = {};
server.on('connection', socket => {
const id = uuid();
@@ -40,7 +40,6 @@ function _requestMaker (user, method, additionalSets = {}) {
|| route.indexOf('/paypal') === 0
|| route.indexOf('/amazon') === 0
|| route.indexOf('/stripe') === 0
|| route.indexOf('/qr-code') === 0
|| route.indexOf('/analytics') === 0
) {
url += `${route}`;
@@ -5,6 +5,8 @@ import { v4 as generateUUID } from 'uuid';
import { ApiUser, ApiGroup, ApiChallenge } from '../api-classes';
import { requester } from '../requester';
import * as Tasks from '../../../../website/server/models/task';
import payments from '../../../../website/server/libs/payments/payments';
import { model as User } from '../../../../website/server/models/user';
// Creates a new user and returns it
// If you need the user to have specific requirements,
@@ -77,6 +79,26 @@ export async function generateGroup (leader, details = {}, update = {}) {
return apiGroup;
}
async function _upgradeToGroupPlan (groupLeader, group) {
const groupLeaderModel = await User.findById(groupLeader._id).exec();
// Create subscription
const paymentData = {
user: groupLeaderModel,
groupId: group._id,
sub: {
key: 'basic_3mo',
},
customerId: 'customer-id',
paymentMethod: 'Payment Method',
headers: {
'x-client': 'habitica-web',
'user-agent': '',
},
};
await payments.createSubscription(paymentData);
}
// This is generate group + the ability to create
// real users to populate it. The settings object
// takes in:
@@ -95,6 +117,7 @@ export async function generateGroup (leader, details = {}, update = {}) {
export async function createAndPopulateGroup (settings = {}) {
const numberOfMembers = settings.members || 0;
const numberOfInvites = settings.invites || 0;
const upgradeToGroupPlan = settings.upgradeToGroupPlan || false;
const { groupDetails } = settings;
const leaderDetails = settings.leaderDetails || { balance: 10 };
@@ -124,6 +147,10 @@ export async function createAndPopulateGroup (settings = {}) {
await Promise.all(invitees.map(invitee => invitee.sync()));
if (upgradeToGroupPlan) {
await _upgradeToGroupPlan(groupLeader, group);
}
return {
groupLeader,
group,
+1
View File
@@ -11,6 +11,7 @@ if (process.env.LOAD_SERVER === '0') { // when the server is in a different proc
setupNconf('./config.json.example');
nconf.set('NODE_DB_URI', nconf.get('TEST_DB_URI'));
nconf.set('NODE_ENV', 'test');
nconf.set('ACCOUNT_MIN_CHAT_AGE', '2');
nconf.set('IS_TEST', true);
// We require src/server and not src/index because
// 1. nconf is already setup
+398 -1039
View File
File diff suppressed because it is too large Load Diff
+14 -13
View File
@@ -13,26 +13,27 @@
"storybook:serve": "vue-cli-service storybook:serve -p 6006 -c config/storybook"
},
"dependencies": {
"@storybook/addon-actions": "6.4.19",
"@storybook/addon-actions": "6.5.8",
"@storybook/addon-knobs": "6.2.9",
"@storybook/addon-links": "6.4.18",
"@storybook/addon-links": "6.5.8",
"@storybook/addon-notes": "5.3.21",
"@storybook/addons": "6.4.19",
"@storybook/addons": "6.5.9",
"@storybook/vue": "6.3.13",
"@vue/cli-plugin-babel": "^4.5.15",
"@vue/cli-plugin-eslint": "^4.5.15",
"@vue/cli-plugin-eslint": "^4.5.19",
"@vue/cli-plugin-router": "^4.5.15",
"@vue/cli-plugin-unit-mocha": "^4.5.15",
"@vue/cli-service": "^4.5.15",
"@vue/test-utils": "1.0.0-beta.29",
"amplitude-js": "^8.17.0",
"amplitude-js": "^8.18.5",
"axios": "^0.25.0",
"axios-progress-bar": "^1.2.0",
"babel-eslint": "^10.1.0",
"bootstrap": "^4.6.0",
"bootstrap-vue": "^2.21.2",
"bootstrap-vue": "^2.22.0",
"chai": "^4.3.6",
"core-js": "^3.21.0",
"core-js": "^3.23.5",
"dompurify": "^2.3.8",
"eslint": "^6.8.0",
"eslint-config-habitrpg": "^6.2.0",
"eslint-plugin-mocha": "^5.3.0",
@@ -40,14 +41,14 @@
"habitica-markdown": "^3.0.0",
"hellojs": "^1.19.5",
"inspectpack": "^4.7.1",
"intro.js": "^5.0.0",
"intro.js": "^5.1.0",
"jquery": "^3.6.0",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"nconf": "^0.11.3",
"moment": "^2.29.4",
"nconf": "^0.12.0",
"sass": "^1.34.0",
"sass-loader": "^8.0.2",
"smartbanner.js": "^1.17.0",
"smartbanner.js": "^1.19.0",
"svg-inline-loader": "^0.8.2",
"svg-url-loader": "^7.1.1",
"svgo": "^1.3.2",
@@ -57,13 +58,13 @@
"vue": "^2.6.14",
"vue-cli-plugin-storybook": "2.1.0",
"vue-mugen-scroll": "^0.2.6",
"vue-router": "^3.5.3",
"vue-router": "^3.5.4",
"vue-template-compiler": "^2.6.14",
"vuedraggable": "^2.24.3",
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#153d339e4dbebb73733658aeda1d5b7fcc55b0a0",
"webpack": "^4.46.0"
},
"devDependencies": {
"@babel/plugin-proposal-optional-chaining": "^7.16.7"
"@babel/plugin-proposal-optional-chaining": "^7.18.6"
}
}
+9 -1
View File
@@ -414,7 +414,15 @@ export default {
this.$store.state.isUserLoaded = true;
Analytics.setUser();
Analytics.updateUser();
return axios.get('/api/v4/i18n/browser-script', { language: this.user.preferences.language });
return axios.get('/api/v4/i18n/browser-script',
{
language: this.user.preferences.language,
headers: {
'Cache-Control': 'no-cache',
Pragma: 'no-cache',
Expires: '0',
},
});
}).then(() => {
const i18nData = window && window['habitica-i18n'];
this.$loadLocale(i18nData);
File diff suppressed because it is too large Load Diff
+76 -26
View File
@@ -82,7 +82,7 @@ input, textarea, input.form-control, textarea.form-control {
}
}
/** Colored Input-Groups, ignoring checklist */
// Colored Input-Groups, ignoring checklist
.input-group:not(.checklist-group) {
border-radius: 2px;
border: solid 1px $gray-400;
@@ -100,7 +100,7 @@ input, textarea, input.form-control, textarea.form-control {
}
}
/** Generic Input Group Styles */
// Generic Input Group Styles
.input-group {
height: 2rem;
@@ -179,10 +179,11 @@ input, textarea, input.form-control, textarea.form-control {
padding-left: 0px;
}
// Checkboxes and radios
// used in checkboxes and radios
$bg-focused-active-control: #4f2993;
$bg-disabled-control: #34303a;
// custom control
.custom-control {
margin-bottom: .5rem;
@@ -205,6 +206,7 @@ $bg-disabled-control: #34303a;
}
}
// checkboxes
.custom-checkbox {
.custom-control-label::before {
border-radius: 2px;
@@ -280,11 +282,26 @@ $bg-disabled-control: #34303a;
padding-left: 36px;
}
// radio buttons
$bg-color: $purple-400;
// svg for the purple dot
@mixin custom-radio-checked-icon ($bg-color) {
background-image: str-replace(url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$bg-color}'/%3E%3C/svg%3E"), "#", "%23");
}
.custom-radio .custom-control-input {
opacity: 0;
margin: 15px 25px 34px 25px;
// outside circle
&:checked~.custom-control-label::before {
background-color: $gray-700;
background-size: 12px 12px;
border-color: $purple-400;
}
// checked indicator
&:checked~.custom-control-label::after {
@include custom-radio-checked-icon($purple-400);
width: 18px;
@@ -292,51 +309,84 @@ $bg-disabled-control: #34303a;
background-size: 12px 12px;
}
&:checked~.custom-control-label::before {
background-color: $gray-700;
background-size: 12px 12px;
border-color: $purple-400;
}
&:active~.custom-control-label::before {
background-color: inherit;
}
&:focus:not(:checked):not(:disabled)~.custom-control-label::before, &:active:not(:checked):not(:disabled)~.custom-control-label::before {
box-shadow: 0 0 0 6px rgba($bg-focused-active-control, 0.1);
// focus / not checked / not disabled
&:focus:not(:checked):not(:disabled)~.custom-control-label::before,
&:active:not(:checked):not(:disabled)~.custom-control-label::before {
border: 2px solid $gray-300;
box-shadow: 0 0 0 2px rgba(146, 92, 243, 0.5);
}
&:focus:checked:not(:disabled)~.custom-control-label::before, &:active:checked:not(:disabled)~.custom-control-label::before {
box-shadow: 0 0 0 6px rgba($bg-focused-active-control, 0.1);
border-color: $purple-400;
background-color: rgba($bg-focused-active-control, 0.1);
// focus / checked / not disabled
&:focus:checked:not(:disabled)~.custom-control-label::before,
&:active:checked:not(:disabled)~.custom-control-label::before {
border: 2px solid $purple-400;
box-shadow: 0 0 0 2px rgba(146, 92, 243, 0.5);
}
&:disabled:checked~.custom-control-label::before {
border-color: $gray-400;
background-color: transparent;
// hover / not checked / not disabled
&:hover:not(:checked):not(:disabled)~.custom-control-label::before,
&:active:not(:checked):not(:disabled)~.custom-control-label::before {
width: 18px;
height: 18px;
background: 50%/50% 50% no-repeat;
@include custom-radio-checked-icon($purple-400);
background-size: 12px 12px;
border: solid 2px $purple-400;
}
&:disabled:checked~.custom-control-label::after {
// hover / checked / not disabled
&:hover:checked:not(:disabled)~.custom-control-label::before,
&:active::checked:not(:disabled)~.custom-control-label::before {
width: 18px;
height: 18px;
background: 50%/50% 50% no-repeat;
@include custom-radio-checked-icon($gray-400);
background-size: 12px 12px;
border: solid 2px $purple-300;
}
// disabled / checked / before
&:disabled:checked~.custom-control-label::before {
background: 50%/50% 50% no-repeat;
@include custom-radio-checked-icon($gray-300);
border: 2px solid $gray-200;
background-color: transparent;
opacity: 0.75;
}
// disabled / checked / after
&:disabled:checked~.custom-control-label::after {
background: 50%/50% 50% no-repeat;
@include custom-radio-checked-icon($gray-300);
width: 18px;
height: 18px;
background-size: 12px 12px;
}
// disabled / not checked / before
&:disabled:not(:checked)~.custom-control-label::before {
border-color: $gray-300;
background-color: transparent;
background-color: $gray-600;
border: 2px solid $gray-200;
}
&:focus:disabled~.custom-control-label::before, &:active:disabled~.custom-control-label::before {
box-shadow: 0 0 0 6px rgba($bg-disabled-control, 0.1);
border-color: $gray-300;
// focus and disabled / not checked / before
&:focus:disabled~.custom-control-label::before,
&:active:disabled~.custom-control-label::before {
background-color: rgba($bg-disabled-control, 0.1);
box-shadow: 0 0 0 6px rgba($bg-disabled-control, 0.1);
border: 2px solid $gray-200;
}
&:focus:disabled:checked~.custom-control-label::before, &:active:disabled:checked~.custom-control-label::before {
border-color: $gray-400;
// focus and disabled / checked / before
&:focus:disabled:checked~.custom-control-label::before,
&:active:disabled:checked~.custom-control-label::before {
background: 50%/50% 50% no-repeat;
@include custom-radio-checked-icon($gray-300);
border: 2px solid $gray-200;
}
}
@@ -18,8 +18,10 @@ body {
// Restore the default styling for a elements without an href attribute
// that was changed in bootstrap 4.5.1
a:not([href]), a:not([href]):hover {
color: inherit;
text-decoration: none;
&:not([role=button]) {
color: inherit;
text-decoration: none;
}
}
a, a:not([href]):not([tabindex]) {
@@ -0,0 +1,27 @@
<svg width="176" height="67" viewBox="0 0 176 67" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<path fill="#77F4C7" d="M35.667 11.667 40 9.5l-4.333-2.167L33.5 3l-2.167 4.333L27 9.5l4.333 2.167L33.5 16z"/>
<path fill="#BDA8FF" d="M24.667 38.667 30 36l-5.333-2.667L22 28l-2.667 5.333L14 36l5.333 2.667L22 44z"/>
<path fill="#8EEDF6" d="M35.667 63.667 39 62l-3.333-1.667L34 57l-1.667 3.333L29 62l3.333 1.667L34 67z"/>
<path fill="#FFBE5D" d="M6.667 49.667 10 48l-3.333-1.667L5 43l-1.667 3.333L0 48l3.333 1.667L5 53z"/>
<path fill="#FFB6B8" d="M5.667 20.667 8 19.5l-2.333-1.167L4.5 16l-1.167 2.333L1 19.5l2.333 1.167L4.5 23z"/>
<g>
<path fill="#77F4C7" d="M140.333 11.667 136 9.5l4.333-2.167L142.5 3l2.167 4.333L149 9.5l-4.333 2.167L142.5 16z"/>
<path fill="#BDA8FF" d="M151.333 38.667 146 36l5.333-2.667L154 28l2.667 5.333L162 36l-5.333 2.667L154 44z"/>
<path fill="#8EEDF6" d="M140.333 63.667 137 62l3.333-1.667L142 57l1.667 3.333L147 62l-3.333 1.667L142 67z"/>
<path fill="#FFBE5D" d="M169.333 49.667 166 48l3.333-1.667L171 43l1.667 3.333L176 48l-3.333 1.667L171 53z"/>
<path fill="#FFB6B8" d="M170.333 20.667 168 19.5l2.333-1.167L171.5 16l1.167 2.333L175 19.5l-2.333 1.167L171.5 23z"/>
</g>
<g>
<path d="M81.117 13.904c-2.139-4.838-6.274-9.113-11.25-9.324-4.976-.211-7.828 3.779-6.367 7.309 1.461 3.53 4.94 4.177 16.227 7.202 3.204.858 3.528-.35 1.39-5.187z" stroke="#22AEB7" stroke-width="4"/>
<path d="M93.833 13.904c2.138-4.838 6.273-9.113 11.25-9.324 4.975-.211 7.828 3.779 6.367 7.309-1.462 3.53-4.94 4.177-16.227 7.202-3.205.858-3.528-.35-1.39-5.187z" stroke="#38C9C6" stroke-width="4"/>
<path d="M87.128 11c-9.738 0-3.907 11.145 0 11.145 3.908 0 9.74-11.145 0-11.145z" fill="#46DDDA"/>
<path fill="#6133B4" d="M62 33h52v34H62zM56 21h64v12H56z"/>
<path fill-opacity=".5" fill="#FFF" style="mix-blend-mode:soft-light" d="M32 30h26v34H32z" transform="translate(56 3)"/>
<path fill="#8EEDF6" d="M88 33h6v34h-6z"/>
<path fill="#3BCAD7" d="M82 33h6v34h-6zM76 21h12v12H76z"/>
<path fill="#8EEDF6" d="M88 21h12v12H88z"/>
<path fill-opacity=".2" fill="#000" style="mix-blend-mode:multiply" d="M6 30h26v6H6zM20 18h12v6H20zM0 24h20v6H0zM44 24h20v6H44zM32 18h12v6H32zM6 58h26v6H6zM32 30h26v6H32zM32 58h26v6H32z" transform="translate(56 3)"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

+10 -4
View File
@@ -1,5 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd" stroke="#A5A1AC" stroke-width="2">
<path d="M1 11L11 1M11 11L1 1"/>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icon/Close</title>
<g id="Modals" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Shop-Modals" transform="translate(-183.000000, -655.000000)" fill="#878190" fill-rule="nonzero">
<g id="Icon/Close" transform="translate(183.000000, 655.000000)">
<polygon id="Mask" points="12.1973467 2 14 3.80265326 9.80187117 8 14 12.1973467 12.1973467 14 8 9.80187117 3.80265326 14 2 12.1973467 6.19812883 8 2 3.80265326 3.80265326 2 8 6.19812883"></polygon>
</g>
</g>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 747 B

@@ -1,60 +0,0 @@
<template>
<b-modal
id="just-add-water"
:title="title"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<achievement-avatar class="avatar" />
</div>
<div class="col-6 offset-3 text-center">
<p>{{ $t('achievementJustAddWaterModalText') }}</p>
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div>
<achievement-footer />
</b-modal>
</template>
<style scoped>
.avatar {
width: 140px;
margin: 0 auto;
margin-bottom: 1.5em;
margin-top: 1.5em;
}
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import { mapState } from '@/libs/store';
export default {
components: {
achievementFooter,
achievementAvatar,
},
data () {
return {
title: `${this.$t('modalAchievement')} ${this.$t('achievementJustAddWater')}`,
};
},
computed: {
...mapState({ user: 'user.data' }),
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'just-add-water');
},
},
};
</script>
@@ -1,60 +0,0 @@
<template>
<b-modal
id="lost-masterclasser"
:title="title"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<achievement-avatar class="avatar" />
</div>
<div class="col-6 offset-3 text-center">
<p>{{ $t('achievementLostMasterclasserModalText') }}</p>
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div>
<achievement-footer />
</b-modal>
</template>
<style scoped>
.avatar {
width: 140px;
margin: 0 auto;
margin-bottom: 1.5em;
margin-top: 1.5em;
}
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import { mapState } from '@/libs/store';
export default {
components: {
achievementFooter,
achievementAvatar,
},
data () {
return {
title: `${this.$t('modalAchievement')} ${this.$t('achievementLostMasterclasser')}`,
};
},
computed: {
...mapState({ user: 'user.data' }),
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'lost-masterclasser');
},
},
};
</script>
@@ -1,60 +0,0 @@
<template>
<b-modal
id="mind-over-matter"
:title="title"
size="md"
:hide-footer="true"
>
<div class="modal-body">
<div class="col-12">
<achievement-avatar class="avatar" />
</div>
<div class="col-6 offset-3 text-center">
<p>{{ $t('achievementMindOverMatterModalText') }}</p>
<button
class="btn btn-primary"
@click="close()"
>
{{ $t('huzzah') }}
</button>
</div>
</div>
<achievement-footer />
</b-modal>
</template>
<style scoped>
.avatar {
width: 140px;
margin: 0 auto;
margin-bottom: 1.5em;
margin-top: 1.5em;
}
</style>
<script>
import achievementFooter from './achievementFooter';
import achievementAvatar from './achievementAvatar';
import { mapState } from '@/libs/store';
export default {
components: {
achievementFooter,
achievementAvatar,
},
data () {
return {
title: `${this.$t('modalAchievement')} ${this.$t('achievementMindOverMatter')}`,
};
},
computed: {
...mapState({ user: 'user.data' }),
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'mind-over-matter');
},
},
};
</script>
+1 -1
View File
@@ -34,7 +34,7 @@
</li>
<li>
<a
href="http://blog.habitrpg.com/"
href="https://blog.habitrpg.com/"
target="_blank"
>{{ $t('tumblr') }}</a>
</li>
@@ -614,6 +614,7 @@ import axios from 'axios';
import hello from 'hellojs';
import debounce from 'lodash/debounce';
import isEmail from 'validator/lib/isEmail';
import DOMPurify from 'dompurify';
import { buildAppleAuthUrl } from '../../libs/auth';
import { MINIMUM_PASSWORD_LENGTH } from '@/../../common/script/constants';
@@ -754,6 +755,12 @@ export default {
}
});
}, 500),
sanitizeRedirect (redirect) {
if (!redirect) return '/';
let sanitizedString = DOMPurify.sanitize(redirect).replace(/\\|\/\/|\./g, '');
sanitizedString = `/${sanitizedString}`;
return sanitizedString;
},
async register () {
// @TODO do not use alert
if (!this.email) {
@@ -785,19 +792,14 @@ export default {
passwordConfirm: this.passwordConfirm,
});
let redirectTo;
if (this.$route.query.redirectTo) {
redirectTo = this.$route.query.redirectTo;
} else {
redirectTo = '/';
}
const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo);
// @TODO do not reload entire page
// problem is that app.vue created hook should be called again
// after user is logged in / just signed up
// ALSO it's the only way to make sure language data
// is reloaded and correct for the logged in user
// Same situation in login and socialAuth functions
window.location.href = redirectTo;
},
async login () {
@@ -807,19 +809,8 @@ export default {
password: this.password,
});
let redirectTo;
const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo);
if (this.$route.query.redirectTo) {
redirectTo = this.$route.query.redirectTo;
} else {
redirectTo = '/';
}
// @TODO do not reload entire page
// problem is that app.vue created hook should be called again
// after user is logged in / just signed up
// ALSO it's the only way to make sure language data
// is reloaded and correct for the logged in user
window.location.href = redirectTo;
},
// @TODO: Abstract hello in to action or lib
@@ -842,19 +833,8 @@ export default {
auth,
});
let redirectTo;
const redirectTo = this.sanitizeRedirect(this.$route.query.redirectTo);
if (this.$route.query.redirectTo) {
redirectTo = this.$route.query.redirectTo;
} else {
redirectTo = '/';
}
// @TODO do not reload entire page
// problem is that app.vue created hook should be called again
// after user is logged in / just signed up
// ALSO it's the only way to make sure language data
// is reloaded and correct for the logged in user
window.location.href = redirectTo;
}
},
@@ -122,6 +122,11 @@
font-weight: bold;
}
.custom-control-input {
z-index: -1;
opacity: 0;
}
.box:hover {
cursor: pointer;
opacity: 0.7;
@@ -225,6 +225,11 @@ export default {
this.group = await this.$store.dispatch('guilds:getGroup', {
groupId: this.searchId,
});
if (!this.group?.purchased?.active) {
if (this.group.type === 'guild') this.$router.push(`/groups/guild/${this.group._id}`);
if (this.group.type === 'party') this.$router.push('/party');
return;
}
this.$store.dispatch('common:setTitle', {
subSection: this.group.name,
section: this.$route.path.startsWith('/group-plans') ? this.$t('groupPlans') : this.$t('group'),
@@ -3,7 +3,7 @@
<creator-intro />
<profileModal />
<report-flag-modal />
<send-gems-modal />
<send-gift-modal />
<select-user-modal />
<b-navbar
id="habitica-menu"
@@ -747,7 +747,7 @@ import creatorIntro from '../creatorIntro';
import notificationMenu from './notificationsDropdown';
import profileModal from '../userMenu/profileModal';
import reportFlagModal from '../chat/reportFlagModal';
import sendGemsModal from '@/components/payments/sendGemsModal';
import sendGiftModal from '@/components/payments/sendGiftModal';
import selectUserModal from '@/components/payments/selectUserModal';
import sync from '@/mixins/sync';
import userDropdown from './userDropdown';
@@ -759,7 +759,7 @@ export default {
notificationMenu,
profileModal,
reportFlagModal,
sendGemsModal,
sendGiftModal,
selectUserModal,
userDropdown,
},
@@ -1,34 +0,0 @@
<template>
<base-notification
:can-remove="canRemove"
:notification="notification"
:read-after-click="true"
@click="action"
>
<div
slot="content"
v-html="achievementString"
></div>
</base-notification>
</template>
<script>
import BaseNotification from './base';
export default {
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
computed: {
achievementString () {
return `<strong>${this.$t('achievement')}</strong>: ${this.$t('achievementJustAddWater')}`;
},
},
methods: {
action () {
this.$root.$emit('bv::show::modal', 'just-add-water');
},
},
};
</script>
@@ -1,34 +0,0 @@
<template>
<base-notification
:can-remove="canRemove"
:notification="notification"
:read-after-click="true"
@click="action"
>
<div
slot="content"
v-html="achievementString"
></div>
</base-notification>
</template>
<script>
import BaseNotification from './base';
export default {
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
computed: {
achievementString () {
return `<strong>${this.$t('achievement')}</strong>: ${this.$t('achievementLostMasterclasser')}`;
},
},
methods: {
action () {
this.$root.$emit('bv::show::modal', 'lost-masterclasser');
},
},
};
</script>
@@ -1,34 +0,0 @@
<template>
<base-notification
:can-remove="canRemove"
:notification="notification"
:read-after-click="true"
@click="action"
>
<div
slot="content"
v-html="achievementString"
></div>
</base-notification>
</template>
<script>
import BaseNotification from './base';
export default {
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
computed: {
achievementString () {
return `<strong>${this.$t('achievement')}</strong>: ${this.$t('achievementMindOverMatter')}`;
},
},
methods: {
action () {
this.$root.$emit('bv::show::modal', 'mind-over-matter');
},
},
};
</script>
@@ -140,9 +140,6 @@ import NEW_INBOX_MESSAGE from './notifications/newPrivateMessage';
import NEW_CHAT_MESSAGE from './notifications/newChatMessage';
import WORLD_BOSS from './notifications/worldBoss';
import VERIFY_USERNAME from './notifications/verifyUsername';
import ACHIEVEMENT_JUST_ADD_WATER from './notifications/justAddWater';
import ACHIEVEMENT_LOST_MASTERCLASSER from './notifications/lostMasterclasser';
import ACHIEVEMENT_MIND_OVER_MATTER from './notifications/mindOverMatter';
import ONBOARDING_COMPLETE from './notifications/onboardingComplete';
import GIFT_ONE_GET_ONE from './notifications/g1g1';
import OnboardingGuide from './onboardingGuide';
@@ -167,9 +164,6 @@ export default {
CARD_RECEIVED,
NEW_INBOX_MESSAGE,
NEW_CHAT_MESSAGE,
ACHIEVEMENT_JUST_ADD_WATER,
ACHIEVEMENT_LOST_MASTERCLASSER,
ACHIEVEMENT_MIND_OVER_MATTER,
WorldBoss: WORLD_BOSS,
VERIFY_USERNAME,
OnboardingGuide,
@@ -194,13 +188,24 @@ export default {
// listed in the order they should appear in the notifications panel.
// NOTE: Those not listed here won't be shown in the notification panel!
handledNotifications: [
'NEW_STUFF', 'GIFT_ONE_GET_ONE', 'GROUP_TASK_NEEDS_WORK',
'GUILD_INVITATION', 'PARTY_INVITATION', 'CHALLENGE_INVITATION',
'QUEST_INVITATION', 'GROUP_TASK_ASSIGNED', 'GROUP_TASK_APPROVAL', 'GROUP_TASK_APPROVED',
'GROUP_TASK_CLAIMED', 'NEW_MYSTERY_ITEMS', 'CARD_RECEIVED',
'NEW_INBOX_MESSAGE', 'NEW_CHAT_MESSAGE', 'UNALLOCATED_STATS_POINTS',
'ACHIEVEMENT_JUST_ADD_WATER', 'ACHIEVEMENT_LOST_MASTERCLASSER', 'ACHIEVEMENT_MIND_OVER_MATTER',
'VERIFY_USERNAME', 'ONBOARDING_COMPLETE',
'NEW_STUFF',
'GIFT_ONE_GET_ONE',
'GROUP_TASK_NEEDS_WORK',
'GUILD_INVITATION',
'PARTY_INVITATION',
'CHALLENGE_INVITATION',
'QUEST_INVITATION',
'GROUP_TASK_ASSIGNED',
'GROUP_TASK_APPROVAL',
'GROUP_TASK_APPROVED',
'GROUP_TASK_CLAIMED',
'NEW_MYSTERY_ITEMS',
'CARD_RECEIVED',
'NEW_INBOX_MESSAGE',
'NEW_CHAT_MESSAGE',
'UNALLOCATED_STATS_POINTS',
'VERIFY_USERNAME',
'ONBOARDING_COMPLETE',
],
};
},
@@ -4,7 +4,7 @@
:class="{ condensed, expanded, 'd-flex': isHeader, row: !isHeader, }"
@click="showMemberModal(member)"
>
<div :class="{ 'col-4': !isHeader }">
<div class="avatar-container" :class="{ 'col-4': !isHeader }">
<avatar
:member="member"
:hide-class-badge="classBadgePosition !== 'under-avatar'"
@@ -92,6 +92,10 @@
.member-details {
white-space: nowrap;
transition: all 0.15s ease-out;
.avatar-container {
margin-bottom: 20px;
}
}
.member-stats {
+116 -323
View File
@@ -30,9 +30,6 @@
v-if="notificationData && notificationData.achievement"
:data="notificationData"
/>
<just-add-water />
<lost-masterclasser />
<mind-over-matter />
<onboarding-complete />
<first-drops />
</div>
@@ -141,25 +138,34 @@ import streak from './achievements/streak';
import ultimateGear from './achievements/ultimateGear';
import wonChallenge from './achievements/wonChallenge';
import genericAchievement from './achievements/genericAchievement';
import justAddWater from './achievements/justAddWater';
import lostMasterclasser from './achievements/lostMasterclasser';
import mindOverMatter from './achievements/mindOverMatter';
import loginIncentives from './achievements/login-incentives';
import onboardingComplete from './achievements/onboardingComplete';
import verifyUsername from './settings/verifyUsername';
import firstDrops from './achievements/firstDrops';
const NOTIFICATIONS = {
// general notifications
NEW_CONTRIBUTOR_LEVEL: {
achievement: true,
label: $t => $t('modalContribAchievement'),
modalId: 'contributor',
sticky: true,
},
// achievement notifications
ACHIEVEMENT: { // null data filled in handleUserNotifications
achievement: true,
modalId: 'generic-achievement',
label: null,
data: {
message: $t => $t('achievement'),
modalText: null,
},
},
CHALLENGE_JOINED_ACHIEVEMENT: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('joinedChallenge')}`,
modalId: 'joined-challenge',
},
ULTIMATE_GEAR_ACHIEVEMENT: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('gearAchievementNotification')}`,
modalId: 'ultimate-gear',
},
GUILD_JOINED_ACHIEVEMENT: {
label: $t => `${$t('achievement')}: ${$t('joinedGuild')}`,
achievement: true,
@@ -170,42 +176,14 @@ const NOTIFICATIONS = {
label: $t => `${$t('achievement')}: ${$t('invitedFriend')}`,
modalId: 'invited-friend',
},
NEW_CONTRIBUTOR_LEVEL: {
ACHIEVEMENT_PARTY_ON: {
achievement: true,
label: $t => $t('modalContribAchievement'),
modalId: 'contributor',
sticky: true,
},
ACHIEVEMENT_ALL_YOUR_BASE: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementAllYourBase')}`,
label: $t => `${$t('achievement')}: ${$t('achievementPartyOn')}`,
modalId: 'generic-achievement',
data: {
achievement: 'allYourBase', // defined manually until the server sends all the necessary data
},
},
ACHIEVEMENT_BACK_TO_BASICS: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementBackToBasics')}`,
modalId: 'generic-achievement',
data: {
achievement: 'backToBasics',
},
},
ACHIEVEMENT_DUST_DEVIL: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementDustDevil')}`,
modalId: 'generic-achievement',
data: {
achievement: 'dustDevil',
},
},
ACHIEVEMENT_ARID_AUTHORITY: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementAridAuthority')}`,
modalId: 'generic-achievement',
data: {
achievement: 'aridAuthority',
message: $t => $t('achievement'),
modalText: $t => $t('achievementPartyOn'),
achievement: 'partyOn',
},
},
ACHIEVEMENT_PARTY_UP: {
@@ -218,245 +196,47 @@ const NOTIFICATIONS = {
achievement: 'partyUp',
},
},
ACHIEVEMENT_PARTY_ON: {
ULTIMATE_GEAR_ACHIEVEMENT: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('gearAchievementNotification')}`,
modalId: 'ultimate-gear',
},
ACHIEVEMENT_STABLE: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementPartyOn')}`,
modalId: 'generic-achievement',
data: {
message: $t => $t('achievement'),
modalText: $t => $t('achievementPartyOn'),
achievement: 'partyOn',
achievement: 'stableAchievs',
},
},
ACHIEVEMENT_BEAST_MASTER: {
ACHIEVEMENT_QUESTS: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('beastAchievement')}`,
modalId: 'generic-achievement',
data: {
message: $t => $t('achievement'),
modalText: $t => $t('beastAchievement'),
achievement: 'beastMaster',
achievement: 'questSeriesAchievs',
},
},
ACHIEVEMENT_MOUNT_MASTER: {
ACHIEVEMENT_ANIMAL_SET: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('mountAchievement')}`,
label: $t => `${$t('achievement')}: ${$t('achievementAnimalSet')}`,
modalId: 'generic-achievement',
data: {
message: $t => $t('achievement'),
modalText: $t => $t('mountAchievement'),
achievement: 'mountMaster',
achievement: 'animalSetAchievs',
},
},
ACHIEVEMENT_TRIAD_BINGO: {
ACHIEVEMENT_PET_COLOR: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('triadBingoAchievement')}`,
label: $t => `${$t('achievement')}: ${$t('achievementPetColor')}`,
modalId: 'generic-achievement',
data: {
message: $t => $t('achievement'),
modalText: $t => $t('triadBingoAchievement'),
achievement: 'triadBingo',
achievement: 'petColorAchievs',
},
},
ACHIEVEMENT_MONSTER_MAGUS: {
ACHIEVEMENT_MOUNT_COLOR: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementMonsterMagus')}`,
label: $t => `${$t('achievement')}: ${$t('achievementMountColor')}`,
modalId: 'generic-achievement',
data: {
achievement: 'monsterMagus',
},
},
ACHIEVEMENT_UNDEAD_UNDERTAKER: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementUndeadUndertaker')}`,
modalId: 'generic-achievement',
data: {
achievement: 'undeadUndertaker',
},
},
ACHIEVEMENT: { // data filled in handleUserNotifications
achievement: true,
modalId: 'generic-achievement',
label: null, // data filled in handleUserNotifications
data: {
message: $t => $t('achievement'),
modalText: null, // data filled in handleUserNotifications
},
},
ACHIEVEMENT_PRIMED_FOR_PAINTING: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementPrimedForPainting')}`,
modalId: 'generic-achievement',
data: {
achievement: 'primedForPainting',
},
},
ACHIEVEMENT_PEARLY_PRO: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementPearlyPro')}`,
modalId: 'generic-achievement',
data: {
achievement: 'pearlyPro',
},
},
ACHIEVEMENT_TICKLED_PINK: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementTickledPink')}`,
modalId: 'generic-achievement',
data: {
achievement: 'tickledPink',
},
},
ACHIEVEMENT_ROSY_OUTLOOK: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementRosyOutlook')}`,
modalId: 'generic-achievement',
data: {
achievement: 'rosyOutlook',
},
},
ACHIEVEMENT_BUG_BONANZA: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementBugBonanza')}`,
modalId: 'generic-achievement',
data: {
achievement: 'bugBonanza',
},
},
ACHIEVEMENT_BARE_NECESSITIES: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementBareNecessities')}`,
modalId: 'generic-achievement',
data: {
achievement: 'bareNecessities',
},
},
ACHIEVEMENT_FRESHWATER_FRIENDS: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementFreshwaterFriends')}`,
modalId: 'generic-achievement',
data: {
achievement: 'freshwaterFriends',
},
},
ACHIEVEMENT_GOOD_AS_GOLD: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementGoodAsGold')}`,
modalId: 'generic-achievement',
data: {
achievement: 'goodAsGold',
},
},
ACHIEVEMENT_ALL_THAT_GLITTERS: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementAllThatGlitters')}`,
modalId: 'generic-achievement',
data: {
achievement: 'allThatGlitters',
},
},
ACHIEVEMENT_BONE_COLLECTOR: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementBoneCollector')}`,
modalId: 'generic-achievement',
data: {
achievement: 'boneCollector',
},
},
ACHIEVEMENT_SKELETON_CREW: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementSkeletonCrew')}`,
modalId: 'generic-achievement',
data: {
achievement: 'skeletonCrew',
},
},
ACHIEVEMENT_SEEING_RED: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementSeeingRed')}`,
modalId: 'generic-achievement',
data: {
achievement: 'seeingRed',
},
},
ACHIEVEMENT_RED_LETTER_DAY: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementRedLetterDay')}`,
modalId: 'generic-achievement',
data: {
achievement: 'redLetterDay',
},
},
ACHIEVEMENT_LEGENDARY_BESTIARY: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementLegendaryBestiary')}`,
modalId: 'generic-achievement',
data: {
achievement: 'legendaryBestiary',
},
},
ACHIEVEMENT_SEASONAL_SPECIALIST: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementSeasonalSpecialist')}`,
modalId: 'generic-achievement',
data: {
achievement: 'seasonalSpecialist',
},
},
ACHIEVEMENT_VIOLETS_ARE_BLUE: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementVioletsAreBlue')}`,
modalId: 'generic-achievement',
data: {
achievement: 'violetsAreBlue',
},
},
ACHIEVEMENT_WILD_BLUE_YONDER: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementWildBlueYonder')}`,
modalId: 'generic-achievement',
data: {
achievement: 'wildBlueYonder',
},
},
ACHIEVEMENT_DOMESTICATED: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementDomesticated')}`,
modalId: 'generic-achievement',
data: {
achievement: 'domesticated',
},
},
ACHIEVEMENT_SHADY_CUSTOMER: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementShadyCustomer')}`,
modalId: 'generic-achievement',
data: {
achievement: 'shadyCustomer',
},
},
ACHIEVEMENT_SHADE_OF_IT_ALL: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementShadeOfItAll')}`,
modalId: 'generic-achievement',
data: {
achievement: 'shadeOfItAll',
},
},
ACHIEVEMENT_ZODIAC_ZOOKEEPER: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementZodiacZookeeper')}`,
modalId: 'generic-achievement',
data: {
achievement: 'zodiacZookeeper',
},
},
ACHIEVEMENT_BIRDS_OF_A_FEATHER: {
achievement: true,
label: $t => `${$t('achievement')}: ${$t('achievementBirdsOfAFeather')}`,
modalId: 'generic-achievement',
data: {
achievement: 'birdsOfAFeather',
achievement: 'mountColorAchievs',
},
},
};
@@ -486,9 +266,6 @@ export default {
loginIncentives,
verifyUsername,
genericAchievement,
lostMasterclasser,
mindOverMatter,
justAddWater,
onboardingComplete,
firstDrops,
},
@@ -509,21 +286,30 @@ export default {
const handledNotifications = {};
[
'GUILD_PROMPT', 'REBIRTH_ENABLED', 'WON_CHALLENGE', 'STREAK_ACHIEVEMENT',
'ULTIMATE_GEAR_ACHIEVEMENT', 'REBIRTH_ACHIEVEMENT', 'GUILD_JOINED_ACHIEVEMENT',
'CHALLENGE_JOINED_ACHIEVEMENT', 'INVITED_FRIEND_ACHIEVEMENT', 'NEW_CONTRIBUTOR_LEVEL',
'CRON', 'LOGIN_INCENTIVE', 'ACHIEVEMENT_ALL_YOUR_BASE', 'ACHIEVEMENT_BACK_TO_BASICS',
'GENERIC_ACHIEVEMENT', 'ACHIEVEMENT_PARTY_UP', 'ACHIEVEMENT_PARTY_ON', 'ACHIEVEMENT_BEAST_MASTER',
'ACHIEVEMENT_MOUNT_MASTER', 'ACHIEVEMENT_TRIAD_BINGO', 'ACHIEVEMENT_DUST_DEVIL', 'ACHIEVEMENT_ARID_AUTHORITY',
'ACHIEVEMENT_MONSTER_MAGUS', 'ACHIEVEMENT_UNDEAD_UNDERTAKER', 'ACHIEVEMENT_PRIMED_FOR_PAINTING',
'ACHIEVEMENT_PEARLY_PRO', 'ACHIEVEMENT_TICKLED_PINK', 'ACHIEVEMENT_ROSY_OUTLOOK', 'ACHIEVEMENT',
'ONBOARDING_COMPLETE', 'FIRST_DROPS', 'ACHIEVEMENT_BUG_BONANZA', 'ACHIEVEMENT_BARE_NECESSITIES',
'ACHIEVEMENT_FRESHWATER_FRIENDS', 'ACHIEVEMENT_GOOD_AS_GOLD', 'ACHIEVEMENT_ALL_THAT_GLITTERS',
'ACHIEVEMENT_BONE_COLLECTOR', 'ACHIEVEMENT_SKELETON_CREW', 'ACHIEVEMENT_SEEING_RED',
'ACHIEVEMENT_RED_LETTER_DAY', 'ACHIEVEMENT_LEGENDARY_BESTIARY', 'ACHIEVEMENT_SEASONAL_SPECIALIST',
'ACHIEVEMENT_VIOLETS_ARE_BLUE', 'ACHIEVEMENT_WILD_BLUE_YONDER', 'ACHIEVEMENT_DOMESTICATED',
'ACHIEVEMENT_SHADY_CUSTOMER', 'ACHIEVEMENT_SHADE_OF_IT_ALL', 'ACHIEVEMENT_ZODIAC_ZOOKEEPER',
'ACHIEVEMENT_BIRDS_OF_A_FEATHER',
// general notifications
'CRON',
'FIRST_DROPS',
'GUILD_PROMPT',
'LOGIN_INCENTIVE',
'NEW_CONTRIBUTOR_LEVEL',
'ONBOARDING_COMPLETE',
'REBIRTH_ENABLED',
'WON_CHALLENGE',
// achievement notifications
'ACHIEVEMENT',
'CHALLENGE_JOINED_ACHIEVEMENT',
'GUILD_JOINED_ACHIEVEMENT',
'INVITED_FRIEND_ACHIEVEMENT',
'ACHIEVEMENT_PARTY_ON',
'ACHIEVEMENT_PARTY_UP',
'REBIRTH_ACHIEVEMENT',
'STREAK_ACHIEVEMENT',
'ULTIMATE_GEAR_ACHIEVEMENT',
'ACHIEVEMENT_STABLE',
'ACHIEVEMENT_QUESTS',
'ACHIEVEMENT_ANIMAL_SET',
'ACHIEVEMENT_PET_COLOR',
'ACHIEVEMENT_MOUNT_COLOR',
].forEach(type => {
handledNotifications[type] = true;
});
@@ -921,57 +707,68 @@ export default {
case 'WON_CHALLENGE':
this.$root.$emit('habitica:won-challenge', notification);
break;
case 'REBIRTH_ACHIEVEMENT':
this.playSound('Achievement_Unlocked');
this.$root.$emit('bv::show::modal', 'rebirth');
break;
case 'STREAK_ACHIEVEMENT':
this.text(`${this.$t('streaks')}: ${this.user.achievements.streak}`, () => {
this.$root.$emit('bv::show::modal', 'streak');
}, this.user.preferences.suppressModals.streak);
this.playSound('Achievement_Unlocked');
break;
case 'REBIRTH_ACHIEVEMENT':
this.playSound('Achievement_Unlocked');
this.$root.$emit('bv::show::modal', 'rebirth');
break;
case 'ULTIMATE_GEAR_ACHIEVEMENT':
case 'GUILD_JOINED_ACHIEVEMENT':
case 'CHALLENGE_JOINED_ACHIEVEMENT':
case 'INVITED_FRIEND_ACHIEVEMENT':
case 'NEW_CONTRIBUTOR_LEVEL':
case 'ACHIEVEMENT_ALL_YOUR_BASE':
case 'ACHIEVEMENT_BACK_TO_BASICS':
case 'ACHIEVEMENT_DUST_DEVIL':
case 'ACHIEVEMENT_ARID_AUTHORITY':
case 'ACHIEVEMENT_PARTY_UP':
case 'CHALLENGE_JOINED_ACHIEVEMENT':
case 'GUILD_JOINED_ACHIEVEMENT':
case 'INVITED_FRIEND_ACHIEVEMENT':
case 'ACHIEVEMENT_PARTY_ON':
case 'ACHIEVEMENT_BEAST_MASTER':
case 'ACHIEVEMENT_MOUNT_MASTER':
case 'ACHIEVEMENT_TRIAD_BINGO':
case 'ACHIEVEMENT_MONSTER_MAGUS':
case 'ACHIEVEMENT_UNDEAD_UNDERTAKER':
case 'ACHIEVEMENT_PRIMED_FOR_PAINTING':
case 'ACHIEVEMENT_PEARLY_PRO':
case 'ACHIEVEMENT_TICKLED_PINK':
case 'ACHIEVEMENT_ROSY_OUTLOOK':
case 'ACHIEVEMENT_BUG_BONANZA':
case 'ACHIEVEMENT_BARE_NECESSITIES':
case 'ACHIEVEMENT_FRESHWATER_FRIENDS':
case 'ACHIEVEMENT_GOOD_AS_GOLD':
case 'ACHIEVEMENT_ALL_THAT_GLITTERS':
case 'ACHIEVEMENT_BONE_COLLECTOR':
case 'ACHIEVEMENT_SKELETON_CREW':
case 'ACHIEVEMENT_SEEING_RED':
case 'ACHIEVEMENT_RED_LETTER_DAY':
case 'ACHIEVEMENT_LEGENDARY_BESTIARY':
case 'ACHIEVEMENT_SEASONAL_SPECIALIST':
case 'ACHIEVEMENT_VIOLETS_ARE_BLUE':
case 'ACHIEVEMENT_WILD_BLUE_YONDER':
case 'ACHIEVEMENT_DOMESTICATED':
case 'ACHIEVEMENT_SHADY_CUSTOMER':
case 'ACHIEVEMENT_SHADE_OF_IT_ALL':
case 'ACHIEVEMENT_ZODIAC_ZOOKEEPER':
case 'ACHIEVEMENT_BIRDS_OF_A_FEATHER':
case 'GENERIC_ACHIEVEMENT':
case 'ACHIEVEMENT_PARTY_UP':
case 'ULTIMATE_GEAR_ACHIEVEMENT':
this.showNotificationWithModal(notification);
break;
case 'ACHIEVEMENT_QUESTS': {
const { achievement } = notification.data;
const upperCaseAchievement = achievement.charAt(0).toUpperCase() + achievement.slice(1);
const achievementTitleKey = `achievement${upperCaseAchievement}`;
NOTIFICATIONS.ACHIEVEMENT_QUESTS.label = $t => `${$t('achievement')}: ${$t(achievementTitleKey)}`;
this.showNotificationWithModal(notification);
Vue.set(this.user.achievements, achievement, true);
break;
}
case 'ACHIEVEMENT_STABLE': {
const { achievement, achievementNotification } = notification.data;
NOTIFICATIONS.ACHIEVEMENT_STABLE.label = $t => `${$t('achievement')}: ${$t(achievementNotification)}`;
this.showNotificationWithModal(notification);
Vue.set(this.user.achievements, achievement, true);
break;
}
case 'ACHIEVEMENT_ANIMAL_SET': {
const { achievement } = notification.data;
const upperCaseAchievement = achievement.charAt(0).toUpperCase() + achievement.slice(1);
const achievementTitleKey = `achievement${upperCaseAchievement}`;
NOTIFICATIONS.ACHIEVEMENT_ANIMAL_SET.label = $t => `${$t('achievement')}: ${$t(achievementTitleKey)}`;
this.showNotificationWithModal(notification);
Vue.set(this.user.achievements, achievement, true);
break;
}
case 'ACHIEVEMENT_PET_COLOR': {
const { achievement } = notification.data;
const upperCaseAchievement = achievement.charAt(0).toUpperCase() + achievement.slice(1);
const achievementTitleKey = `achievement${upperCaseAchievement}`;
NOTIFICATIONS.ACHIEVEMENT_PET_COLOR.label = $t => `${$t('achievement')}: ${$t(achievementTitleKey)}`;
this.showNotificationWithModal(notification);
Vue.set(this.user.achievements, achievement, true);
break;
}
case 'ACHIEVEMENT_MOUNT_COLOR': {
const { achievement } = notification.data;
const upperCaseAchievement = achievement.charAt(0).toUpperCase() + achievement.slice(1);
const achievementTitleKey = `achievement${upperCaseAchievement}`;
NOTIFICATIONS.ACHIEVEMENT_MOUNT_COLOR.label = $t => `${$t('achievement')}: ${$t(achievementTitleKey)}`;
this.showNotificationWithModal(notification);
Vue.set(this.user.achievements, achievement, true);
break;
}
case 'ACHIEVEMENT': { // generic achievement
const { achievement } = notification.data;
const upperCaseAchievement = achievement.charAt(0).toUpperCase() + achievement.slice(1);
@@ -984,10 +781,6 @@ export default {
Vue.set(this.user.achievements, achievement, true);
break;
}
case 'CRON':
// Not needed because it's shown already by the userHp and userMp watchers
// Keeping an empty block so that it gets read
break;
case 'LOGIN_INCENTIVE':
if (this.user.flags.tour.intro === this.TOUR_END && this.user.flags.welcomed) {
this.notificationData = notification.data;
@@ -198,7 +198,7 @@ export default {
appState.newGroup = false;
appState.group = pick(this.amazonPayments.group, ['_id', 'memberCount', 'name']);
}
} else if (paymentType.indexOf('gift-') === 0) {
} else if (paymentType && paymentType.indexOf('gift-') === 0) {
appState.gift = this.amazonPayments.gift;
appState.giftReceiver = this.amazonPayments.giftReceiver;
} else if (paymentType === 'gems') {
@@ -1,5 +1,6 @@
<template>
<div class="payments-column mx-auto mt-auto">
<h4>{{ $t('choosePaymentMethod') }}</h4>
<button
v-if="stripeAvailable"
class="btn btn-primary payment-button payment-item with-icon"
@@ -80,6 +81,13 @@
cursor: default !important;
}
}
h4 {
font-size: 0.875rem;
font-weight: bold;
text-align: center;
margin-bottom: 1rem;
}
</style>
<script>
@@ -14,15 +14,44 @@
</div>
<h2
v-else
class="ml-2"
class="d-flex flex-column mx-auto align-items-center"
>
{{ $t('sendGift') }}
{{ $t('sendAGift') }}
</h2>
<div
v-if="currentEvent && currentEvent.promo === 'g1g1'"
class="g1g1-margin d-flex flex-column align-items-center"
>
<div
class="svg-big-gift"
v-once
v-html="icons.bigGift"
></div>
</div>
<div
v-else
class="d-flex flex-column align-items-center">
<div
class="svg-big-gift"
v-once
v-html="icons.bigGift"
></div>
</div>
<div class="d-flex flex-column align-items-center">
<div
class="modal-close"
v-if="currentEvent && currentEvent.promo === 'g1g1'"
class="g1g1-modal-close"
@click="close()"
>
<div
class="g1g1-svg-icon"
v-html="icons.close"
></div>
</div>
<div
v-else
class="modal-close"
@click="close()">
<div
class="svg-icon"
v-html="icons.close"
@@ -42,6 +71,7 @@
v-model="userSearchTerm"
class="form-control"
type="text"
ref="textBox"
:placeholder="$t('usernameOrUserId')"
:class="{
'input-valid': foundUser._id,
@@ -70,15 +100,20 @@
<div
v-else
>
{{ $t('selectGift') }}
{{ $t('next') }}
</div>
</button>
<a
class="cancel-link mx-auto mt-3"
@click="close()"
<div
v-if="currentEvent && currentEvent.promo ==='g1g1'"
class="g1g1-cancel d-flex justify-content-center"
v-html="$t('cancel')"
@click="close()"
>
{{ $t('cancel') }}
</a>
{{ $t('cancel') }}
</div>
<div
v-else>
</div>
</div>
</div>
</div>
@@ -110,13 +145,16 @@
@import '~@/assets/scss/mixins.scss';
#select-user-modal {
.modal-content {
width:448px;
}
.input-group {
margin-top: 0rem;
}
.modal-dialog {
width: 29.5rem;
margin-top: 25vh;
width: 448px;
}
.modal-footer {
@@ -126,7 +164,16 @@
margin: 0rem 0.25rem 0.25rem 0.25rem;
}
}
}
body.modal-open .modal {
display: flex !important;
height: 100%;
}
body.modal-open .modal .modal-dialog {
margin: auto;
}
}
</style>
<style lang="scss" scoped>
@@ -146,12 +193,12 @@
.g1g1 {
background-image: url('~@/assets/images/g1g1-send.png');
background-size: 472px 152px;
width: 470px;
background-size: 446px 152px;
width: 446px;
height: 152px;
margin: -1rem 0rem 0rem -1rem;
border-radius: 0.3rem 0.3rem 0rem 0rem;
padding: 1.5rem;
margin: -16px 0px 0px -16px;
border-radius: 4.8px 4.8px 0px 0px;
padding: 24px;
color: $white;
h1 {
@@ -169,6 +216,16 @@
}
}
.g1g1-margin {
margin-top: 24px;
}
.g1g1-cancel {
margin-top: 16px;
color: $blue-10;
cursor: pointer;
}
.g1g1-fine-print {
color: $gray-100;
background-color: $gray-700;
@@ -176,6 +233,29 @@
line-height: 1.33;
}
.g1g1-modal-close {
position: absolute;
width: 18px;
height: 18px;
padding: 4px;
right: 16px;
top: 16px;
cursor: pointer;
.g1g1-svg-icon {
width: 12px;
height: 12px;
& ::v-deep svg path {
fill: #FFFFFF;
}
}
}
.g1g1-modal-dialog {
margin-top: 10vh;
}
.input-error {
color: $red-50;
font-size: 90%;
@@ -192,6 +272,18 @@
border-color: $purple-500;
}
h2 {
font-size: 1.25rem;
line-height: 1.75rem;
color: $purple-300;
padding-top: 1rem;
}
.svg-big-gift {
width: 176px;
height: 64px;
}
.modal-close {
position: absolute;
width: 18px;
@@ -206,14 +298,17 @@
height: 12px;
}
}
</style>
<script>
// import { nextTick } from 'vue'; // may not need this? I don't know!
import debounce from 'lodash/debounce';
import find from 'lodash/find';
import isUUID from 'validator/lib/isUUID';
import { mapState } from '@/libs/store';
import closeIcon from '@/assets/svg/close.svg';
import bigGiftIcon from '@/assets/svg/big-gift.svg';
export default {
data () {
@@ -223,6 +318,7 @@ export default {
foundUser: {},
icons: Object.freeze({
close: closeIcon,
bigGift: bigGiftIcon,
}),
};
},
@@ -281,7 +377,7 @@ export default {
this.foundUser = result;
}, 500),
selectUser () {
this.$root.$emit('habitica::send-gems', this.foundUser);
this.$root.$emit('habitica::send-gift', this.foundUser);
this.close();
},
onHide () {
@@ -0,0 +1,659 @@
<template>
<b-modal
id="send-gift"
:hide-footer="true"
:hide-header="true"
size="md"
@hide="onHide()"
>
<div>
<!-- header -->
<div
class="modal-close"
@click="close()"
>
<div
class="icon-close"
v-html="icons.closeIcon"
>
</div>
</div>
<div>
<h2 class="d-flex flex-column mx-auto align-items-center">
{{ $t('sendAGift') }}
</h2>
</div>
<!-- user avatar -->
<div
v-if="userReceivingGift"
class="modal-body"
>
<avatar
:member="userReceivingGift"
:hideClassBadge="true"
class="d-flex flex-column mx-auto align-items-center"
/>
<div class="avatar-spacer"></div>
<div class="d-flex flex-column mx-auto align-items-center display-name">
<!-- user display name and username -->
<user-link
:user-id="displayName"
:name="displayName"
:backer="userBacker"
:contributor="userContributor"
:class="display-name"
/>
</div>
<div class="d-flex flex-column mx-auto align-items-center user-name">
@{{ userName }}
</div>
</div>
<!-- menu area -->
<div class="row">
<div class="col-md-8 offset-md-2 text-center nav">
<div
class="nav-link"
:class="{active: selectedPage === 'subscription'}"
@click="selectPage('subscription')"
>
{{ $t('subscription') }}
</div>
<div
class="nav-link"
:class="{active: selectedPage !== 'subscription'}"
@click="selectPage('buyGems')"
>
{{ $t('gems') }}
</div>
</div>
</div>
<!-- subscriber block -->
<subscription-options
v-show="selectedPage === 'subscription'"
class="subscribe-option"
:userReceivingGift="userReceivingGift"
/>
<!-- gem block -->
<div
v-show="selectedPage === 'buyGems'"
>
<div class="gem-group">
<!-- buy gems with money -->
<label v-once>
{{ $t('howManyGemsPurchase') }}
</label>
<div class="d-flex flex-row align-items-center justify-content-center">
<div
class="gray-circle"
@click="gift.gems.amount <= 0
? gift.gems.amount = 0
: gift.gems.amount--"
>
<div
class="icon-negative"
v-html="icons.negativeIcon"
></div>
</div>
<div class="input-group">
<div class="input-group-prepend input-group-icon align-items-center">
<div
class="icon-gem"
v-html="icons.gemIcon"
></div>
</div>
<input
id="gemsForm"
v-model.number="gift.gems.amount"
class="form-control"
max="9999"
>
</div>
<div
class="gray-circle"
@click="gift.gems.amount++"
>
<div
class="icon-positive"
v-html="icons.positiveIcon"
></div>
</div>
</div>
<!-- the word "total" -->
<div class="buy-gem-total">
{{ $t('sendGiftTotal') }}
</div>
<!-- the actual dollar amount -->
<div class="buy-gem-amount">
<span>
{{ formatter.format(totalGems) }}
</span>
</div>
<!-- change to sending own gems page -->
<div
:class="{active: selectedPage === 'ownGems'}"
class="gem-state-change"
@click="selectPage('ownGems')"
>
{{ $t('wantToSendOwnGems') }}
</div>
</div>
<!-- paying for gems -->
<payments-buttons
class="payment-buttons"
:stripe-fn="() => redirectToStripe({gift, uuid: userReceivingGift._id, receiverName})"
:paypal-fn="() => openPaypalGift({
gift: gift, giftedTo: userReceivingGift._id, receiverName,
})"
:amazon-data="{type: 'single', gift, giftedTo: userReceivingGift._id, receiverName}"
/>
</div>
</div>
<!-- send gems from balance -->
<div
v-show="selectedPage === 'ownGems'"
>
<div class="gem-group">
<label v-once>
{{ $t('howManyGemsSend') }}
</label>
<div class="d-flex align-items-center justify-content-center">
<div
class="gray-circle"
@click="gift.gems.amount <= 0
? gift.gems.amount = 0
: gift.gems.amount--"
>
<div
class="icon-negative"
v-html="icons.negativeIcon"
></div>
</div>
<div class="input-group">
<div class="input-group-prepend input-group-icon align-items-center">
<div
class="icon-gem"
v-html="icons.gemIcon"
></div>
</div>
<input
id="gemsForm"
v-model="gift.gems.amount"
class="form-control"
:max="maxGems"
>
</div>
<div
class="gray-circle"
@click="gift.gems.amount < maxGems
? gift.gems.amount++
: gift.gems.amount = maxGems"
>
<div
class="icon-positive"
v-html="icons.positiveIcon"
></div>
</div>
</div>
<div class="align-items-middle">
<div class="d-flex justify-content-center align-items-middle">
<span class="balance-text">
{{ $t('yourBalance') }}
</span>
<span
class="icon-gem balance-gem-margin"
style="display: inline-block;"
v-html="icons.gemIcon"
></span>
<span
class="balance-gems"
>
{{ maxGems }}
</span>
</div>
</div>
<div class="d-flex flex-column justify-content-center align-items-middle mt-3">
<button
v-if="fromBal"
class="btn btn-primary mx-auto mt-2"
type="submit"
:disabled="sendingInProgress"
@click="sendGift()"
>
{{ $t("send") }}
</button>
</div>
<!-- change to buying gems page -->
<div
:class="{active: selectedPage === 'buyGems'}"
class="gem-state-change"
@click="selectPage('buyGems')"
>
{{ $t('needToPurchaseGems') }}
</div>
</div>
</div>
</b-modal>
</template>
<style lang="scss">
@import '~@/assets/scss/mixins.scss';
#send-gift {
.modal-dialog {
max-width: 448px;
}
.modal-content {
width: 448px;
border-radius: 8px;
box-shadow: 0 14px 28px 0 rgba(26, 24, 29, 0.24), 0 10px 10px 0 rgba(26, 24, 29, 0.28);
}
.modal-body{
padding: 0px;
}
.modal-close {
position: absolute;
right: 16px;
top: 16px;
cursor: pointer;
.icon-close {
width: 18px;
height: 18px;
vertical-align: middle;
& ::v-deep svg path {
fill: #878190;
}
& :hover {
fill: #686274;
}
}
}
#subscription-form .subscribe-option {
background: #F9F9F9;
}
#subscription-form .selected {
background: rgba(213, 200, 255, 0.32);
// using rgba for transparency
}
}
</style>
<style scoped lang="scss">
@import '~@/assets/scss/colors.scss';
h2 {
color: $purple-300;
padding-top: 2rem;
}
.avatar-spacer {
height: 9px;
}
.display-name {
font-size: 0.875rem;
font-weight: bold;
line-height: 1.71;
margin: 0px 6px 0 20px;
}
.display-name a:hover{
text-decoration: none;
}
.user-name {
font-size: 0.75rem;
line-height: 1.33;
text-align: center;
color: $gray-100;
padding-bottom: 16px;
}
.row {
background-color: $gray-700;
margin: 0 0 0 0;
min-height: 32px;
}
.nav {
font-weight: bold;
font-size: 0.75rem;
min-height: 32px;
padding: 16px 0 0 0;
justify-content: center;
}
.nav-link {
color: $gray-100;
display: inline-block;
padding: 0px 8px 6px 8px;
&.active {
color: $purple-300;
border-bottom: 2px solid $purple-400;
}
&:hover {
color: $purple-300;
border-bottom: 2px solid $purple-400;
cursor: pointer;
}
}
.gem-group {
padding: 0 0 24px 0;
background-color: $gray-700;
margin: 0 0 0 0;
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px
}
label {
color: $gray-50;
font-size: 0.875rem;
font-weight: bold;
line-height: 1.71;
margin: 12px 0 16px 0;
width: 100%;
text-align: center;
}
.input-group {
width: 94px;
height: 32px;
margin: 0px 16px 0px 16px;
padding: 0;
border-radius: 2px;
border: solid 1px $gray-400;
background-color: $white;
}
.gray-circle {
border-radius: 100%;
border: solid 2px $gray-300;
width: 32px;
height: 32px;
cursor: pointer;
&:hover {
border-color: $purple-400;
}
}
.gray-circle:hover{
.icon-positive, .icon-negative {
& ::v-deep svg path {
fill: $purple-400;
}
}
}
.icon-gem {
width: 16px;
height: 16px;
margin-bottom: 4px;
}
.icon-positive, .icon-negative {
width: 10px;
height: 10px;
margin: 4px auto;
& ::v-deep svg path {
fill: $gray-300;
}
}
.buy-gem-total {
font-size: 0.875rem;
font-weight: bold;
line-height: 1.71;
padding-top: 24px;
text-align: center;
height: 28px;
}
.buy-gem-amount {
font-size: 1.25rem;
font-weight: bold;
line-height: 1.4;
margin: 16px 0 24px 0;
text-align: center;
height: 28px;
color: $green-10;
}
.balance-text {
font-size: 0.75rem;
font-weight: bold;
color: $gray-100;
line-height: 1.33;
margin: 12px 0px 0px 70px;
}
.balance-gem-margin {
margin: 8px 4px 0px 8px;
}
.balance-gems {
font-size: 0.75rem;
color: $gray-100;
line-height: 1.33;
margin: 12px 71px 0px 4px;
}
.gem-state-change {
color: $blue-10;
font-size: 0.875rem;
min-height: 24px;
margin: 16px 0 0;
text-align: center;
cursor: pointer;
}
.subscribe-option {
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
padding-bottom: 24px;
}
.payment-buttons {
padding: 24px 0;
}
</style>
<script>
// libs imports
import { mapState } from '@/libs/store';
// mixins imports
import paymentsMixin from '../../mixins/payments';
// component imports
import avatar from '../avatar';
import userLink from '../userLink';
import subscriptionOptions from '../settings/subscriptionOptions.vue';
import paymentsButtons from '@/components/payments/buttons/list';
// svg imports
import closeIcon from '@/assets/svg/close.svg';
import gemIcon from '@/assets/svg/gem.svg';
import positiveIcon from '@/assets/svg/positive.svg';
import negativeIcon from '@/assets/svg/negative.svg';
export default {
components: {
avatar,
subscriptionOptions,
paymentsButtons,
userLink,
},
mixins: [
paymentsMixin,
],
data () {
return {
subscription: {
key: '',
},
icons: Object.freeze({
closeIcon,
gemIcon,
positiveIcon,
negativeIcon,
}),
userReceivingGift: {
profile: '',
},
name: '',
display: '',
selectedPage: 'subscription',
gift: {
type: 'gems',
gems: {
amount: 0,
fromBalance: true,
},
},
sendingInProgress: false,
amazonPayments: {},
gemCost: 1,
};
},
computed: {
...mapState({
userLoggedIn: 'user.data',
}),
userName () {
const userName = this.userReceivingGift.auth
&& this.userReceivingGift.auth.local
&& this.userReceivingGift.auth.local.username;
return userName;
},
displayName () {
const displayName = this.userReceivingGift.profile.name;
return displayName;
},
userBacker () {
const userBacker = this.userReceivingGift.backer;
return userBacker;
},
userContributor () {
const userContributor = this.userReceivingGift.contributor;
return userContributor;
},
tierIcon () {
if (this.isNPC) {
return this.icons.tierNPC;
}
return this.icons[`tier${this.level}`];
},
fromBal () {
return this.gift.type === 'gems' && this.gift.gems.fromBalance;
},
maxGems () {
const maxGems = this.fromBal ? this.userLoggedIn.balance * 4 : 9999;
return maxGems;
},
formatter () {
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
});
return formatter;
},
totalGems () {
const totalGems = this.gift.gems.amount * 0.25;
return totalGems;
},
receiverName () {
if (
this.userReceivingGift.auth
&& this.userReceivingGift.auth.local
&& this.userReceivingGift.auth.local.username
) {
return this.userReceivingGift.auth.local.username;
}
return this.userReceivingGift.profile.name;
},
},
watch: {
startingPage () {
this.selectedPage = this.startingPage;
},
},
mounted () {
this.$root.$on('habitica::send-gift', data => {
this.userReceivingGift = data;
if (this.$store.state.giftModalOptions.startingPage) {
this.selectedPage = this.$store.state.giftModalOptions.startingPage;
this.$store.state.giftModalOptions.startingPage = '';
this.selectPage(this.selectedPage);
} else {
this.selectPage(this.startingPage);
}
this.setGemDefaults();
this.$root.$emit('bv::show::modal', 'send-gift');
});
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'send-gift');
},
setGemDefaults () {
if (this.selectedPage === 'buyGems') {
this.gift.gems.amount = 20;
} else if (this.selectedPage === 'ownGems') {
this.gift.gems.amount = 1;
} else {
this.gift.gems.amount = 0;
}
},
selectPage (page) {
if (page === this.selectedPage) return;
if (page === 'buyGems') this.selectedPage = 'buyGems';
if (page === 'buyGems' && this.selectedPage === 'ownGems') return;
this.selectedPage = page || 'subscription';
this.setGemDefaults();
},
async sendGift () {
this.sendingInProgress = true;
await this.$store.dispatch('members:transferGems', {
toUserId: this.userReceivingGift._id,
gemAmount: this.gift.gems.amount,
});
this.close();
setTimeout(() => { // wait for the send gem modal to be closed
this.$root.$emit('habitica:payment-success', {
paymentMethod: 'balance',
paymentCompleted: true,
paymentType: 'gift-gems-balance',
gift: {
gems: {
amount: this.gift.gems.amount,
},
},
giftReceiver: this.receiverName,
});
}, 500);
},
onHide () {
this.sendingInProgress = false;
},
},
};
</script>
@@ -739,6 +739,14 @@ export default {
} else if (attribute === 'email') {
this.user.auth.local.email = updates.newEmail;
window.alert(this.$t('emailSuccess')); // eslint-disable-line no-alert
} else if (attribute === 'password') {
this.passwordUpdates = {};
this.$store.dispatch('snackbars:add', {
title: 'Habitica',
text: this.$t('passwordSuccess'),
type: 'success',
timeout: true,
});
}
},
async changeDisplayName (newName) {
@@ -450,10 +450,6 @@
background-color: $white;
}
.subscribe-option {
border-bottom: 1px solid $gray-600;
}
.svg-amazon-pay {
width: 208px;
}
@@ -10,10 +10,17 @@
:value="block.key"
class="subscribe-option pt-2 pl-5 pb-3 mb-0"
:class="{selected: subscription.key === block.key}"
@click.native="subscription.key = block.key"
@click.native="updateSubscriptionData(block.key)"
>
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div
v-if="userReceivingGift && userReceivingGift._id"
class="subscription-text ml-2 mb-1"
v-html="$t('giftSubscriptionRateText', {price: block.price, months: block.months})"
>
</div>
<div
v-else
class="subscription-text ml-2 mb-1"
v-html="$t('subscriptionRateText', {price: block.price, months: block.months})"
>
@@ -25,7 +32,18 @@
</div>
</b-form-radio>
</b-form-group>
<!-- payment buttons first is for gift subs and the second is for renewing subs -->
<payments-buttons
v-if="userReceivingGift && userReceivingGift._id"
:disabled="!subscription.key"
:stripe-fn="() => redirectToStripe({gift, uuid: userReceivingGift._id, receiverName})"
:paypal-fn="() => openPaypalGift({
gift: gift, giftedTo: userReceivingGift._id, receiverName,
})"
:amazon-data="{type: 'single', gift, giftedTo: userReceivingGift._id, receiverName}"
/>
<payments-buttons
v-else
:disabled="!subscription.key"
:stripe-fn="() => redirectToStripe({
subscription: subscription.key,
@@ -43,6 +61,7 @@
<style lang="scss">
@import '~@/assets/scss/colors.scss';
#subscription-form {
.custom-control .custom-control-label::before,
.custom-radio .custom-control-input:checked ~ .custom-control-label::after {
@@ -101,11 +120,22 @@ export default {
mixins: [
paymentsMixin,
],
props: {
userReceivingGift: {
type: Object,
default () {},
},
},
data () {
return {
subscription: {
key: null,
key: 'basic_earned',
},
gift: {
type: 'subscription',
subscription: { key: 'basic_earned' },
},
receiverName: '',
};
},
computed: {
@@ -114,7 +144,6 @@ export default {
},
subscriptionBlocksOrdered () {
const subscriptions = filter(subscriptionBlocks, o => o.discount !== true);
return sortBy(subscriptions, [o => o.months]);
},
},
@@ -131,6 +160,10 @@ export default {
return '<span class="subscription-bubble px-2 py-1">Gem cap at 25</span>';
}
},
updateSubscriptionData (key) {
this.subscription.key = key;
if (this.userReceivingGift._id) this.gift.subscription.key = key;
},
},
};
</script>
@@ -89,9 +89,6 @@ export default {
try {
this.$store.dispatch('shops:releasePets', { user: this.user });
this.text(this.$t('releasePetsSuccess'));
// this.$router.push({name: 'stable'});
// Reload because achievement is set in user.save instead of common
window.location.reload(true);
} catch (err) {
window.alert(err.message); // eslint-disable-line no-alert
}
@@ -112,9 +109,6 @@ export default {
try {
this.$store.dispatch('shops:releaseMounts', { user: this.user });
this.text(this.$t('releaseMountsSuccess'));
// this.$router.push({name: 'stable'});
// Reload because achievement is set in user.save instead of common
window.location.reload(true);
} catch (err) {
window.alert(err.message); // eslint-disable-line no-alert
}
@@ -135,9 +129,6 @@ export default {
try {
this.$store.dispatch('shops:releaseBoth', { user: this.user });
this.text(this.$t('releaseBothSuccess'));
// this.$router.push({name: 'stable'});
// Reload because achievement is set in user.save instead of common
window.location.reload(true);
} catch (err) {
window.alert(err.message); // eslint-disable-line no-alert
}
@@ -560,14 +560,8 @@ export default {
this.selectedItemToBuy = null;
}
},
isGearLocked (gear) {
if (gear.value > this.userStats.gp) {
return true;
}
return false;
},
selectItem (item) {
if (item.locked) return;
this.selectedItemToBuy = item;
this.$root.$emit('bv::show::modal', 'buy-quest-modal');
@@ -27,7 +27,7 @@
position: fixed;
right: 10px;
width: 350px;
z-index: 999;
z-index: 9999; // to keep it above modal overlays
top: var(--current-scrollY);
+1 -1
View File
@@ -18,7 +18,7 @@
</a>
<a
href="https://geo.itunes.apple.com/us/app/habitica/id994882113?mt=8"
style="display:inline-block;overflow:hidden;background:url(http://linkmaker.itunes.apple.com/images/badges/en-us/badge_appstore-lrg.svg#svgView) no-repeat;background-size:100%;width:152px;height:45px;margin-left:20px;image-rendering:auto"
style="display:inline-block;overflow:hidden;background:url(https://linkmaker.itunes.apple.com/images/badges/en-us/badge_appstore-lrg.svg#svgView) no-repeat;background-size:100%;width:152px;height:45px;margin-left:20px;image-rendering:auto"
></a>
</div>
</div>
@@ -209,6 +209,7 @@
<li>Fox_town</li>
<li>MaybeSteveRogers</li>
<li>shanaqui</li>
<li>deilann (not yet pictured)</li>
</ul>
</div>
</div>
@@ -218,7 +219,7 @@
{{ $t('commGuidePara014') }}<br>
<em>
Lemoness, lefnire, Slappybag, litenull, Shaner, Bobbyroberts99, wc8,
deilann, Breadstrings, Megan, Blade, and Daniel the Bard
Breadstrings, Megan, Blade, and Daniel the Bard
</em>
</p>
<h2 id="final">
@@ -52,7 +52,7 @@
<li class="nav-item">
<a
class="nav-link"
href="http://blog.habitrpg.com/"
href="https://blog.habitrpg.com/"
target="_blank"
>{{ $t('tumblr') }}</a>
</li>
@@ -6,7 +6,7 @@
<noscript class="banner">
{{ $t('jsDisabledHeadingFull') }}
<br />
<a href="http://www.enable-javascript.com/" target="_blank">{{ $t('jsDisabledLink') }}</a>
<a href="https://www.enable-javascript.com/" target="_blank">{{ $t('jsDisabledLink') }}</a>
</noscript>
<div
id="intro-signup"
@@ -137,15 +137,15 @@
browser which allows you to refuse cookies. Further information about the procedure to follow in order to
disable cookies can be found on your Internet browser providers website via your help screen. You may
wish to refer to <a
href="http://www.allaboutcookies.org/manage-cookies/index.html"
href="https://www.allaboutcookies.org/manage-cookies/index.html"
target="_blank"
>
http://www.allaboutcookies.org/manage-cookies/index.html</a> for information on commonly used browsers.
https://www.allaboutcookies.org/manage-cookies/index.html</a> for information on commonly used browsers.
For more information about targeting and advertising cookies and how you can opt out, you can also visit
<a
href="http://optout.aboutads.info"
href="https://optout.aboutads.info"
target="_blank"
>http://optout.aboutads.info</a>. Please be aware
>https://optout.aboutads.info</a>. Please be aware
that if cookies are disabled, not all features of the Service may operate properly or as intended.
</p>
<h3>Third-Party Analytics Providers</h3>
@@ -70,9 +70,9 @@
<p>WITHIN THIRTY (30) DAYS OF YOUR PREMIUM PAYMENT DATE AS SHOWN ON YOUR PAYMENT BILL, YOU CAN REQUEST A FULL REFUND BY CONTACTING US AT ADMIN@HABITICA.COM. AFTER THIRTY (30) DAYS OF YOUR PREMIUM PAYMENT DATE, ANY PAYMENT REFUND IS SOLELY SUBJECT TO OUR DISCRETION. THE REFUND SHALL BE YOUR SOLE AND EXCLUSIVE REMEDY.</p>
<p>
FOR ANY CUSTOMER WHO PURCHASED PREMIUM IN APPLE INC.'s APP STORE ("APP STORE"), PLEASE CONTACT APPLE INC.'s SUPPORT TEAM: <a
href="http://reportaproblem.apple.com"
href="https://reportaproblem.apple.com"
target="_blank"
>http://reportaproblem.apple.com</a>. APPLE'S APP STORE DOES NOT ALLOW DEVELOPERS TO ISSUE REFUND FOR APP STORE PURCHASES MADE BY CUSTOMERS.
>https://reportaproblem.apple.com</a>. APPLE'S APP STORE DOES NOT ALLOW DEVELOPERS TO ISSUE REFUND FOR APP STORE PURCHASES MADE BY CUSTOMERS.
</p>
<h2>Warranty Disclaimer</h2>
<p>THE SERVICE AND ANY CONTENT MADE AVAILABLE BY HABITRPG VIA THE SERVICE IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT ANY WARRANTIES OF ANY KIND, INCLUDING, WITHOUT LIMITATION, THAT THE SERVICE OR CONTENT WILL OPERATE ERROR-FREE OR THAT THE SERVICE OR CONTENT OR ITS SERVERS ARE FREE OF COMPUTER VIRUSES OR SIMILAR CONTAMINATION OR DESTRUCTIVE FEATURES.</p>
+18 -2
View File
@@ -268,17 +268,33 @@
<span v-if="task.type === 'daily'">{{ task.streak }}</span>
<span v-if="task.type === 'habit'">
<span
v-if="task.up"
v-if="task.up && task.counterUp != 0 && task.down"
class="m-0"
>+{{ task.counterUp }}</span>
<span
v-else-if=" task.counterUp !=0 && task.counterDown ==0"
class="m-0"
>{{ task.counterUp }}</span>
<span
v-else-if="task.up"
class="m-0"
>0</span>
<span
v-if="task.up && task.down"
class="m-0"
>&nbsp;|&nbsp;</span>
<span
v-if="task.down"
v-if="task.down && task.counterDown != 0 && task.up"
class="m-0"
>-{{ task.counterDown }}</span>
<span
v-else-if="task.counterDown !=0 && task.counterUp ==0"
class="m-0"
>{{ task.counterDown }}</span>
<span
v-else-if="task.down"
class="m-0"
>0</span>
</span>
</div>
<div
@@ -662,6 +662,11 @@
margin-bottom: 0;
}
.custom-control-input {
z-index: -1;
opacity: 0;
}
.modal-header {
.form-group {
margin-bottom: 1rem;
@@ -1280,12 +1285,17 @@ export default {
createTag: 'tags:createTag',
}),
async syncTask () {
if (this.task && this.task.group && this.task.group.managerNotes) {
if (this.task?.group?.managerNotes) {
this.managerNotes = this.task.group.managerNotes;
}
if (this.groupId && this.task.group && this.task.group.approval) {
if (this.groupId && this.task.group?.approval) {
this.requiresApproval = this.task.group.approval.required;
}
if (this.task?.group?.sharedCompletion) {
this.sharedCompletion = this.task.group.sharedCompletion;
} else if (this.task.group) {
this.sharedCompletion = 'singleCompletion';
}
if (this.groupId) {
const members = await this.$store.dispatch('members:getGroupMembers', {
@@ -1306,9 +1316,6 @@ export default {
if (this.task.group && this.task.group.assignedUsers) {
this.assignedMembers = this.task.group.assignedUsers;
}
if (this.task.group) {
this.sharedCompletion = this.task.group.sharedCompletion || 'singleCompletion';
}
}
// @TODO: This whole component is mutating a prop
@@ -126,7 +126,7 @@
</div>
</div>
<div class="row">
<div class="col-12 col-md-6 offset-md-3 text-center nav">
<div class="text-center nav">
<div
class="nav-item"
:class="{active: selectedPage === 'profile'}"
@@ -470,6 +470,7 @@
.gift-icon svg {
height: 14px;
}
</style>
<style lang="scss" scoped>
@@ -538,6 +539,7 @@
}
.nav {
width: 100%;
font-weight: bold;
min-height: 40px;
justify-content: center;
@@ -710,6 +712,27 @@
}
}
}
@media (max-width: 990px) {
.profile-actions {
flex-direction: column;
}
.profile-actions :not(:last-child) {
margin-bottom: 15px;
}
.profile-actions {
margin-right: 0;
}
}
@media (max-width: 550px) {
.member-details {
flex-direction: column;
}
.member-details .avatar {
margin-bottom: 15px;
}
}
</style>
<script>
@@ -969,7 +992,8 @@ export default {
axios.post(`/api/v4/user/block/${this.user._id}`);
},
openSendGemsModal () {
this.$root.$emit('habitica::send-gems', this.user);
this.$store.state.giftModalOptions.startingPage = 'buyGems';
this.$root.$emit('habitica::send-gift', this.user);
},
adminTurnOnShadowMuting () {
if (!this.hero.flags) {
@@ -4,7 +4,7 @@
class="standard-page"
>
<div class="row">
<div class="col-12 col-md-6">
<div class="stats-section-equipment col-12 col-md-6">
<h2 class="text-center">
{{ $t('equipment') }}
</h2>
@@ -12,7 +12,7 @@
<div
v-for="(label, key) in equipTypes"
:key="key"
class="col-12 col-md-4 item-wrapper"
class="item-wrapper"
>
<div
v-if="label !== 'skip'"
@@ -48,7 +48,7 @@
</div>
</div>
</div>
<div class="col-12 col-md-6">
<div class="stats-section-costume col-12 col-md-6">
<h2 class="text-center">
{{ $t('costume') }}
</h2>
@@ -57,7 +57,7 @@
<div
v-for="(label, key) in equipTypes"
:key="key"
class="col-12 col-md-4 item-wrapper"
class="item-wrapper"
>
<!-- Append a "C" to the key name since HTML IDs have to be unique.-->
<div
@@ -111,7 +111,7 @@
</div>
</div>
<div class="row pet-mount-row">
<div class="col-12 col-md-6">
<div class="stats-section-pets col-12 col-md-6">
<h2
v-once
class="text-center"
@@ -119,8 +119,7 @@
{{ $t('pets') }}
</h2>
<div class="well pet-mount-well">
<div class="row col-12">
<div class="col-12 col-md-4">
<div class="pet-mount-well-image">
<div
class="box"
:class="{white: user.items.currentPet}"
@@ -131,7 +130,7 @@
></div>
</div>
</div>
<div class="col-12 col-md-8">
<div class="pet-mount-well-text">
<div>{{ formatAnimal(user.items.currentPet, 'pet') }}</div>
<div>
<strong>{{ $t('petsFound') }}:</strong>
@@ -142,10 +141,9 @@
{{ beastMasterProgress(user.items.pets) }}
</div>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-6">
<div class="stats-section-mounts col-12 col-md-6">
<h2
v-once
class="text-center"
@@ -153,28 +151,26 @@
{{ $t('mounts') }}
</h2>
<div class="well pet-mount-well">
<div class="row col-12">
<div class="col-12 col-md-4">
<div class="pet-mount-well-image">
<div
class="box"
:class="{white: user.items.currentMount}"
>
<div
class="box"
:class="{white: user.items.currentMount}"
>
<div
class="mount"
:class="`Mount_Icon_${user.items.currentMount}`"
></div>
</div>
class="mount"
:class="`Mount_Icon_${user.items.currentMount}`"
></div>
</div>
<div class="col-12 col-md-8">
<div>{{ formatAnimal(user.items.currentMount, 'mount') }}</div>
<div>
<strong>{{ $t('mountsTamed') }}:</strong>
<span>{{ totalCount(user.items.mounts) }}</span>
</div>
<div>
<strong>{{ $t('mountMasterProgress') }}:</strong>
<span>{{ mountMasterProgress(user.items.mounts) }}</span>
</div>
</div>
<div class="pet-mount-well-text">
<div>{{ formatAnimal(user.items.currentMount, 'mount') }}</div>
<div>
<strong>{{ $t('mountsTamed') }}:</strong>
<span>{{ totalCount(user.items.mounts) }}</span>
</div>
<div>
<strong>{{ $t('mountMasterProgress') }}:</strong>
<span>{{ mountMasterProgress(user.items.mounts) }}</span>
</div>
</div>
</div>
@@ -309,15 +305,13 @@
v-if="showStatsSave"
class="row save-row"
>
<div class="col-12 col-md-6 offset-md-3 text-center">
<button
class="btn btn-primary"
:disabled="loading"
@click="saveAttributes()"
>
{{ loading ? $t('loading') : $t('save') }}
</button>
</div>
<button
class="btn btn-primary"
:disabled="loading"
@click="saveAttributes()"
>
{{ loading ? $t('loading') : $t('save') }}
</button>
</div>
</div>
</div>
@@ -650,10 +644,17 @@ export default {
border-radius: 2px;
padding: 0.4em;
padding-top: 1em;
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 15px;
}
.well.pet-mount-well {
padding-left: 15px;
padding-bottom: 1em;
flex-wrap: nowrap;
justify-content: flex-start;
strong {
margin-right: .2em;
@@ -690,12 +691,13 @@ export default {
}
.save-row {
margin-top: 1em;
margin: 2em 0 1em 0;
justify-content: center;
}
.gear.box {
vertical-align: top;
margin: 0 auto;
// margin: 0 auto;
}
.gear-label {
@@ -721,4 +723,34 @@ export default {
// breaks the long words without a space
word-break: break-word;
}
@media (max-width: 850px) {
#stats .col-md-6 {
flex: none;
max-width: 100%;
}
}
@media(max-width: 990px) {
.modal-body #stats .col-md-6 {
flex: none;
max-width: 100%;
}
[class^="stats-section-"] {
margin-bottom: 30px;
}
#allocation {
.box {
width: 100%;
height: 100%;
.col-9 {
padding: 0;
margin: 0;
}
.col-9 div:first-child {
font-size: 13px;
}
}
}
}
</style>
+5
View File
@@ -39,6 +39,11 @@ export default [
type: 'Moderator',
uuid: '28771972-ca6d-4c03-8261-e1734aa7d21d',
},
{
name: 'deilann',
type: 'Moderator',
uuid: 'e7b5d1e2-3b6e-4192-b867-8bafdb03eeec',
},
{
name: 'Dewines',
type: 'Moderator',
+3
View File
@@ -124,6 +124,9 @@ export default function () {
profileOptions: {
startingPage: '',
},
giftModalOptions: {
startingPage: '',
},
rageModalOptions: {
npc: '',
},
+2 -2
View File
@@ -1,4 +1,4 @@
HabitRPG's translations are managed at http://translate.habitica.com/
HabitRPG's translations are managed at https://translate.habitica.com/
The files in this folder are automatically pulled from there, with
exception of the original American-English strings which are managed
@@ -10,5 +10,5 @@ request that your changes be translated; changes are automatically
copied to the translation website on a regular basis.
If you want to help with translations, please first read [Guidance for
Linguists](http://habitica.fandom.com/wiki/Guidance_for_Linguists) and
Linguists](https://habitica.fandom.com/wiki/Guidance_for_Linguists) and
note especially its information about the [Translations Trello card](https://trello.com/c/SvTsLdRF/12-translations).
+4 -4
View File
@@ -178,10 +178,10 @@
"advocacy_causes": "Advocacy + Causes",
"entertainment": "Entertainment",
"finance": "Finance",
"health_fitness": "Health + Fitness",
"hobbies_occupations": "Hobbies + Occupations",
"health_fitness": "الصحة واللياقة البدنية",
"hobbies_occupations": "الهوايات والمهن",
"location_based": "Location-based",
"mental_health": "Mental Health + Self-Care",
"mental_health": "الصحة العقلية + العناية الذاتية",
"getting_organized": "Getting Organized",
"self_improvement": "Self-Improvement",
"spirituality": "Spirituality",
@@ -192,7 +192,7 @@
"emptyMessagesLine1": "You don't have any messages",
"emptyMessagesLine2": "Send a message to start a conversation!",
"userSentMessage": "<span class=\"notification-bold\"><%- user %></span> sent you a message",
"letsgo": "Let's Go!",
"letsgo": "لنذهب!",
"selected": "Selected",
"howManyToBuy": "How many would you like to buy?",
"contactForm": "Contact the Moderation Team"
+23 -23
View File
@@ -1,25 +1,25 @@
{
"unlockedReward": "You have received <%= reward %>",
"earnedRewardForDevotion": "You have earned <%= reward %> for being committed to improving your life.",
"nextRewardUnlocksIn": "Check-ins until your next prize: <%= numberOfCheckinsLeft %>",
"awesome": "Awesome!",
"countLeft": "Check-ins until next reward: <%= count %>",
"incentivesDescription": "When it comes to building habits, consistency is key. Each day you check-in you get closer to a prize.",
"checkinEarned": "Your Check-In Counter went up!",
"unlockedCheckInReward": "You unlocked a Check-In Prize!",
"checkinProgressTitle": "Progress until next",
"incentiveBackgroundsUnlockedWithCheckins": "Locked Plain Backgrounds will unlock with Daily Check-Ins.",
"oneOfAllPetEggs": "one of each standard Pet Egg",
"twoOfAllPetEggs": "two of each standard Pet Egg",
"threeOfAllPetEggs": "three of each standard Pet Egg",
"oneOfAllHatchingPotions": "one of each standard Hatching Potion",
"threeOfEachFood": "three of each standard Pet Food",
"fourOfEachFood": "four of each standard Pet Food",
"twoSaddles": "two Saddles",
"threeSaddles": "three Saddles",
"incentiveAchievement": "the Royally Loyal achievement",
"royallyLoyal": "Royally Loyal",
"royallyLoyalText": "This user has checked in over 500 times, and has earned every Check-In Prize!",
"checkInRewards": "Check-In Rewards",
"backloggedCheckInRewards": "You received Check-In Prizes! Visit your Inventory and Equipment to see what's new."
"unlockedReward": "You have received <%= reward %>",
"earnedRewardForDevotion": "You have earned <%= reward %> for being committed to improving your life.",
"nextRewardUnlocksIn": "Check-ins until your next prize: <%= numberOfCheckinsLeft %>",
"awesome": "Awesome!",
"countLeft": "Check-ins until next reward: <%= count %>",
"incentivesDescription": "When it comes to building habits, consistency is key. Each day you check-in you get closer to a prize.",
"checkinEarned": "Your Check-In Counter went up!",
"unlockedCheckInReward": "You unlocked a Check-In Prize!",
"checkinProgressTitle": "Progress until next",
"incentiveBackgroundsUnlockedWithCheckins": "Locked Plain Backgrounds will unlock with Daily Check-Ins.",
"oneOfAllPetEggs": "one of each standard Pet Egg",
"twoOfAllPetEggs": "two of each standard Pet Egg",
"threeOfAllPetEggs": "three of each standard Pet Egg",
"oneOfAllHatchingPotions": "one of each standard Hatching Potion",
"threeOfEachFood": "three of each standard Pet Food",
"fourOfEachFood": "four of each standard Pet Food",
"twoSaddles": "two Saddles",
"threeSaddles": "ثلاثة سروج",
"incentiveAchievement": "the Royally Loyal achievement",
"royallyLoyal": "Royally Loyal",
"royallyLoyalText": "This user has checked in over 500 times, and has earned every Check-In Prize!",
"checkInRewards": "Check-In Rewards",
"backloggedCheckInRewards": "You received Check-In Prizes! Visit your Inventory and Equipment to see what's new."
}
+6 -6
View File
@@ -1,12 +1,12 @@
{
"npc": "شخصية غير قابلة للعب",
"npcAchievementName": "<%= key %> NPC",
"npcAchievementText": "Backed the Kickstarter project at the maximum level!",
"welcomeTo": "Welcome to",
"welcomeBack": "Welcome back!",
"npcAchievementName": "<%= key %> شخصية غير قابلة للعب",
"npcAchievementText": "لقد دعمت مشروع Kickstarter بأقصى مستوى!",
"welcomeTo": "مرحبًا بكِ في",
"welcomeBack": "مرحباً بعودتك!",
"justin": "جستن",
"justinIntroMessage1": "Hello there! You must be new here. My name is <strong>Justin</strong>, and I'll be your guide in Habitica.",
"justinIntroMessage3": "Great! Now, what are you interested in working on throughout this journey?",
"justinIntroMessage1": "أهلاً بك! يبدو أنك جديد/ة هنا. اسمي <strong>جاستن</strong> ، وسأكون دليلك في Habitica.",
"justinIntroMessage3": "رائعة! الآن ، ما الذي تهتم بالعمل عليه طوال هذه المغامرة؟",
"justinIntroMessageUsername": "Before we begin, lets figure out what to call you. Below youll find a display name and username Ive generated for you. After youve picked a display name and username, well get started by creating an avatar!",
"justinIntroMessageAppearance": "So how would you like to look? Dont worry, you can change this later.",
"introTour": "Here we are! I've filled out some Tasks for you based on your interests, so you can get started right away. Click a Task to edit or add new Tasks to fit your routine!",
+10 -9
View File
@@ -1,8 +1,8 @@
{
"pets": "الحيوانات الأليفة",
"stable": "مستقر",
"stable": "الإسطبل",
"noActivePet": "لا يوجد حيوان أليف نشط",
"activePet": "أنشطة الحيوانات الأليفة",
"activePet": "الحيوان الأليف النشط",
"raisedPet": "لقد نمت <٪ = حيوان أليف٪>!",
"feedPet": "تغذية <٪ = text٪> إلى <٪ = name٪>؟",
"mountNotOwned": "أنت لاتملك هذه الكمية.",
@@ -32,7 +32,7 @@
"etherealLion": "الأسد السماوي",
"magicMounts": "جرعة سحرية متصاعدة",
"questMounts": "تنقيب جبال",
"mountsTamed": "ترويض الجبل",
"mountsTamed": "المراكيب المروضة",
"noSaddlesAvailable": "أنت لاتملك أي سروج.",
"noFoodAvailable": "أنت لاتملك أي أغذية للحيوانات الأليفة.",
"food": "أغذية الحيوانات الأليفة والسروج",
@@ -61,20 +61,21 @@
"veteranFox": "الثعلب المخضرم",
"veteranBear": "الدب المخضرم",
"veteranLion": "الأسد المخضرم",
"activeMount": "جبل نشط",
"mounts": "يتصاعد",
"activeMount": "مركوب نشط",
"mounts": "مركوب",
"wackyPets": "حيوانات أليف مضحكة",
"magicPets": "دواء سحري للحيوانات الأليفة",
"petsFound": "إنشاء حيوانات أليفة",
"keyToPets": "مفتاح بيوت الحيوانات",
"noActiveMount": "لا يوجد تثبيت نشط",
"noActiveMount": "لا يوجد مركوب نشط",
"questPets": "بحث الحيوانات",
"releasePetsConfirm": "هل أنت متأكد أنك تريد إطلاق سراح حيوانك الأليف القياسي؟",
"keyToMounts": "مفتاح بيت الحيوان",
"petsReleased": "أفرج عن الحيوانات الأليفة",
"keyToPetsDesc": "حرر جميع الحيوانات المسموح بها حتى تتمكن من جمعها مرة أخرى. (لا تتأثر بالحيوانات الأليفة والحيوانات الأليفة الغريبة.)",
"petName": "<%= potion(locale) %> <%= egg(locale) %>",
"keyToPetsDesc": "حرر جميع الحيوانات الأليفة القياسية حتى تتمكن من جمعها مرة أخرى. (لا تتأثر بالحيوانات الأليفة من المهام والحيوانات الأليفة الغريبة.)",
"petName": "<%= egg(locale) %> <%= potion(locale) %>",
"keyToMountsDesc": "حرر جميع العينات القياسية حتى تتمكن من جمعها مرة أخرى. (لا تتأثر عمليات تثبيت المهام وعمليات التثبيت النادرة.)",
"keyToBoth": "مفاتيح رئيسية لبيوت الكلاب",
"releasePetsSuccess": "تم إطلاق حيوانك الأليف القياسي!"
"releasePetsSuccess": "تم إطلاق حيوانك الأليف القياسي!",
"mountName": "<%= mount(locale) %> <%= potion(locale) %>"
}

Some files were not shown because too many files have changed in this diff Show More