finish linting client

This commit is contained in:
Matteo Pagliazzi
2019-10-13 18:04:04 +02:00
parent c1ea91803c
commit a0e5a56bf2
105 changed files with 804 additions and 316 deletions

View File

@@ -72,7 +72,7 @@
"npm": "^6" "npm": "^6"
}, },
"scripts": { "scripts": {
"lint": "eslint --ext .js --fix ./website/server", "lint": "eslint --ext .js --fix .",
"test": "npm run lint && gulp test && gulp apidoc", "test": "npm run lint && gulp test && gulp apidoc",
"test:build": "gulp test:prepare:build", "test:build": "gulp test:prepare:build",
"test:api-v3": "gulp test:api-v3", "test:api-v3": "gulp test:api-v3",

View File

@@ -6253,6 +6253,12 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true "dev": true
}, },
"ini": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
"dev": true
},
"inquirer": { "inquirer": {
"version": "6.5.2", "version": "6.5.2",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
@@ -7868,6 +7874,127 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true "dev": true
}, },
"nconf": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/nconf/-/nconf-0.10.0.tgz",
"integrity": "sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q==",
"dev": true,
"requires": {
"async": "^1.4.0",
"ini": "^1.3.0",
"secure-keys": "^1.0.0",
"yargs": "^3.19.0"
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
"dev": true
},
"camelcase": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
"dev": true
},
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
"dev": true,
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wrap-ansi": "^2.0.0"
}
},
"invert-kv": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"lcid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
"dev": true,
"requires": {
"invert-kv": "^1.0.0"
}
},
"os-locale": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
"dev": true,
"requires": {
"lcid": "^1.0.0"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"wrap-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"dev": true,
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1"
}
},
"y18n": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
"dev": true
},
"yargs": {
"version": "3.32.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
"integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
"dev": true,
"requires": {
"camelcase": "^2.0.1",
"cliui": "^3.0.3",
"decamelize": "^1.1.1",
"os-locale": "^1.4.0",
"string-width": "^1.0.1",
"window-size": "^0.1.4",
"y18n": "^3.2.0"
}
}
}
},
"negotiator": { "negotiator": {
"version": "0.6.2", "version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
@@ -9857,6 +9984,12 @@
"ajv-keywords": "^3.1.0" "ajv-keywords": "^3.1.0"
} }
}, },
"secure-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz",
"integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=",
"dev": true
},
"select-hose": { "select-hose": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -12050,6 +12183,12 @@
"string-width": "^1.0.2 || 2" "string-width": "^1.0.2 || 2"
} }
}, },
"window-size": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz",
"integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=",
"dev": true
},
"wordwrap": { "wordwrap": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",

View File

@@ -6,7 +6,7 @@
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit --opts ../../test/mocha.opts", "test:unit": "vue-cli-service test:unit --opts ../../test/mocha.opts",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint --quiet"
}, },
"dependencies": { "dependencies": {
"amplitude-js": "^5.3.1", "amplitude-js": "^5.3.1",
@@ -42,7 +42,7 @@
"eslint": "^5.16.0", "eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0", "eslint-plugin-vue": "^5.0.0",
"inspectpack": "^4.2.2", "inspectpack": "^4.2.2",
"pug": "^2.0.4", "nconf": "^0.10.0",
"sass": "^1.19.0", "sass": "^1.19.0",
"sass-loader": "^8.0.0", "sass-loader": "^8.0.0",
"svg-inline-loader": "^0.8.0", "svg-inline-loader": "^0.8.0",

View File

@@ -29,7 +29,8 @@
></div> ></div>
{{ $t('share') }} {{ $t('share') }}
</a> </a>
<!-- @TODO: Still want this? .col-4a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')--> <!-- @TODO: Still want this?
.col-4a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')-->
</div> </div>
</div> </div>
</div> </div>

View File

@@ -16,6 +16,7 @@
<div class="row"> <div class="row">
<div <div
v-for="heroClass in classes" v-for="heroClass in classes"
:key="heroClass"
class="col-md-3" class="col-md-3"
> >
<div @click="selectedClass = heroClass"> <div @click="selectedClass = heroClass">
@@ -36,6 +37,7 @@
<br> <br>
<div <div
v-for="heroClass in classes" v-for="heroClass in classes"
:key="heroClass"
class="d-flex justify-content-center" class="d-flex justify-content-center"
> >
<div <div
@@ -56,7 +58,10 @@
</div> </div>
</div> </div>
</div> </div>
<div v-for="heroClass in classes"> <div
v-for="heroClass in classes"
:key="heroClass"
>
<div <div
v-if="selectedClass === heroClass" v-if="selectedClass === heroClass"
class="class-explanation text-center" class="class-explanation text-center"

View File

@@ -53,7 +53,8 @@ label(style='display:inline-block') {{ $t('dontShowAgain') }}
{{ $t('share') }} {{ $t('share') }}
</a> </a>
</div> </div>
<!-- @TODO: Still want this? .col-4a.tumblr-share-button(:data-href='socialLevelLink', data-notes='none')--> <!-- @TODO: Still want this? .col-4a.tumblr
-share-button(:data-href='socialLevelLink', data-notes='none')-->
</div> </div>
</div> </div>
</b-modal> </b-modal>

View File

@@ -35,12 +35,15 @@
v-if="nextReward.rewardKey.length === 1" v-if="nextReward.rewardKey.length === 1"
:class="nextReward.rewardKey[0]" :class="nextReward.rewardKey[0]"
></div> ></div>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="reward in nextReward.rewardKey" v-for="reward in nextReward.rewardKey"
v-if="nextReward.rewardKey.length > 1" v-if="nextReward.rewardKey.length > 1"
:key="reward"
class="reward" class="reward"
:class="reward" :class="reward"
></div> ></div>
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
</div> </div>
<div <div
v-if="data.rewardText" v-if="data.rewardText"
@@ -50,12 +53,15 @@
v-if="data.rewardKey.length === 1" v-if="data.rewardKey.length === 1"
:class="data.rewardKey[0]" :class="data.rewardKey[0]"
></div> ></div>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="reward in data.rewardKey" v-for="reward in data.rewardKey"
v-if="data.rewardKey.length > 1" v-if="data.rewardKey.length > 1"
:key="reward"
class="reward" class="reward"
:class="reward" :class="reward"
></div> ></div>
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
</div> </div>
</div> </div>
<div <div
@@ -79,7 +85,10 @@
v-if="data && data.nextRewardAt" v-if="data && data.nextRewardAt"
class="col-12 text-center" class="col-12 text-center"
> >
<h3>{{ $t('nextRewardUnlocksIn', {numberOfCheckinsLeft: data.nextRewardAt - user.loginIncentives}) }}</h3> <h3>
{{ $t('nextRewardUnlocksIn', {
numberOfCheckinsLeft: data.nextRewardAt - user.loginIncentives}) }}
</h3>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -29,7 +29,7 @@
<div ng-if="quests[user.party.quest.key].collect"> <div ng-if="quests[user.party.quest.key].collect">
<p ng-repeat="(k,v) in quests[user.party.quest.key].collect"> <p ng-repeat="(k,v) in quests[user.party.quest.key].collect">
<strong>{{ $t('collect') }} + ': '</strong> <strong>{{ $t('collect') }} + ': '</strong>
{{ quests[user.party.quest.key].collect[k].count }} {{ quests[user.party.quest.key].collect[k].text() }} {{ quests[user.party.quest.key].collect[k].count }} {{ quests[user.party.quest.key].collect[k].text() }} <!-- eslint-disable-line max-len -->
</p> </p>
</div> </div>
</div> </div>

View File

@@ -10,7 +10,9 @@
<!-- @TODO: +achievementAvatar('sun',0)--><achievement-avatar class="avatar" /> <!-- @TODO: +achievementAvatar('sun',0)--><achievement-avatar class="avatar" />
</div><div class="col-6 offset-3 text-center"> </div><div class="col-6 offset-3 text-center">
<div v-if="user.achievements.rebirthLevel < 100"> <div v-if="user.achievements.rebirthLevel < 100">
{{ $t('rebirthAchievement', {number: user.achievements.rebirths, level: user.achievements.rebirthLevel}) }} {{ $t('rebirthAchievement', {
number: user.achievements.rebirths,
level: user.achievements.rebirthLevel}) }}
</div><div v-if="user.achievements.rebirthLevel >= 100"> </div><div v-if="user.achievements.rebirthLevel >= 100">
{{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }} {{ $t('rebirthAchievement100', {number: user.achievements.rebirths}) }}
</div><br><button </div><br><button

View File

@@ -47,7 +47,10 @@
</table> </table>
<br> <br>
<div <div
v-if="!(user.achievements.ultimateGearSets.healer && user.achievements.ultimateGearSets.wizard && user.achievements.ultimateGearSets.rogue && user.achievements.ultimateGearSets.warrior)" v-if="!user.achievements.ultimateGearSets.healer
&& user.achievements.ultimateGearSets.wizard
&& user.achievements.ultimateGearSets.rogue
&& user.achievements.ultimateGearSets.warrior"
> >
<p v-html="$t('moreGearAchievements')"></p> <p v-html="$t('moreGearAchievements')"></p>
<br> <br>

View File

@@ -10,7 +10,9 @@
class="svg-icon social-icon" class="svg-icon social-icon"
v-html="icons.facebookIcon" v-html="icons.facebookIcon"
></div> ></div>
<span>{{ registering ? $t('signUpWithSocial', {social: 'Facebook'}) : $t('loginWithSocial', {social: 'Facebook'}) }}</span> <span>{{ registering
? $t('signUpWithSocial', {social: 'Facebook'})
: $t('loginWithSocial', {social: 'Facebook'}) }}</span>
</div> </div>
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
@@ -22,7 +24,9 @@
class="svg-icon social-icon" class="svg-icon social-icon"
v-html="icons.googleIcon" v-html="icons.googleIcon"
></div> ></div>
<span>{{ registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'}) }}</span> <span>{{ registering
? $t('signUpWithSocial', {social: 'Google'})
: $t('loginWithSocial', {social: 'Google'}) }}</span>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -33,7 +33,9 @@
<div <div
class="text" class="text"
> >
{{ registering ? $t('signUpWithSocial', {social: 'Facebook'}) : $t('loginWithSocial', {social: 'Facebook'}) }} {{ registering
? $t('signUpWithSocial', {social: 'Facebook'})
: $t('loginWithSocial', {social: 'Facebook'}) }}
</div> </div>
</div> </div>
</div> </div>
@@ -49,7 +51,9 @@
<div <div
class="text" class="text"
> >
{{ registering ? $t('signUpWithSocial', {social: 'Google'}) : $t('loginWithSocial', {social: 'Google'}) }} {{ registering
? $t('signUpWithSocial', {social: 'Google'})
: $t('loginWithSocial', {social: 'Google'}) }}
</div> </div>
</div> </div>
</div> </div>
@@ -72,6 +76,7 @@
> >
<div <div
v-for="issue in usernameIssues" v-for="issue in usernameIssues"
:key="issue"
class="input-error" class="input-error"
> >
{{ issue }} {{ issue }}

View File

@@ -7,7 +7,12 @@
v-for="option in items" v-for="option in items"
:key="option.key" :key="option.key"
class="outer-option-background" class="outer-option-background"
:class="{locked: option.gemLocked || option.goldLocked, premium: Boolean(option.gem), active: option.active || currentValue === option.key, none: option.none, hide: option.hide }" :class="{
locked: option.gemLocked || option.goldLocked,
premium: Boolean(option.gem),
active: option.active || currentValue === option.key,
none: option.none,
hide: option.hide }"
@click="option.click(option)" @click="option.click(option)"
> >
<div class="option"> <div class="option">

View File

@@ -17,10 +17,13 @@
:items="freeHairColors" :items="freeHairColors"
:current-value="user.preferences.hair.color" :current-value="user.preferences.hair.color"
/> />
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="set in seasonalHairColors" v-for="set in seasonalHairColors"
v-if="editing && set.key !== 'undefined'" v-if="editing && set.key !== 'undefined'"
:key="set.key"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<customize-options <customize-options
:items="set.options" :items="set.options"
:current-value="user.preferences.skin" :current-value="user.preferences.skin"
@@ -33,6 +36,7 @@
v-if="activeSubPage === 'style'" v-if="activeSubPage === 'style'"
id="style" id="style"
> >
<!-- eslint-disable vue/require-v-for-key NO KEY AVAILABLE HERE -->
<div v-for="set in styleSets"> <div v-for="set in styleSets">
<customize-options <customize-options
:items="set.options" :items="set.options"
@@ -40,6 +44,7 @@
@unlock="set.unlock()" @unlock="set.unlock()"
/> />
</div> </div>
<!-- eslint-enable vue/require-v-for-key -->
</div> </div>
<div <div
v-if="activeSubPage === 'bangs'" v-if="activeSubPage === 'bangs'"
@@ -58,12 +63,14 @@
v-if="editing" v-if="editing"
:items="mustacheList" :items="mustacheList"
/> />
<!-- eslint-disable max-len -->
<customize-options <customize-options
v-if="editing" v-if="editing"
:items="beardList" :items="beardList"
:full-set="isPurchaseAllNeeded('hair', ['baseHair5', 'baseHair6'], ['mustache', 'beard'])" :full-set="isPurchaseAllNeeded('hair', ['baseHair5', 'baseHair6'], ['mustache', 'beard'])"
@unlock="unlock(`hair.mustache.${baseHair5Keys.join(',hair.mustache.')},hair.beard.${baseHair6Keys.join(',hair.beard.')}`)" @unlock="unlock(`hair.mustache.${baseHair5Keys.join(',hair.mustache.')},hair.beard.${baseHair6Keys.join(',hair.beard.')}`)"
/> />
<!-- eslint-enable max-len -->
</div> </div>
</div> </div>
</template> </template>

View File

@@ -13,10 +13,13 @@
:items="freeSkins" :items="freeSkins"
:current-value="user.preferences.skin" :current-value="user.preferences.skin"
/> />
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="set in seasonalSkins" v-for="set in seasonalSkins"
v-if="editing && set.key !== 'undefined'" v-if="editing && set.key !== 'undefined'"
:key="set.key"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<customize-options <customize-options
:items="set.options" :items="set.options"
:current-value="user.preferences.skin" :current-value="user.preferences.skin"

View File

@@ -10,6 +10,7 @@
>{{ $t('joined') }}</span> >{{ $t('joined') }}</span>
<span <span
v-for="category in categories" v-for="category in categories"
:key="category.slug"
class="category-label" class="category-label"
:class="{'category-label-purple':isOfficial(category)}" :class="{'category-label-purple':isOfficial(category)}"
>{{ $t(category.name) }}</span> >{{ $t(category.name) }}</span>

View File

@@ -30,8 +30,10 @@
:group="challenge.group" :group="challenge.group"
/> />
</span> </span>
<!-- @TODO: make challenge.author a variable inside the createdBy string (helps with RTL languages)--> <!-- @TODO: make challenge.author a variable inside the
<!-- @TODO: Implement in V2 strong.margin-left(v-once).svg-icon.calendar-icon(v-html="icons.calendarIcon") createdBy string (helps with RTL languages)-->
<!-- @TODO: Implement in V2 strong.margin-left
(v-once).svg-icon.calendar-icon(v-html="icons.calendarIcon")
| {{$t('endDate')}} | {{$t('endDate')}}
// "endDate": "End Date: <% endDate %>",--> // "endDate": "End Date: <% endDate %>",-->
<!-- span {{challenge.endDate}}--> <!-- span {{challenge.endDate}}-->
@@ -39,6 +41,7 @@
<div class="tags"> <div class="tags">
<span <span
v-for="tag in challenge.tags" v-for="tag in challenge.tags"
:key="tag"
class="tag" class="tag"
>{{ tag }}</span> >{{ tag }}</span>
</div> </div>
@@ -112,6 +115,7 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<task-column <task-column
v-for="column in columns" v-for="column in columns"
v-if="tasksByType[column].length > 0" v-if="tasksByType[column].length > 0"
@@ -123,6 +127,7 @@
@editTask="editTask" @editTask="editTask"
@taskDestroyed="taskDestroyed" @taskDestroyed="taskDestroyed"
/> />
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
</div> </div>
</div> </div>
<div class="col-12 col-md-4 sidebar standard-page"> <div class="col-12 col-md-4 sidebar standard-page">

View File

@@ -78,6 +78,7 @@
<div class="well"> <div class="well">
<div <div
v-for="task in tasksData" v-for="task in tasksData"
:key="task.label"
:class="{'muted': task.value === 0}" :class="{'muted': task.value === 0}"
> >
<div class="number"> <div class="number">
@@ -413,7 +414,8 @@ export default {
return this.user.challenges.indexOf(this.challenge._id) !== -1; return this.user.challenges.indexOf(this.challenge._id) !== -1;
}, },
isOfficial () { isOfficial () {
return this.challenge.official || this.challenge.categories.map(category => category.slug).includes('habitica_official'); return this.challenge.official
|| this.challenge.categories.map(category => category.slug).includes('habitica_official');
}, },
tasksData () { tasksData () {
return [ return [

View File

@@ -68,6 +68,7 @@
> >
<option <option
v-for="group in groups" v-for="group in groups"
:key="group._id"
:value="group._id" :value="group._id"
> >
{{ group.name }} {{ group.name }}
@@ -91,6 +92,7 @@
>{{ $t('none') }}</span> >{{ $t('none') }}</span>
<div <div
v-for="category in workingChallenge.categories" v-for="category in workingChallenge.categories"
:key="category"
class="category-label" class="category-label"
> >
{{ $t(categoriesHashByKey[category]) }} {{ $t(categoriesHashByKey[category]) }}
@@ -100,12 +102,14 @@
v-if="showCategorySelect && creating" v-if="showCategorySelect && creating"
class="category-box" class="category-box"
> >
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="group in categoryOptions" v-for="group in categoryOptions"
v-if="group.key !== 'habitica_official' || user.contributor.admin" v-if="group.key !== 'habitica_official' || user.contributor.admin"
:key="group.key" :key="group.key"
class="form-check" class="form-check"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<input <input
:id="`challenge-modal-cat-${group.key}`" :id="`challenge-modal-cat-${group.key}`"

View File

@@ -13,8 +13,10 @@
</h1> </h1>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<!-- @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}b-dropdown(:text="$t('sort')", right=true) <!-- @TODO: implement sorting span.dropdown-label
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}--> {{ $t('sortBy') }}b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions',
:key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}-->
<button <button
class="btn btn-secondary create-challenge-button float-right" class="btn btn-secondary create-challenge-button float-right"
@click="createChallenge()" @click="createChallenge()"
@@ -40,6 +42,7 @@
<div class="row"> <div class="row">
<div <div
v-for="challenge in filteredChallenges" v-for="challenge in filteredChallenges"
:key="challenge._id"
class="col-12 col-md-6" class="col-12 col-md-6"
> >
<challenge-item :challenge="challenge" /> <challenge-item :challenge="challenge" />

View File

@@ -13,8 +13,10 @@
</h1> </h1>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<!-- @TODO: implement sorting span.dropdown-label {{ $t('sortBy') }}b-dropdown(:text="$t('sort')", right=true) <!-- @TODO: implement sorting span.dropdown-label
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}--> {{ $t('sortBy') }}b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions',
:key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}-->
<button <button
class="btn btn-secondary create-challenge-button float-right" class="btn btn-secondary create-challenge-button float-right"
@click="createChallenge()" @click="createChallenge()"
@@ -60,6 +62,7 @@
<div class="row"> <div class="row">
<div <div
v-for="challenge in filteredChallenges" v-for="challenge in filteredChallenges"
:key="challenge._id"
class="col-12 col-md-6" class="col-12 col-md-6"
> >
<challenge-item :challenge="challenge" /> <challenge-item :challenge="challenge" />

View File

@@ -6,6 +6,7 @@
> >
<div <div
v-for="result in searchResults" v-for="result in searchResults"
:key="result.username"
class="autocomplete-results d-flex align-items-center" class="autocomplete-results d-flex align-items-center"
:class="{'hover-background': result.hover}" :class="{'hover-background': result.hover}"
@click="select(result)" @click="select(result)"
@@ -134,7 +135,11 @@ export default {
this.currentSearch = this.currentSearch.substring(1, this.currentSearch.length); // eslint-disable-line vue/no-side-effects-in-computed-properties, max-len this.currentSearch = this.currentSearch.substring(1, this.currentSearch.length); // eslint-disable-line vue/no-side-effects-in-computed-properties, max-len
return this.tmpSelections return this.tmpSelections
.filter(option => option.displayName.toLowerCase().indexOf(this.currentSearch.toLowerCase()) !== -1 || option.username && option.username.toLowerCase().indexOf(this.currentSearch.toLowerCase()) !== -1) .filter(option => { // eslint-disable-line arrow-body-style
return option.displayName.toLowerCase().indexOf(this.currentSearch.toLowerCase()) !== -1
|| (option.username
&& option.username.toLowerCase().indexOf(this.currentSearch.toLowerCase()) !== -1);
})
.slice(0, 4); .slice(0, 4);
}, },

View File

@@ -61,7 +61,8 @@
<div>{{ $t('copyAsTodo') }}</div> <div>{{ $t('copyAsTodo') }}</div>
</div> </div>
<div <div
v-if="(inbox || (user.flags.communityGuidelinesAccepted && msg.uuid !== 'system')) && (!isMessageReported || user.contributor.admin)" v-if="(inbox || (user.flags.communityGuidelinesAccepted && msg.uuid !== 'system'))
&& (!isMessageReported || user.contributor.admin)"
class="action d-flex align-items-center" class="action d-flex align-items-center"
@click="report(msg)" @click="report(msg)"
> >
@@ -273,7 +274,10 @@ export default {
const messageText = message.text.toLowerCase(); const messageText = message.text.toLowerCase();
const displayName = user.profile.name; const displayName = user.profile.name;
const username = user.auth.local && user.auth.local.username; const username = user.auth.local && user.auth.local.username;
const mentioned = max([messageText.indexOf(username.toLowerCase()), messageText.indexOf(displayName.toLowerCase())]); const mentioned = max([
messageText.indexOf(username.toLowerCase()),
messageText.indexOf(displayName.toLowerCase()),
]);
if (mentioned === -1) return message.highlight; if (mentioned === -1) return message.highlight;
const escapedDisplayName = escapeRegExp(displayName); const escapedDisplayName = escapeRegExp(displayName);

View File

@@ -30,18 +30,22 @@
{{ $t('loading') }} {{ $t('loading') }}
</h2> </h2>
</div> </div>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="(msg, index) in messages" v-for="msg in messages"
v-if="chat && canViewFlag(msg)" v-if="chat && canViewFlag(msg)"
:key="msg.id"
:class="{row: inbox}" :class="{row: inbox}"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div <div
v-if="user._id !== msg.uuid" v-if="user._id !== msg.uuid"
class="d-flex" class="d-flex"
:class="{'flex-grow-1': inbox}" :class="{'flex-grow-1': inbox}"
> >
<avatar <avatar
v-if="msg.userStyles || (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)" v-if="msg.userStyles
|| (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)"
class="avatar-left" class="avatar-left"
:member="msg.userStyles || cachedProfileData[msg.uuid]" :member="msg.userStyles || cachedProfileData[msg.uuid]"
:avatar-only="true" :avatar-only="true"
@@ -85,7 +89,8 @@
/> />
</div> </div>
<avatar <avatar
v-if="msg.userStyles || (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)" v-if="msg.userStyles
|| (cachedProfileData[msg.uuid] && !cachedProfileData[msg.uuid].rejected)"
:member="msg.userStyles || cachedProfileData[msg.uuid]" :member="msg.userStyles || cachedProfileData[msg.uuid]"
:avatar-only="true" :avatar-only="true"
:hide-class-badge="true" :hide-class-badge="true"

View File

@@ -33,7 +33,7 @@
<span class="glyphicon glyphicon-forward"></span> <span class="glyphicon glyphicon-forward"></span>
{{ $t('consecutiveSubscription') }} {{ $t('consecutiveSubscription') }}
<ul class="list-unstyled"> <ul class="list-unstyled">
<li>{{ $t('consecutiveMonths') }} {{ group.purchased.plan.consecutive.count + group.purchased.plan.consecutive.offset }}</li> <li>{{ $t('consecutiveMonths') }} {{ group.purchased.plan.consecutive.count + group.purchased.plan.consecutive.offset }}</li> <!-- eslint-disable-line max-len -->
<li>{{ $t('gemCapExtra') }} {{ group.purchased.plan.consecutive.gemCapExtra }}</li> <li>{{ $t('gemCapExtra') }} {{ group.purchased.plan.consecutive.gemCapExtra }}</li>
<li>{{ $t('mysticHourglasses') }} {{ group.purchased.plan.consecutive.trinkets }}</li> <li>{{ $t('mysticHourglasses') }} {{ group.purchased.plan.consecutive.trinkets }}</li>
</ul> </ul>
@@ -50,7 +50,8 @@
{{ $t('upgrade') }} {{ $t('upgrade') }}
</button> </button>
<div <div
v-if="!group.purchased.plan.dateTerminated && group.purchased.plan.paymentMethod === 'Stripe'" v-if="!group.purchased.plan.dateTerminated
&& group.purchased.plan.paymentMethod === 'Stripe'"
class="btn btn-primary" class="btn btn-primary"
@click="showStripeEdit({groupId: group.id})" @click="showStripeEdit({groupId: group.id})"
> >

View File

@@ -15,9 +15,11 @@
</h1> </h1>
</div> </div>
<div class="col-4"> <div class="col-4">
<!-- @TODO: Add when we implement recent activity .float-rightspan.dropdown-label {{ $t('sortBy') }} <!-- @TODO: Add when we implement recent activity
.float-rightspan.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true) b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}--> b-dropdown-item(v-for='sortOption in sortOptions',
:key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}-->
<button <button
class="btn btn-secondary create-group-button float-right" class="btn btn-secondary create-group-button float-right"
@click="createGroup()" @click="createGroup()"
@@ -51,7 +53,7 @@ b-dropdown(:text="$t('sort')", right=true)
<mugen-scroll <mugen-scroll
v-show="loading" v-show="loading"
:handler="fetchGuilds" :handler="fetchGuilds"
:should-handle="!loading && !this.hasLoadedAllGuilds" :should-handle="!loading && !hasLoadedAllGuilds"
:handle-on-mount="true" :handle-on-mount="true"
> >
<span v-once>{{ $t('loading') }}</span> <span v-once>{{ $t('loading') }}</span>

View File

@@ -4,9 +4,9 @@
class="row" class="row"
> >
<group-form-modal v-if="isParty" /> <group-form-modal v-if="isParty" />
<start-quest-modal :group="this.group" /> <start-quest-modal :group="group" />
<quest-details-modal :group="this.group" /> <quest-details-modal :group="group" />
<participant-list-modal :group="this.group" /> <participant-list-modal :group="group" />
<group-gems-modal /> <group-gems-modal />
<div class="col-12 col-sm-8 standard-page"> <div class="col-12 col-sm-8 standard-page">
<div class="row"> <div class="row">
@@ -141,13 +141,22 @@
> >
{{ $t('invite') }} {{ $t('invite') }}
</button> </button>
<!-- @TODO: hide the invitation button if there's an active group plan and the player is not the leader--> <!-- @TODO: hide the invitation button
if there's an active group plan and the player is not the leader-->
</div> </div>
<div class="button-container"> <div class="button-container">
<!-- @TODO: V2 button.btn.btn-primary(v-once, v-if='!isLeader') {{$t('messageGuildLeader')}} // Suggest making the button visible to the leader too - useful for them to test how the feature works or to send a note to themself. -- Alys--> <!-- @TODO: V2 button.btn.btn-primary(v-once, v-if='!isLeader')
{{$t('messageGuildLeader')}} // Suggest making the button
visible to the leader too - useful for them to test how
the feature works or to send a note to themself. -- Alys-->
</div> </div>
<div class="button-container"> <div class="button-container">
<!-- @TODO: V2 button.btn.btn-primary(v-once, v-if='isMember && !isParty') {{$t('donateGems')}} // Suggest removing the isMember restriction - it's okay if non-members donate to a public guild. Also probably allow it for parties if parties can buy imagery. -- Alys--> <!-- @TODO: V2 button.btn.btn-primary(v-once,
v-if='isMember && !isParty') {{$t('donateGems')}}
// Suggest removing the isMember restriction
- it's okay if non-members donate to a public
guild. Also probably allow it for parties
if parties can buy imagery. -- Alys-->
</div> </div>
</div> </div>
</div> </div>
@@ -379,7 +388,6 @@ import groupUtilities from '@/mixins/groupsUtilities';
import styleHelper from '@/mixins/styleHelper'; import styleHelper from '@/mixins/styleHelper';
import { mapState } from '@/libs/store'; import { mapState } from '@/libs/store';
import * as Analytics from '@/libs/analytics'; import * as Analytics from '@/libs/analytics';
import membersModal from './membersModal';
import startQuestModal from './startQuestModal'; import startQuestModal from './startQuestModal';
import questDetailsModal from './questDetailsModal'; import questDetailsModal from './questDetailsModal';
import participantListModal from './participantListModal'; import participantListModal from './participantListModal';
@@ -406,7 +414,6 @@ import bronzeGuildBadgeIcon from '@/assets/svg/bronze-guild-badge-small.svg';
export default { export default {
components: { components: {
membersModal,
startQuestModal, startQuestModal,
groupFormModal, groupFormModal,
groupChallenges, groupChallenges,

View File

@@ -49,14 +49,15 @@
/> />
</div> </div>
<!-- br--> <!-- br-->
<!-- @TODO Implement in V2 .custom-control.custom-checkboxinput.custom-control-input(type="checkbox", v-model="workingGroup.guildLeaderCantBeMessaged") <!-- @TODO Implement in V2 .custom-control.custom-checkboxinput.custom
-control-input(type="checkbox", v-model="workingGroup.guildLeaderCantBeMessaged")
label.custom-control-label(v-once) {{ $t('guildLeaderCantBeMessaged') }} label.custom-control-label(v-once) {{ $t('guildLeaderCantBeMessaged') }}
// "guildLeaderCantBeMessaged": "Leader can not be messaged directly", // "guildLeaderCantBeMessaged": "Leader can not be messaged directly",
// @TODO discuss the impact of this with moderators before implementing // @TODO discuss the impact of this with moderators before implementing
--> -->
<br> <br>
<div <div
v-if="!isParty && !this.workingGroup.id" v-if="!isParty && !workingGroup.id"
class="custom-control custom-checkbox" class="custom-control custom-checkbox"
> >
<input <input
@@ -86,7 +87,9 @@ label.custom-control-label(v-once) {{ $t('guildLeaderCantBeMessaged') }}
/> />
</div> </div>
<!-- br--> <!-- br-->
<!-- @TODO: Implement in v2 .custom-control.custom-checkbox(v-if='!creatingParty')input.custom-control-input(type="checkbox", v-model="workingGroup.allowGuildInvitationsFromNonMembers") <!-- @TODO: Implement in v2 .custom-control.custom-checkbox(v-if='!creatingParty')
input.custom-control-input(type="checkbox", v-model="workingGroup.allowG
uildInvitationsFromNonMembers")
label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers') }} label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers') }}
// "allowGuildInvitationsFromNonMembers": "Allow Guild invitations from non-members", // "allowGuildInvitationsFromNonMembers": "Allow Guild invitations from non-members",
--> -->
@@ -123,7 +126,8 @@ label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers')
class="form-control description-textarea" class="form-control description-textarea"
type="text" type="text"
textarea="textarea" textarea="textarea"
:placeholder="isParty ? $t('partyDescriptionPlaceholder') : $t('guildDescriptionPlaceholder')" :placeholder="isParty
? $t('partyDescriptionPlaceholder') : $t('guildDescriptionPlaceholder')"
></textarea> ></textarea>
</div> </div>
<div <div
@@ -155,6 +159,7 @@ label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers')
>{{ $t('none') }}</span> >{{ $t('none') }}</span>
<div <div
v-for="category in workingGroup.categories" v-for="category in workingGroup.categories"
:key="category"
class="category-label" class="category-label"
> >
{{ $t(categoriesHashByKey[category]) }} {{ $t(categoriesHashByKey[category]) }}
@@ -164,12 +169,14 @@ label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers')
v-if="showCategorySelect" v-if="showCategorySelect"
class="category-box" class="category-box"
> >
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="group in categoryOptions" v-for="group in categoryOptions"
v-if="group.key !== 'habitica_official' || user.contributor.admin" v-if="group.key !== 'habitica_official' || user.contributor.admin"
:key="group.key" :key="group.key"
class="form-check" class="form-check"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<input <input
:id="`category-${group.key}`" :id="`category-${group.key}`"
@@ -192,7 +199,8 @@ label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers')
{{ $t('close') }} {{ $t('close') }}
</button> </button>
</div> </div>
<!-- @TODO: need categories only for PUBLIC GUILDS, not for tavern, private guilds, or party--> <!-- @TODO: need categories only for PUBLIC GUILDS,
not for tavern, private guilds, or party-->
</div> </div>
<div <div
v-if="inviteMembers && !workingGroup.id" v-if="inviteMembers && !workingGroup.id"
@@ -203,6 +211,7 @@ label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers')
<p v-once>{{ $t('inviteMembersHowTo') }} *</p> <p v-once>{{ $t('inviteMembersHowTo') }} *</p>
</label> </label>
<div> <div>
<!-- eslint-disable-next-line vue/require-v-for-key -->
<div v-for="(member, index) in membersToInvite"> <div v-for="(member, index) in membersToInvite">
<input <input
v-model="member.value" v-model="member.value"
@@ -226,7 +235,7 @@ label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers')
</div> </div>
<div class="form-group text-center"> <div class="form-group text-center">
<div <div
v-if="!this.workingGroup.id" v-if="!workingGroup.id"
class="item-with-icon" class="item-with-icon"
> >
<div <div
@@ -250,7 +259,7 @@ label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers')
{{ isParty ? $t('updateParty') : $t('updateGuild') }} {{ isParty ? $t('updateParty') : $t('updateGuild') }}
</button> </button>
<div <div
v-if="!this.workingGroup.id" v-if="!workingGroup.id"
v-once v-once
class="gem-description" class="gem-description"
> >
@@ -324,7 +333,6 @@ label.custom-control-label(v-once) {{ $t('allowGuildInvitationsFromNonMembers')
<script> <script>
import { mapState } from '@/libs/store'; import { mapState } from '@/libs/store';
import toggleSwitch from '@/components/ui/toggleSwitch'; import toggleSwitch from '@/components/ui/toggleSwitch';
import groupMemberSearchDropdown from '@/components/members/groupMemberSearchDropdown';
import markdownDirective from '@/directives/markdown'; import markdownDirective from '@/directives/markdown';
import gemIcon from '@/assets/svg/gem.svg'; import gemIcon from '@/assets/svg/gem.svg';
import informationIcon from '@/assets/svg/information.svg'; import informationIcon from '@/assets/svg/information.svg';
@@ -340,7 +348,6 @@ import { MAX_SUMMARY_SIZE_FOR_GUILDS } from '@/../../common/script/constants';
export default { export default {
components: { components: {
toggleSwitch, toggleSwitch,
groupMemberSearchDropdown,
}, },
directives: { directives: {
markdown: markdownDirective, markdown: markdownDirective,

View File

@@ -24,7 +24,7 @@
> >
<hr> <hr>
<h2>{{ $t('teamBasedTasks') }}</h2> <h2>{{ $t('teamBasedTasks') }}</h2>
<p>Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!</p> <p>Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!</p><!-- eslint-disable-line max-len -->
</div> </div>
</div> </div>
<div class="col-4"> <div class="col-4">
@@ -35,7 +35,7 @@
> >
<hr> <hr>
<h2>Group Management Controls</h2> <h2>Group Management Controls</h2>
<p>Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.</p> <p>Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.</p><!-- eslint-disable-line max-len -->
</div> </div>
</div> </div>
<div class="col-4"> <div class="col-4">
@@ -46,7 +46,7 @@
> >
<hr> <hr>
<h2>In-Game Benefits</h2> <h2>In-Game Benefits</h2>
<p>Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.</p> <p>Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.</p><!-- eslint-disable-line max-len -->
</div> </div>
</div> </div>
</div> </div>

View File

@@ -9,6 +9,7 @@
<div class="small"> <div class="small">
{{ $t('inviteEmailUsernameInfo') }} {{ $t('inviteEmailUsernameInfo') }}
</div> </div>
<!-- eslint-disable-next-line vue/require-v-for-key -->
<div v-for="(invite, index) in invites"> <div v-for="(invite, index) in invites">
<div class="input-group"> <div class="input-group">
<div <div
@@ -25,7 +26,8 @@
class="form-control" class="form-control"
type="text" type="text"
:placeholder="$t('emailOrUsernameInvite')" :placeholder="$t('emailOrUsernameInvite')"
:class="{'input-valid': invite.valid, 'is-invalid input-invalid': invite.valid === false}" :class="{
'input-valid': invite.valid, 'is-invalid input-invalid': invite.valid === false}"
@keyup="expandInviteList" @keyup="expandInviteList"
@change="checkInviteList" @change="checkInviteList"
> >

View File

@@ -3,7 +3,7 @@
<div> <div>
<remove-member-modal <remove-member-modal
:member-to-remove="memberToRemove" :member-to-remove="memberToRemove"
:group-id="this.groupId" :group-id="groupId"
@member-removed="memberRemoved" @member-removed="memberRemoved"
/> />
<b-modal <b-modal
@@ -49,6 +49,7 @@
> >
<option <option
v-for="sortOption in sortOptions" v-for="sortOption in sortOptions"
:key="sortOption.value"
:value="sortOption.value" :value="sortOption.value"
> >
{{ sortOption.text }} {{ sortOption.text }}
@@ -62,6 +63,7 @@
> >
<option <option
v-for="sortDirection in sortDirections" v-for="sortDirection in sortDirections"
:key="sortDirection.value"
:value="sortDirection.value" :value="sortDirection.value"
> >
{{ sortDirection.text }} {{ sortDirection.text }}
@@ -100,6 +102,7 @@
<div v-if="selectedPage === 'members'"> <div v-if="selectedPage === 'members'">
<div <div
v-for="(member, index) in sortedMembers" v-for="(member, index) in sortedMembers"
:key="member._id"
class="row" class="row"
> >
<div class="col-11 no-padding-left"> <div class="col-11 no-padding-left">
@@ -201,6 +204,7 @@
<div v-if="selectedPage === 'invites'"> <div v-if="selectedPage === 'invites'">
<div <div
v-for="(member, index) in invites" v-for="(member, index) in invites"
:key="member._id"
class="row" class="row"
> >
<div class="col-11 no-padding-left"> <div class="col-11 no-padding-left">

View File

@@ -28,9 +28,11 @@
></div> ></div>
<span v-once>{{ $t('createGuild2') }}</span> <span v-once>{{ $t('createGuild2') }}</span>
</button> </button>
<!-- @TODO: Add when we implement recent activity .float-rightspan.dropdown-label {{ $t('sortBy') }} <!-- @TODO: Add when we implement recent activity
.float-rightspan.dropdown-label {{ $t('sortBy') }}
b-dropdown(:text="$t('sort')", right=true) b-dropdown(:text="$t('sort')", right=true)
b-dropdown-item(v-for='sortOption in sortOptions', :key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}} b-dropdown-item(v-for='sortOption in sortOptions',
:key="sortOption.value", @click='sort(sortOption.value)') {{sortOption.text}}
--> -->
</div> </div>
</div> </div>
@@ -107,7 +109,6 @@ b-dropdown(:text="$t('sort')", right=true)
</style> </style>
<script> <script>
import MugenScroll from 'vue-mugen-scroll';
import { mapState } from '@/libs/store'; import { mapState } from '@/libs/store';
import groupUtilities from '@/mixins/groupsUtilities'; import groupUtilities from '@/mixins/groupsUtilities';
@@ -119,7 +120,7 @@ import greyBadgeIcon from '@/assets/svg/grey-badge.svg';
import positiveIcon from '@/assets/svg/positive.svg'; import positiveIcon from '@/assets/svg/positive.svg';
export default { export default {
components: { PublicGuildItem, MugenScroll, Sidebar }, components: { PublicGuildItem, Sidebar },
mixins: [groupUtilities], mixins: [groupUtilities],
data () { data () {
return { return {

View File

@@ -28,6 +28,7 @@
</div> </div>
<div <div
v-for="member in participants" v-for="member in participants"
:key="member._id"
class="row" class="row"
> >
<div class="col-12 no-padding-left"> <div class="col-12 no-padding-left">

View File

@@ -9,7 +9,9 @@
<div class="col-md-2 badge-column"> <div class="col-md-2 badge-column">
<div <div
class="shield-wrap" class="shield-wrap"
:class="{gold: guild.memberCount >= 1000, silver: guild.memberCount >= 100 && guild.memberCount < 1000}" :class="{
gold: guild.memberCount >= 1000,
silver: guild.memberCount >= 100 && guild.memberCount < 1000}"
> >
<div <div
v-if="guild.memberCount >= 1000" v-if="guild.memberCount >= 1000"

View File

@@ -21,6 +21,7 @@
<div class="row"> <div class="row">
<div <div
v-for="member in members" v-for="member in members"
:key="member._id"
class="col-12 member" class="col-12 member"
> >
<strong :class="{'declined-name': member.accepted === false}">{{ member.name }}</strong> <strong :class="{'declined-name': member.accepted === false}">{{ member.name }}</strong>
@@ -60,7 +61,9 @@
> >
{{ $t('begin') }} {{ $t('begin') }}
</button> </button>
<!-- @TODO don't allow the party leader to start the quest until the leader has accepted or rejected the invitation (users get confused and think "begin" means "join quest")--> <!-- @TODO don't allow the party leader to
start the quest until the leader has accepted
or rejected the invitation (users get confused and think "begin" means "join quest")-->
</div> </div>
<div> <div>
<div <div
@@ -243,6 +246,7 @@ export default {
return partyMembers.map(member => ({ return partyMembers.map(member => ({
name: member.profile.name, name: member.profile.name,
accepted: this.group.quest.members[member._id], accepted: this.group.quest.members[member._id],
_id: member._id,
})); }));
}, },
canEditQuest () { canEditQuest () {

View File

@@ -92,6 +92,7 @@
</div> </div>
<div <div
v-for="(value, key) in questData.collect" v-for="(value, key) in questData.collect"
:key="key"
class="row" class="row"
> >
<div class="col-2"> <div class="col-2">
@@ -148,19 +149,22 @@
<div class="row boss-details"> <div class="row boss-details">
<div class="col-6"> <div class="col-6">
<span class="float-left"> <span class="float-left">
{{ Math.ceil(parseFloat(group.quest.progress.hp) * 100) / 100 }} / {{ parseFloat(questData.boss.hp).toFixed(2) }} {{ Math.ceil(parseFloat(group.quest.progress.hp) * 100) / 100 }} / {{ parseFloat(questData.boss.hp).toFixed(2) }} <!-- eslint-disable-line max-len -->
<!-- current boss hp uses ceil so you don't underestimate damage needed to end quest--> <!-- current boss hp uses ceil so
you don't underestimate damage needed to end quest-->
</span> </span>
</div> </div>
<div <div
v-if="userIsOnQuest" v-if="userIsOnQuest"
class="col-6" class="col-6"
> >
<!-- @TODO: Why do we not sync quest progress on the group doc? Each user could have different progress.--> <!-- @TODO: Why do we not sync quest
progress on the group doc? Each user could have different progress.-->
<span <span
class="float-right" class="float-right"
>{{ user.party.quest.progress.up | floor(10) }} {{ $t('pendingDamageLabel') }}</span> >{{ user.party.quest.progress.up | floor(10) }} {{ $t('pendingDamageLabel') }}</span> <!-- eslint-disable-line max-len -->
<!-- player's pending damage uses floor so you don't overestimate damage you've already done--> <!-- player's pending damage uses floor so you
don't overestimate damage you've already done-->
</div> </div>
</div> </div>
<div <div
@@ -171,7 +175,8 @@
<div class="grey-progress-bar"> <div class="grey-progress-bar">
<div <div
class="boss-health-bar rage-bar" class="boss-health-bar rage-bar"
:style="{width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}" :style="{
width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}"
></div> ></div>
</div> </div>
</div> </div>
@@ -183,7 +188,7 @@
<div class="col-6"> <div class="col-6">
<span <span
class="float-left" class="float-left"
>{{ $t('rage') }} {{ parseFloat(group.quest.progress.rage).toFixed(2) }} / {{ questData.boss.rage.value }}</span> >{{ $t('rage') }} {{ parseFloat(group.quest.progress.rage).toFixed(2) }} / {{ questData.boss.rage.value }}</span> <!-- eslint-disable-line max-len -->
</div> </div>
</div> </div>
</div> </div>

View File

@@ -11,13 +11,16 @@
Quests Quests
</h3> </h3>
<div class="row"> <div class="row">
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="(value, key, index) in user.items.quests" v-for="(value, key) in user.items.quests"
v-if="value > 0" v-if="value > 0"
:key="key"
class="col-4 quest-col" class="col-4 quest-col"
:class="{selected: key === selectedQuest}" :class="{selected: key === selectedQuest}"
@click="selectQuest({key})" @click="selectQuest({key})"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div class="quest-wrapper"> <div class="quest-wrapper">
<b-popover <b-popover
:target="`inventory_quest_scroll_${key}`" :target="`inventory_quest_scroll_${key}`"

View File

@@ -26,7 +26,10 @@
<div <div
v-if="group && group.quest && group.quest.active" v-if="group && group.quest && group.quest.active"
class="world-boss" class="world-boss"
:style="{background: questData.colors.dark, 'border-color': questData.colors.extralight, 'outline-color': questData.colors.light}" :style="{
background: questData.colors.dark,
'border-color': questData.colors.extralight,
'outline-color': questData.colors.light}"
> >
<div <div
class="corner-decoration" class="corner-decoration"
@@ -105,7 +108,9 @@
></div> ></div>
<span <span
class="reduce ml-1 pt-1" class="reduce ml-1 pt-1"
>{{ $t('bossHealth', {currentHealth: bossCurrentHealth(), maxHealth: questData.boss.hp.toLocaleString()}) }}</span> >{{ $t('bossHealth', {
currentHealth: bossCurrentHealth(),
maxHealth: questData.boss.hp.toLocaleString()}) }}</span>
</span> </span>
<div class="mt-3 mb-2"> <div class="mt-3 mb-2">
<strong class="mr-1">{{ $t('rageAttack') }}</strong> <strong class="mr-1">{{ $t('rageAttack') }}</strong>
@@ -114,7 +119,8 @@
<div class="grey-progress-bar mb-1"> <div class="grey-progress-bar mb-1">
<div <div
class="boss-health-bar rage-bar" class="boss-health-bar rage-bar"
:style="{width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}" :style="{
width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}"
></div> ></div>
</div> </div>
<span class="d-flex align-items-center"> <span class="d-flex align-items-center">
@@ -124,7 +130,9 @@
></div> ></div>
<span <span
class="reduce ml-1 pt-1" class="reduce ml-1 pt-1"
>{{ $t('bossRage', {currentRage: bossCurrentRage(), maxRage: questData.boss.rage.value.toLocaleString()}) }}</span> >{{ $t('bossRage', {
currentRage: bossCurrentRage(),
maxRage: questData.boss.rage.value.toLocaleString()}) }}</span>
</span> </span>
<div class="row d-flex align-items-center mb-2 mt-2"> <div class="row d-flex align-items-center mb-2 mt-2">
<div class="col-sm-4 d-flex"> <div class="col-sm-4 d-flex">
@@ -217,7 +225,8 @@
></div> ></div>
</div> </div>
</div> </div>
<!-- .text-center.mt-4.world-boss-info-button(@click="showWorldBossInfo()") {{$t('whatIsWorldBoss') }} <!-- .text-center.mt-4.world-boss
-info-button(@click="showWorldBossInfo()") {{$t('whatIsWorldBoss') }}
--> -->
</div> </div>
<div class="sleep below-header-sections"> <div class="sleep below-header-sections">
@@ -259,8 +268,12 @@
<div class="row"> <div class="row">
<div <div
v-for="user in staff" v-for="user in staff"
:key="user.uuid"
class="col-4 staff" class="col-4 staff"
:class="{staff: user.type === 'Staff', moderator: user.type === 'Moderator', bailey: user.name === 'It's Bailey'}" :class="{
staff: user.type === 'Staff',
moderator: user.type === 'Moderator',
bailey: user.name === 'It\'s Bailey'}"
> >
<div> <div>
<router-link <router-link
@@ -275,12 +288,12 @@
v-html="icons.tierStaff" v-html="icons.tierStaff"
></div> ></div>
<div <div
v-if="user.type === 'Moderator' && user.name !== 'It's Bailey'" v-if="user.type === 'Moderator' && user.name !== 'It\'s Bailey'"
class="svg-icon mod-icon" class="svg-icon mod-icon"
v-html="icons.tierMod" v-html="icons.tierMod"
></div> ></div>
<div <div
v-if="user.name === 'It's Bailey'" v-if="user.name === 'It\'s Bailey'"
class="svg-icon npc-icon" class="svg-icon npc-icon"
v-html="icons.tierNPC" v-html="icons.tierNPC"
></div> ></div>

View File

@@ -48,7 +48,7 @@
> >
<small> <small>
Common titles: Common titles:
<strong>Ambassador, Artisan, Bard, Blacksmith, Challenger, Comrade, Fletcher, Linguist, Linguistic Scribe, Scribe, Socialite, Storyteller</strong>. Rare titles: Advisor, Chamberlain, Designer, Mathematician, Shirtster, Spokesperson, Statistician, Tinker, Transcriber, Troubadour. <strong>Ambassador, Artisan, Bard, Blacksmith, Challenger, Comrade, Fletcher, Linguist, Linguistic Scribe, Scribe, Socialite, Storyteller</strong>. Rare titles: Advisor, Chamberlain, Designer, Mathematician, Shirtster, Spokesperson, Statistician, Tinker, Transcriber, Troubadour. <!-- eslint-disable-line max-len -->
</small> </small>
</div> </div>
<div class="form-group"> <div class="form-group">
@@ -59,7 +59,7 @@
type="number" type="number"
> >
<small> <small>
1-7 for normal contributors, 8 for moderators, 9 for staff. This determines which items, pets, and mounts are available, and name-tag coloring. Tiers 8 and 9 are automatically given admin status.&nbsp; 1-7 for normal contributors, 8 for moderators, 9 for staff. This determines which items, pets, and mounts are available, and name-tag coloring. Tiers 8 and 9 are automatically given admin status.&nbsp; <!-- eslint-disable-line max-len -->
<a <a
target="_blank" target="_blank"
href="https://trello.com/c/wkFzONhE/277-contributor-gear" href="https://trello.com/c/wkFzONhE/277-contributor-gear"
@@ -89,7 +89,7 @@
<small> <small>
<span> <span>
'{{ hero.balance }}' is in USD, '{{ hero.balance }}' is in USD,
<em>not</em> in Gems. E.g., if this number is 1, it means 4 Gems. Only use this option when manually granting Gems to players, don't use it when granting contributor tiers. Contrib tiers will automatically add Gems. <em>not</em> in Gems. E.g., if this number is 1, it means 4 Gems. Only use this option when manually granting Gems to players, don't use it when granting contributor tiers. Contrib tiers will automatically add Gems. <!-- eslint-disable-line max-len -->
</span> </span>
</small> </small>
</div> </div>
@@ -134,7 +134,7 @@
<strong>item value</strong>. E.g., <strong>item value</strong>. E.g.,
<code>5</code> or <code>5</code> or
<code>false</code> or <code>false</code> or
<code>head_warrior_3</code>. All values are listed in the All Item Paths section below. <code>head_warrior_3</code>. All values are listed in the All Item Paths section below. <!-- eslint-disable-line max-len -->
</small> </small>
<div class="accordion"> <div class="accordion">
<div <div
@@ -229,7 +229,10 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(hero, index) in heroes"> <tr
v-for="(hero, index) in heroes"
:key="hero._id"
>
<td> <td>
<user-link <user-link
v-if="hero.contributor && hero.contributor.admin" v-if="hero.contributor && hero.contributor.admin"

View File

@@ -16,7 +16,10 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="patron in patrons"> <tr
v-for="patron in patrons"
:key="patron._id"
>
<td> <td>
<a <a
v-class="userLevelStyle(patron)" v-class="userLevelStyle(patron)"

View File

@@ -33,6 +33,7 @@
class="party-members d-flex" class="party-members d-flex"
@resized="setPartyMembersWidth($event)" @resized="setPartyMembersWidth($event)"
> >
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<member-details <member-details
v-for="(member, $index) in sortedPartyMembers" v-for="(member, $index) in sortedPartyMembers"
v-if="member._id !== user._id && $index < membersToShow" v-if="member._id !== user._id && $index < membersToShow"
@@ -44,6 +45,7 @@
:class-badge-position="'hidden'" :class-badge-position="'hidden'"
@onHover="expandMember(member._id)" @onHover="expandMember(member._id)"
/> />
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
</div> </div>
<div <div
v-else v-else

View File

@@ -57,7 +57,9 @@
</b-nav-item> </b-nav-item>
<li <li
class="topbar-item droppable" class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/inventory'), 'down': $route.path.startsWith('/inventory') && this.isDesktop()}" :class="{
'active': $route.path.startsWith('/inventory'),
'down': $route.path.startsWith('/inventory') && isDesktop()}"
> >
<div <div
class="chevron rotate" class="chevron rotate"
@@ -99,7 +101,9 @@
</li> </li>
<li <li
class="topbar-item droppable" class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/shop'), 'down': $route.path.startsWith('/shop') && this.isDesktop()}" :class="{
'active': $route.path.startsWith('/shop'),
'down': $route.path.startsWith('/shop') && isDesktop()}"
> >
<div <div
class="chevron rotate" class="chevron rotate"
@@ -146,7 +150,7 @@
</div> </div>
</li> </li>
<b-nav-item <b-nav-item
v-if="this.user.party._id" v-if="user.party._id"
class="topbar-item" class="topbar-item"
:class="{'active': $route.path.startsWith('/party')}" :class="{'active': $route.path.startsWith('/party')}"
tag="li" tag="li"
@@ -155,7 +159,7 @@
{{ $t('party') }} {{ $t('party') }}
</b-nav-item> </b-nav-item>
<b-nav-item <b-nav-item
v-if="!this.user.party._id" v-if="!user.party._id"
class="topbar-item" class="topbar-item"
:class="{'active': $route.path.startsWith('/party')}" :class="{'active': $route.path.startsWith('/party')}"
@click="openPartyModal()" @click="openPartyModal()"
@@ -164,7 +168,9 @@
</b-nav-item> </b-nav-item>
<li <li
class="topbar-item droppable" class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/groups'), 'down': $route.path.startsWith('/groups') && this.isDesktop()}" :class="{
'active': $route.path.startsWith('/groups'),
'down': $route.path.startsWith('/groups') && isDesktop()}"
> >
<div <div
class="chevron rotate" class="chevron rotate"
@@ -205,7 +211,9 @@
</li> </li>
<li <li
class="topbar-item droppable" class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/group-plans'), 'down': $route.path.startsWith('/group-plans') && this.isDesktop()}" :class="{
'active': $route.path.startsWith('/group-plans'),
'down': $route.path.startsWith('/group-plans') && isDesktop()}"
> >
<div <div
v-if="groupPlans.length > 0" v-if="groupPlans.length > 0"
@@ -237,7 +245,9 @@
</li> </li>
<li <li
class="topbar-item droppable" class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/challenges'), 'down': $route.path.startsWith('/challenges') && this.isDesktop()}" :class="{
'active': $route.path.startsWith('/challenges'),
'down': $route.path.startsWith('/challenges') && isDesktop()}"
> >
<div <div
class="chevron rotate" class="chevron rotate"
@@ -272,7 +282,9 @@
</li> </li>
<li <li
class="topbar-item droppable" class="topbar-item droppable"
:class="{'active': $route.path.startsWith('/help'), 'down': $route.path.startsWith('/help') && this.isDesktop()}" :class="{
'active': $route.path.startsWith('/help'),
'down': $route.path.startsWith('/help') && isDesktop()}"
> >
<div <div
class="chevron rotate" class="chevron rotate"

View File

@@ -1,7 +1,8 @@
<template lang="pug" functional> <template functional>
span.message-count( <span
:class="{'top-count': props.top === true, 'top-count-gray': props.gray === true}" class="message-count"
) {{props.count}} :class="{'top-count': props.top === true, 'top-count-gray': props.gray === true}"
> {{ props.count }} </span>
</template> </template>
<style lang="scss"> <style lang="scss">

View File

@@ -1,3 +1,3 @@
<template lang="pug" functional> <template functional>
div {{ props.notification }} <div>{{ props.notification }}</div>
</template> </template>

View File

@@ -81,7 +81,7 @@ export default {
return; return;
} }
if (!confirm(this.$t('confirmNeedsWork'))) return; if (!window.confirm(this.$t('confirmNeedsWork'))) return;
await this.$store.dispatch('tasks:needsWork', { await this.$store.dispatch('tasks:needsWork', {
taskId: this.notification.data.groupTaskId, taskId: this.notification.data.groupTaskId,

View File

@@ -60,7 +60,7 @@ export default {
async accept () { async accept () {
const group = this.notification.data; const group = this.notification.data;
if (group.cancelledPlan && !confirm(this.$t('aboutToJoinCancelledGroupPlan'))) { if (group.cancelledPlan && !window.confirm(this.$t('aboutToJoinCancelledGroupPlan'))) {
return; return;
} }

View File

@@ -40,7 +40,7 @@ export default {
async accept () { async accept () {
const group = this.notification.data; const group = this.notification.data;
if (group.cancelledPlan && !confirm(this.$t('aboutToJoinCancelledGroupPlan'))) { if (group.cancelledPlan && !window.confirm(this.$t('aboutToJoinCancelledGroupPlan'))) {
return; return;
} }

View File

@@ -50,6 +50,7 @@
</base-notification> </base-notification>
</template> </template>
<!-- eslint-disable max-len -->
<style lang="scss" scoped> <style lang="scss" scoped>
.background { .background {
position: relative; position: relative;
@@ -157,6 +158,7 @@
color: #fff; color: #fff;
} }
</style> </style>
<!-- eslint-enable max-len -->
<script> <script>
import * as quests from '@/../../common/script/content/quests'; import * as quests from '@/../../common/script/content/quests';
@@ -183,10 +185,6 @@ export default {
worldBoss: {}, worldBoss: {},
}; };
}, },
async mounted () {
const result = await this.$store.dispatch('worldState:getWorldState');
this.worldBoss = result.worldBoss;
},
computed: { computed: {
...mapState({ user: 'user.data' }), ...mapState({ user: 'user.data' }),
bossHp () { bossHp () {
@@ -196,6 +194,10 @@ export default {
return this.questData.boss.hp.toLocaleString(); return this.questData.boss.hp.toLocaleString();
}, },
}, },
async mounted () {
const result = await this.$store.dispatch('worldState:getWorldState');
this.worldBoss = result.worldBoss;
},
methods: { methods: {
action () { action () {
this.$router.push({ name: 'tavern' }); this.$router.push({ name: 'tavern' });

View File

@@ -24,7 +24,8 @@
</div> </div>
<div slot="dropdown-content"> <div slot="dropdown-content">
<div <div
class="dropdown-item dropdown-separated d-flex justify-content-between dropdown-inactive align-items-center" class="dropdown-item dropdown-separated
d-flex justify-content-between dropdown-inactive align-items-center"
@click.stop @click.stop
> >
<h4 <h4
@@ -49,7 +50,8 @@
/> />
<div <div
v-if="notificationsCount === 0" v-if="notificationsCount === 0"
class="dropdown-item dropdown-separated d-flex justify-content-center dropdown-inactive no-notifications flex-column" class="dropdown-item dropdown-separated
d-flex justify-content-center dropdown-inactive no-notifications flex-column"
> >
<div <div
class="svg-icon" class="svg-icon"

View File

@@ -31,7 +31,8 @@
<span class="small-text">{{ $t('editAvatar') }}</span> <span class="small-text">{{ $t('editAvatar') }}</span>
</a> </a>
<a <a
class="nav-link dropdown-item dropdown-separated d-flex justify-content-between align-items-center" class="nav-link dropdown-item
dropdown-separated d-flex justify-content-between align-items-center"
@click.prevent="showInbox()" @click.prevent="showInbox()"
> >
<div>{{ $t('messages') }}</div> <div>{{ $t('messages') }}</div>
@@ -73,7 +74,7 @@
@click.prevent="logout()" @click.prevent="logout()"
>{{ $t('logout') }}</a> >{{ $t('logout') }}</a>
<li <li
v-if="!this.user.purchased.plan.customerId" v-if="!user.purchased.plan.customerId"
@click="showBuyGemsModal('subscribe')" @click="showBuyGemsModal('subscribe')"
> >
<div class="dropdown-item text-center"> <div class="dropdown-item text-center">

View File

@@ -13,7 +13,7 @@
<h2 v-once> <h2 v-once>
{{ $t('filter') }} {{ $t('filter') }}
</h2> </h2>
<h3>{{ this.groupBy === 'type' ? $t('equipmentType') : $t('class') }}</h3> <h3>{{ groupBy === 'type' ? $t('equipmentType') : $t('class') }}</h3>
<div class="form-group"> <div class="form-group">
<div <div
v-for="group in itemsGroups" v-for="group in itemsGroups"
@@ -122,11 +122,14 @@
:key="flatGear[activeItems[group]] ? flatGear[activeItems[group]].key : group" :key="flatGear[activeItems[group]] ? flatGear[activeItems[group]].key : group"
class="pointer" class="pointer"
:item="flatGear[activeItems[group]]" :item="flatGear[activeItems[group]]"
:item-content-class="flatGear[activeItems[group]] ? 'shop_' + flatGear[activeItems[group]].key : null" :item-content-class="flatGear[activeItems[group]]
:empty-item="!flatGear[activeItems[group]] || flatGear[activeItems[group]].key.indexOf('_base_0') !== -1" ? 'shop_' + flatGear[activeItems[group]].key : null"
:empty-item="!flatGear[activeItems[group]]
|| flatGear[activeItems[group]].key.indexOf('_base_0') !== -1"
:label="label" :label="label"
:popover-position="'top'" :popover-position="'top'"
:show-popover="flatGear[activeItems[group]] && Boolean(flatGear[activeItems[group]].text)" :show-popover="flatGear[activeItems[group]]
&& Boolean(flatGear[activeItems[group]].text)"
@click="equipItem(flatGear[activeItems[group]])" @click="equipItem(flatGear[activeItems[group]])"
> >
<template <template
@@ -148,12 +151,14 @@
</item> </item>
</div> </div>
</drawer> </drawer>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="group in itemsGroups" v-for="group in itemsGroups"
v-if="!anyFilterSelected || viewOptions[group.key].selected" v-if="!anyFilterSelected || viewOptions[group.key].selected"
:key="group.key" :key="group.key"
:class="group.key" :class="group.key"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<h2 class="mb-3"> <h2 class="mb-3">
{{ group.label }} {{ group.label }}
<span <span

View File

@@ -72,11 +72,14 @@
</b-dropdown> </b-dropdown>
</div> </div>
</div> </div>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="group in groups" v-for="group in groups"
v-if="!anyFilterSelected || group.selected" v-if="!anyFilterSelected || group.selected"
:key="group.key" :key="group.key"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<h2 class="mb-3"> <h2 class="mb-3">
{{ $t(group.key) }} {{ $t(group.key) }}
<span <span
@@ -472,7 +475,7 @@ export default {
quantity: this.user.purchased.plan.mysteryItems.length, quantity: this.user.purchased.plan.mysteryItems.length,
}); });
for (const type in this.content.cardTypes) { for (const type of Object.keys(this.content.cardTypes)) {
const card = this.user.items.special[`${type}Received`] || []; const card = this.user.items.special[`${type}Received`] || [];
if (this.user.items.special[type] > 0 || card.length > 0) { if (this.user.items.special[type] > 0 || card.length > 0) {
specialArray.push({ specialArray.push({

View File

@@ -17,7 +17,9 @@
</h4> </h4>
<div <div
class="text" class="text"
v-html="$t('hatchDialogText', { potionName: hatchablePet.potionName, eggName: hatchablePet.eggName, petName: hatchablePet.name })" v-html="$t('hatchDialogText', {
potionName: hatchablePet.potionName,
eggName: hatchablePet.eggName, petName: hatchablePet.name })"
></div> ></div>
</div> </div>
<span <span

View File

@@ -134,21 +134,27 @@
class="badge badge-pill badge-default" class="badge badge-pill badge-default"
>{{ countOwnedAnimals(petGroups[0], 'pet') }}</span> >{{ countOwnedAnimals(petGroups[0], 'pet') }}</span>
</h2> </h2>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="(petGroup, index) in petGroups" v-for="(petGroup) in petGroups"
v-if="!anyFilterSelected || viewOptions[petGroup.key].selected" v-if="!anyFilterSelected || viewOptions[petGroup.key].selected"
:key="petGroup.key" :key="petGroup.key"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<h4 v-if="viewOptions[petGroup.key].animalCount !== 0"> <h4 v-if="viewOptions[petGroup.key].animalCount !== 0">
{{ petGroup.label }} {{ petGroup.label }}
</h4> </h4>
<!-- eslint-disable vue/no-use-v-if-with-v-for, max-len -->
<div <div
v-for="(group, key, index) in pets(petGroup, hideMissing, selectedSortBy, searchTextThrottled)" v-for="(group, key, index) in pets(petGroup, hideMissing, selectedSortBy, searchTextThrottled)"
v-if="index === 0 || $_openedItemRows_isToggled(petGroup.key)" v-if="index === 0 || $_openedItemRows_isToggled(petGroup.key)"
:key="key"
class="pet-row d-flex" class="pet-row d-flex"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div <div
v-for="item in group" v-for="item in group"
:key="item.key"
v-drag.drop.food="item.key" v-drag.drop.food="item.key"
class="pet-group" class="pet-group"
:class="{'last': item.isLastInRow}" :class="{'last': item.isLastInRow}"
@@ -190,21 +196,27 @@
class="badge badge-pill badge-default" class="badge badge-pill badge-default"
>{{ countOwnedAnimals(mountGroups[0], 'mount') }}</span> >{{ countOwnedAnimals(mountGroups[0], 'mount') }}</span>
</h2> </h2>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="mountGroup in mountGroups" v-for="mountGroup in mountGroups"
v-if="!anyFilterSelected || viewOptions[mountGroup.key].selected" v-if="!anyFilterSelected || viewOptions[mountGroup.key].selected"
:key="mountGroup.key" :key="mountGroup.key"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<h4 v-if="viewOptions[mountGroup.key].animalCount != 0"> <h4 v-if="viewOptions[mountGroup.key].animalCount != 0">
{{ mountGroup.label }} {{ mountGroup.label }}
</h4> </h4>
<!-- eslint-disable vue/no-use-v-if-with-v-for, max-len -->
<div <div
v-for="(group, key, index) in mounts(mountGroup, hideMissing, selectedSortBy, searchTextThrottled)" v-for="(group, key, index) in mounts(mountGroup, hideMissing, selectedSortBy, searchTextThrottled)"
v-if="index === 0 || $_openedItemRows_isToggled(mountGroup.key)" v-if="index === 0 || $_openedItemRows_isToggled(mountGroup.key)"
:key="key"
class="pet-row d-flex" class="pet-row d-flex"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div <div
v-for="item in group" v-for="item in group"
:key="item.key"
class="pet-group" class="pet-group"
> >
<mountItem <mountItem
@@ -219,7 +231,6 @@
</span> </span>
<template <template
slot="itemBadge" slot="itemBadge"
slot-scope="context"
> >
<starBadge <starBadge
:selected="item.key === currentMount" :selected="item.key === currentMount"
@@ -459,8 +470,6 @@ import _throttle from 'lodash/throttle';
import groupBy from 'lodash/groupBy'; import groupBy from 'lodash/groupBy';
import { mapState } from '@/libs/store'; import { mapState } from '@/libs/store';
import Item from '../item';
import ItemRows from '@/components/ui/itemRows';
import PetItem from './petItem'; import PetItem from './petItem';
import MountItem from './mountItem.vue'; import MountItem from './mountItem.vue';
import FoodItem from './foodItem'; import FoodItem from './foodItem';
@@ -468,11 +477,8 @@ import HatchedPetDialog from './hatchedPetDialog';
import MountRaisedModal from './mountRaisedModal'; import MountRaisedModal from './mountRaisedModal';
import WelcomeModal from './welcomeModal'; import WelcomeModal from './welcomeModal';
import HatchingModal from './hatchingModal'; import HatchingModal from './hatchingModal';
import Drawer from '@/components/ui/drawer';
import toggleSwitch from '@/components/ui/toggleSwitch'; import toggleSwitch from '@/components/ui/toggleSwitch';
import StarBadge from '@/components/ui/starBadge'; import StarBadge from '@/components/ui/starBadge';
import CountBadge from '@/components/ui/countBadge';
import DrawerSlider from '@/components/ui/drawerSlider';
import InventoryDrawer from '@/components/shared/inventoryDrawer'; import InventoryDrawer from '@/components/shared/inventoryDrawer';
import ResizeDirective from '@/directives/resize.directive'; import ResizeDirective from '@/directives/resize.directive';
@@ -500,15 +506,10 @@ let lastMouseMoveEvent = {};
export default { export default {
components: { components: {
PetItem, PetItem,
Item,
ItemRows,
FoodItem, FoodItem,
MountItem, MountItem,
Drawer,
toggleSwitch, toggleSwitch,
StarBadge, StarBadge,
CountBadge,
DrawerSlider,
HatchedPetDialog, HatchedPetDialog,
MountRaisedModal, MountRaisedModal,
WelcomeModal, WelcomeModal,

View File

@@ -92,7 +92,7 @@ export default {
this.$set(this.amazonPayments, 'loggedIn', true); this.$set(this.amazonPayments, 'loggedIn', true);
this.$root.$emit('habitica::pay-with-amazon', this.amazonPayments); return this.$root.$emit('habitica::pay-with-amazon', this.amazonPayments);
}, },
authorization: () => { authorization: () => {
if (this.amazonDisabled === true) return; if (this.amazonDisabled === true) return;

View File

@@ -546,16 +546,16 @@
} }
.gem-count { .gem-count {
font-family: Roboto; font-family: Roboto;
font-size: 40px; font-size: 40px;
font-weight: bold; font-weight: bold;
color: #2995cd; color: #2995cd;
} }
.gem-text { .gem-text {
font-family: Roboto; font-family: Roboto;
font-size: 16px; font-size: 16px;
color: #a5a1ac; color: #a5a1ac;
margin-bottom: 1em; margin-bottom: 1em;
} }
@@ -608,10 +608,10 @@
} }
.subscription-price { .subscription-price {
font-family: Roboto Condensed; font-family: Roboto Condensed;
font-size: 48px; font-size: 48px;
font-weight: bold; font-weight: bold;
color: #1ca372; color: #1ca372;
} }
.superscript { .superscript {
@@ -670,7 +670,6 @@ import amazonButton from '@/components/payments/amazonButton';
export default { export default {
components: { components: {
planGemLimits,
amazonButton, amazonButton,
}, },
directives: { directives: {
@@ -705,7 +704,8 @@ export default {
}, },
userReachedGemCap () { userReachedGemCap () {
return this.user.purchased.plan.customerId return this.user.purchased.plan.customerId
&& this.user.purchased.plan.gemsBought >= this.user.purchased.plan.consecutive.gemCapExtra + this.planGemLimits.convCap; && this.user.purchased.plan.gemsBought
>= (this.user.purchased.plan.consecutive.gemCapExtra + this.planGemLimits.convCap);
}, },
}, },
watch: { watch: {

View File

@@ -78,11 +78,14 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="form-group"> <div class="form-group">
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="block in subscriptionBlocks" v-for="block in subscriptionBlocks"
v-if="block.target !== 'group' && block.canSubscribe === true" v-if="block.target !== 'group' && block.canSubscribe === true"
:key="block.key"
class="radio" class="radio"
> >
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<label> <label>
<input <input
v-model="gift.subscription.key" v-model="gift.subscription.key"

View File

@@ -38,7 +38,8 @@
</div> </div>
</template> </template>
<template <template
v-if="paymentData.paymentType === 'gift-gems' || paymentData.paymentType === 'gift-gems-balance'" v-if="paymentData.paymentType === 'gift-gems'
|| paymentData.paymentType === 'gift-gems-balance'"
> >
<span v-html="$t('paymentYouSentGems', {name: paymentData.giftReceiver})"></span> <span v-html="$t('paymentYouSentGems', {name: paymentData.giftReceiver})"></span>
<div class="details-block gems"> <div class="details-block gems">
@@ -52,29 +53,34 @@
</template> </template>
<template v-if="paymentData.paymentType === 'gift-subscription'"> <template v-if="paymentData.paymentType === 'gift-subscription'">
<span <span
v-html="$t('paymentYouSentSubscription', {name: paymentData.giftReceiver, months: paymentData.subscription.months})" v-html="$t('paymentYouSentSubscription', {
name: paymentData.giftReceiver, months: paymentData.subscription.months})"
></span> ></span>
</template> </template>
<template v-if="paymentData.paymentType === 'subscription'"> <template v-if="paymentData.paymentType === 'subscription'">
<strong v-once>{{ $t('nowSubscribed') }}</strong> <strong v-once>{{ $t('nowSubscribed') }}</strong>
<div class="details-block"> <div class="details-block">
<span <span
v-html="$t('paymentSubBilling', {amount: paymentData.subscription.price, months: paymentData.subscription.months})" v-html="$t('paymentSubBilling', {
amount: paymentData.subscription.price, months: paymentData.subscription.months})"
></span> ></span>
</div> </div>
</template> </template>
<template v-if="paymentData.paymentType === 'groupPlan'"> <template v-if="paymentData.paymentType === 'groupPlan'">
<span <span
v-html="$t(paymentData.newGroup ? 'groupPlanCreated' : 'groupPlanUpgraded', {groupName: paymentData.group.name})" v-html="$t(paymentData.newGroup
? 'groupPlanCreated' : 'groupPlanUpgraded', {groupName: paymentData.group.name})"
></span> ></span>
<div class="details-block"> <div class="details-block">
<span <span
v-html="$t('paymentSubBilling', {amount: groupPlanCost, months: paymentData.subscription.months})" v-html="$t('paymentSubBilling', {
amount: groupPlanCost, months: paymentData.subscription.months})"
></span> ></span>
</div> </div>
</template> </template>
<template <template
v-if="paymentData.paymentType === 'groupPlan' || paymentData.paymentType === 'subscription'" v-if="paymentData.paymentType === 'groupPlan'
|| paymentData.paymentType === 'subscription'"
> >
<span <span
v-once v-once

View File

@@ -68,7 +68,10 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(webhook, index) in user.webhooks"> <tr
v-for="(webhook, index) in user.webhooks"
:key="webhook.id"
>
<td> <td>
<input <input
v-model="webhook.enabled" v-model="webhook.enabled"

View File

@@ -38,7 +38,10 @@
<span>{{ $t('push') }}</span> <span>{{ $t('push') }}</span>
</th> </th>
</tr> </tr>
<tr v-for="notification in notificationsIds"> <tr
v-for="notification in notificationsIds"
:key="notification"
>
<td> <td>
<span>{{ $t(notification) }}</span> <span>{{ $t(notification) }}</span>
</td> </td>

View File

@@ -50,7 +50,8 @@
data-for="stats.gp" data-for="stats.gp"
> >
</div> </div>
<!--input.form-control(type='number', step="any", data-for='stats.gp', v-model='restoreValues.stats.gp',disabled)--> <!--input.form-control(type='number',
step="any", data-for='stats.gp', v-model='restoreValues.stats.gp',disabled)-->
</div> </div>
<div class="form-group row"> <div class="form-group row">
<div class="col-sm-3"> <div class="col-sm-3">

View File

@@ -16,6 +16,7 @@
> >
<option <option
v-for="lang in availableLanguages" v-for="lang in availableLanguages"
:key="lang.code"
:value="lang.code" :value="lang.code"
> >
{{ lang.name }} {{ lang.name }}
@@ -37,6 +38,7 @@
> >
<option <option
v-for="dateFormat in availableFormats" v-for="dateFormat in availableFormats"
:key="dateFormat"
:value="dateFormat" :value="dateFormat"
> >
{{ dateFormat }} {{ dateFormat }}
@@ -54,6 +56,7 @@
> >
<option <option
v-for="sound in availableAudioThemes" v-for="sound in availableAudioThemes"
:key="sound"
:value="sound" :value="sound"
> >
{{ $t(`audioTheme_${sound}`) }} {{ $t(`audioTheme_${sound}`) }}
@@ -217,6 +220,7 @@
> >
<option <option
v-for="option in dayStartOptions" v-for="option in dayStartOptions"
:key="option.value"
:value="option.value" :value="option.value"
> >
{{ option.name }} {{ option.name }}
@@ -252,7 +256,10 @@
<div class="panel-body"> <div class="panel-body">
<div> <div>
<ul class="list-inline"> <ul class="list-inline">
<li v-for="network in SOCIAL_AUTH_NETWORKS"> <li
v-for="network in SOCIAL_AUTH_NETWORKS"
:key="network.key"
>
<button <button
v-if="!user.auth[network.key].id" v-if="!user.auth[network.key].id"
class="btn btn-primary mb-2" class="btn btn-primary mb-2"
@@ -343,6 +350,7 @@
> >
<div <div
v-for="issue in displayNameIssues" v-for="issue in displayNameIssues"
:key="issue"
class="input-error" class="input-error"
> >
{{ issue }} {{ issue }}
@@ -390,6 +398,7 @@
> >
<div <div
v-for="issue in usernameIssues" v-for="issue in usernameIssues"
:key="issue"
class="input-error" class="input-error"
> >
{{ issue }} {{ issue }}
@@ -754,10 +763,10 @@ export default {
return true; return true;
} }
return find(this.SOCIAL_AUTH_NETWORKS, network => { return this.SOCIAL_AUTH_NETWORKS.find(network => {
if (network.key !== networkKeyToCheck) { if (network.key !== networkKeyToCheck) {
if (this.user.auth[network.key]) { if (this.user.auth[network.key]) {
return this.user.auth[network.key].id; return !!this.user.auth[network.key].id;
} }
} }

View File

@@ -103,9 +103,9 @@
<span class="glyphicon glyphicon-forward"></span> <span class="glyphicon glyphicon-forward"></span>
&nbsp; {{ $t('consecutiveSubscription') }} &nbsp; {{ $t('consecutiveSubscription') }}
<ul class="list-unstyled"> <ul class="list-unstyled">
<li>{{ $t('consecutiveMonths') }} {{ user.purchased.plan.consecutive.count + user.purchased.plan.consecutive.offset }}</li> <li>{{ $t('consecutiveMonths') }} {{ user.purchased.plan.consecutive.count + user.purchased.plan.consecutive.offset }}</li> <!-- eslint-disable-line max-len -->
<li>{{ $t('gemCapExtra') }} {{ user.purchased.plan.consecutive.gemCapExtra }}</li> <li>{{ $t('gemCapExtra') }} {{ user.purchased.plan.consecutive.gemCapExtra }}</li>
<li>{{ $t('mysticHourglasses') }} {{ user.purchased.plan.consecutive.trinkets }}</li> <li>{{ $t('mysticHourglasses') }} {{ user.purchased.plan.consecutive.trinkets }}</li> <!-- eslint-disable-line max-len -->
</ul> </ul>
</td> </td>
</tr> </tr>
@@ -115,11 +115,14 @@
{{ $t("resubscribe") }} {{ $t("resubscribe") }}
</h4> </h4>
<div class="form-group reduce-top-margin"> <div class="form-group reduce-top-margin">
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="block in subscriptionBlocksOrdered" v-for="block in subscriptionBlocksOrdered"
v-if="block.target !== 'group' && block.canSubscribe === true" v-if="block.target !== 'group' && block.canSubscribe === true"
:key="block.key"
class="radio" class="radio"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<label> <label>
<input <input
v-model="subscription.key" v-model="subscription.key"
@@ -207,7 +210,8 @@
</button> </button>
<amazon-button <amazon-button
class="payment-item" class="payment-item"
:amazon-data="{type: 'subscription', subscription: this.subscription.key, coupon: this.subscription.coupon}" :amazon-data="{
type: 'subscription', subscription: subscription.key, coupon: subscription.coupon}"
/> />
</div> </div>
</div> </div>

View File

@@ -13,7 +13,9 @@
class="form-control" class="form-control"
type="text" type="text"
:placeholder="$t('newDisplayName')" :placeholder="$t('newDisplayName')"
:class="{'is-invalid input-invalid': displayNameInvalid, 'input-valid': displayNameValid, 'text-darker': temporaryDisplayName.length > 0}" :class="{
'is-invalid input-invalid': displayNameInvalid,
'input-valid': displayNameValid, 'text-darker': temporaryDisplayName.length > 0}"
@blur="restoreEmptyDisplayName()" @blur="restoreEmptyDisplayName()"
> >
</div> </div>
@@ -25,6 +27,7 @@
> >
<div <div
v-for="issue in displayNameIssues" v-for="issue in displayNameIssues"
:key="issue"
class="input-error text-center" class="input-error text-center"
> >
{{ issue }} {{ issue }}
@@ -45,7 +48,9 @@
class="form-control" class="form-control"
type="text" type="text"
:placeholder="$t('newUsername')" :placeholder="$t('newUsername')"
:class="{'is-invalid input-invalid': usernameInvalid, 'input-valid': usernameValid, 'text-darker': temporaryUsername.length > 0}" :class="{
'is-invalid input-invalid': usernameInvalid,
'input-valid': usernameValid, 'text-darker': temporaryUsername.length > 0}"
@blur="restoreEmptyUsername()" @blur="restoreEmptyUsername()"
> >
</div> </div>
@@ -58,6 +63,7 @@
> >
<div <div
v-for="issue in usernameIssues" v-for="issue in usernameIssues"
:key="issue"
class="input-error text-center" class="input-error text-center"
> >
{{ issue }} {{ issue }}

View File

@@ -65,16 +65,12 @@ import { mapState } from '@/libs/store';
import inventoryUtils from '@/mixins/inventoryUtils'; import inventoryUtils from '@/mixins/inventoryUtils';
import svgInformation from '@/assets/svg/information.svg'; import svgInformation from '@/assets/svg/information.svg';
import CountBadge from '@/components/ui/countBadge';
import Item from '@/components/inventory/item';
import Drawer from '@/components/ui/drawer'; import Drawer from '@/components/ui/drawer';
import DrawerSlider from '@/components/ui/drawerSlider'; import DrawerSlider from '@/components/ui/drawerSlider';
import DrawerHeaderTabs from '@/components/ui/drawerHeaderTabs'; import DrawerHeaderTabs from '@/components/ui/drawerHeaderTabs';
export default { export default {
components: { components: {
Item,
CountBadge,
Drawer, Drawer,
DrawerSlider, DrawerSlider,
DrawerHeaderTabs, DrawerHeaderTabs,

View File

@@ -11,8 +11,8 @@ export default {
}), }),
}, },
methods: { methods: {
enoughCurrency (currency, amount) { enoughCurrency (currency, amount) { // eslint-disable-line consistent-return
switch (currency) { switch (currency) { // eslint-disable-line default-case
case 'gold': case 'gold':
return this.userGold >= amount; return this.userGold >= amount;
case 'gems': case 'gems':

View File

@@ -123,7 +123,8 @@
{{ $t('notEnoughGemsToBuy') }} {{ $t('notEnoughGemsToBuy') }}
</div> </div>
<button <button
v-if="getPriceClass() === 'gems' && !this.enoughCurrency(getPriceClass(), item.value * selectedAmountToBuy)" v-if="getPriceClass() === 'gems'
&& !enoughCurrency(getPriceClass(), item.value * selectedAmountToBuy)"
class="btn btn-primary" class="btn btn-primary"
@click="purchaseGems()" @click="purchaseGems()"
> >
@@ -132,8 +133,10 @@
<button <button
v-else v-else
class="btn btn-primary" class="btn btn-primary"
:disabled="item.key === 'gem' && gemsLeft === 0 || attemptingToPurchaseMoreGemsThanAreLeft || numberInvalid" :disabled="item.key === 'gem' && gemsLeft === 0 ||
:class="{'notEnough': !preventHealthPotion || !this.enoughCurrency(getPriceClass(), item.value * selectedAmountToBuy)}" attemptingToPurchaseMoreGemsThanAreLeft || numberInvalid"
:class="{'notEnough': !preventHealthPotion ||
!enoughCurrency(getPriceClass(), item.value * selectedAmountToBuy)}"
@click="buyItem()" @click="buyItem()"
> >
{{ $t('buyNow') }} {{ $t('buyNow') }}
@@ -406,6 +409,21 @@ export default {
Avatar, Avatar,
}, },
mixins: [buyMixin, currencyMixin, notifications, numberInvalid, spellsMixin], mixins: [buyMixin, currencyMixin, notifications, numberInvalid, spellsMixin],
props: {
item: {
type: Object,
},
priceType: {
type: String,
},
withPin: {
type: Boolean,
},
genericPurchase: {
type: Boolean,
default: true,
},
},
data () { data () {
return { return {
icons: Object.freeze({ icons: Object.freeze({
@@ -595,20 +613,5 @@ export default {
return {}; return {};
}, },
}, },
props: {
item: {
type: Object,
},
priceType: {
type: String,
},
withPin: {
type: Boolean,
},
genericPurchase: {
type: Boolean,
default: true,
},
},
}; };
</script> </script>

View File

@@ -52,10 +52,13 @@
</filter-dropdown> </filter-dropdown>
</div> </div>
</layout-section> </layout-section>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="category in categories" v-for="category in categories"
v-if="!anyFilterSelected || viewOptions[category.identifier].selected" v-if="!anyFilterSelected || viewOptions[category.identifier].selected"
:key="category.identifier"
> >
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<h4>{{ category.text }}</h4> <h4>{{ category.text }}</h4>
<category-row <category-row
:hide-pinned="hidePinned" :hide-pinned="hidePinned"
@@ -160,14 +163,11 @@ import _map from 'lodash/map';
import _throttle from 'lodash/throttle'; import _throttle from 'lodash/throttle';
import { mapState } from '@/libs/store'; import { mapState } from '@/libs/store';
import ShopItem from '../shopItem';
import KeysToKennel from './keysToKennel'; import KeysToKennel from './keysToKennel';
import EquipmentSection from './equipmentSection'; import EquipmentSection from './equipmentSection';
import CategoryRow from './categoryRow'; import CategoryRow from './categoryRow';
import Item from '@/components/inventory/item'; import Item from '@/components/inventory/item';
import CountBadge from '@/components/ui/countBadge'; import CountBadge from '@/components/ui/countBadge';
import ItemRows from '@/components/ui/itemRows';
import Avatar from '@/components/avatar';
import InventoryDrawer from '@/components/shared/inventoryDrawer'; import InventoryDrawer from '@/components/shared/inventoryDrawer';
import FeaturedItemsHeader from '../featuredItemsHeader'; import FeaturedItemsHeader from '../featuredItemsHeader';
import PageLayout from '@/components/ui/pageLayout'; import PageLayout from '@/components/ui/pageLayout';
@@ -176,8 +176,6 @@ import FilterDropdown from '@/components/ui/filterDropdown';
import MarketFilter from './filter'; import MarketFilter from './filter';
import SellModal from './sellModal.vue'; import SellModal from './sellModal.vue';
import EquipmentAttributesGrid from '../../inventory/equipment/attributesGrid.vue';
import SelectMembersModal from '@/components/selectMembersModal.vue';
import svgPin from '@/assets/svg/pin.svg'; import svgPin from '@/assets/svg/pin.svg';
import svgGem from '@/assets/svg/gem.svg'; import svgGem from '@/assets/svg/gem.svg';
@@ -197,16 +195,11 @@ const sortItems = ['AZ', 'sortByNumber'].map(g => ({ id: g }));
export default { export default {
components: { components: {
ShopItem,
KeysToKennel, KeysToKennel,
Item, Item,
CountBadge, CountBadge,
ItemRows,
SellModal, SellModal,
EquipmentAttributesGrid,
Avatar,
InventoryDrawer, InventoryDrawer,
FeaturedItemsHeader, FeaturedItemsHeader,
@@ -216,8 +209,6 @@ export default {
EquipmentSection, EquipmentSection,
CategoryRow, CategoryRow,
MarketFilter, MarketFilter,
SelectMembersModal,
}, },
mixins: [notifications, buyMixin, currencyMixin, inventoryUtils, pinUtils], mixins: [notifications, buyMixin, currencyMixin, inventoryUtils, pinUtils],
data () { data () {

View File

@@ -52,7 +52,8 @@
>{{ item.value }}</span> >{{ item.value }}</span>
</div> </div>
<button <button
v-if="priceType === 'gems' && !this.enoughCurrency(priceType, item.value * selectedAmountToBuy)" v-if="priceType === 'gems'
&& !enoughCurrency(priceType, item.value * selectedAmountToBuy)"
class="btn btn-primary" class="btn btn-primary"
@click="purchaseGems()" @click="purchaseGems()"
> >
@@ -61,7 +62,7 @@
<button <button
v-else v-else
class="btn btn-primary" class="btn btn-primary"
:class="{'notEnough': !this.enoughCurrency(priceType, item.value * selectedAmountToBuy)}" :class="{'notEnough': !enoughCurrency(priceType, item.value * selectedAmountToBuy)}"
:disabled="numberInvalid" :disabled="numberInvalid"
@click="buyItem()" @click="buyItem()"
> >
@@ -247,7 +248,6 @@ import svgHourglasses from '@/assets/svg/hourglass.svg';
import BalanceInfo from '../balanceInfo.vue'; import BalanceInfo from '../balanceInfo.vue';
import currencyMixin from '../_currencyMixin'; import currencyMixin from '../_currencyMixin';
import QuestInfo from './questInfo.vue';
import notifications from '@/mixins/notifications'; import notifications from '@/mixins/notifications';
import buyMixin from '@/mixins/buy'; import buyMixin from '@/mixins/buy';
import numberInvalid from '@/mixins/numberInvalid'; import numberInvalid from '@/mixins/numberInvalid';
@@ -258,7 +258,6 @@ import questDialogContent from './questDialogContent';
export default { export default {
components: { components: {
BalanceInfo, BalanceInfo,
QuestInfo,
questDialogDrops, questDialogDrops,
questDialogContent, questDialogContent,
}, },

View File

@@ -139,13 +139,17 @@
</b-dropdown> </b-dropdown>
</div> </div>
</div> </div>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="category in categories" v-for="category in categories"
v-if="!anyFilterSelected || viewOptions[category.identifier].selected" v-if="!anyFilterSelected || viewOptions[category.identifier].selected"
:key="category.identifier"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<h2 class="mb-3"> <h2 class="mb-3">
{{ category.text }} {{ category.text }}
</h2> </h2>
<!-- eslint-disable max-len -->
<itemRows <itemRows
v-if="category.identifier === 'pet'" v-if="category.identifier === 'pet'"
:items="questItems(category, selectedSortItemsBy, searchTextThrottled, hideLocked, hidePinned)" :items="questItems(category, selectedSortItemsBy, searchTextThrottled, hideLocked, hidePinned)"
@@ -153,6 +157,7 @@
:item-margin="24" :item-margin="24"
:type="'pet_quests'" :type="'pet_quests'"
> >
<!-- eslint-enable max-len -->
<template <template
slot="item" slot="item"
slot-scope="ctx" slot-scope="ctx"
@@ -201,11 +206,14 @@
v-else-if="category.identifier === 'unlockable' || category.identifier === 'gold'" v-else-if="category.identifier === 'unlockable' || category.identifier === 'gold'"
class="grouped-parent" class="grouped-parent"
> >
<!-- eslint-disable vue/no-use-v-if-with-v-for, max-len -->
<div <div
v-for="(items, key) in getGrouped(questItems(category, selectedSortItemsBy, searchTextThrottled, hideLocked, hidePinned))" v-for="(items, key) in getGrouped(questItems(category, selectedSortItemsBy,searchTextThrottled, hideLocked, hidePinned))"
v-if="key !== 'questGroupEarnable'" v-if="key !== 'questGroupEarnable'"
:key="key"
class="group" class="group"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for, max-len -->
<h3>{{ $t(key) }}</h3> <h3>{{ $t(key) }}</h3>
<div class="items"> <div class="items">
<shopItem <shopItem
@@ -233,9 +241,11 @@
class="popover-content-text" class="popover-content-text"
>{{ `${$t('questUnlockLostMasterclasser')}` }}</div> >{{ `${$t('questUnlockLostMasterclasser')}` }}</div>
<div <div
v-if="item.locked && item.unlockCondition && item.unlockCondition.incentiveThreshold" v-if="item.locked && item.unlockCondition
&& item.unlockCondition.incentiveThreshold"
class="popover-content-text" class="popover-content-text"
>{{ `${$t('loginIncentiveQuest', {count: item.unlockCondition.incentiveThreshold})}` }}</div> >{{ `${$t('loginIncentiveQuest', {
count: item.unlockCondition.incentiveThreshold})}` }}</div>
<div <div
v-if="item.locked && item.previous && isBuyingDependentOnPrevious(item)" v-if="item.locked && item.previous && isBuyingDependentOnPrevious(item)"
class="popover-content-text" class="popover-content-text"
@@ -278,7 +288,8 @@
class="items" class="items"
> >
<shopItem <shopItem
v-for="item in questItems(category, selectedSortItemsBy, searchTextThrottled, hideLocked, hidePinned)" v-for="item in questItems(category, selectedSortItemsBy,
searchTextThrottled, hideLocked, hidePinned)"
:key="item.key" :key="item.key"
:item="item" :item="item"
:price="item.value" :price="item.value"
@@ -484,7 +495,6 @@ import Item from '@/components/inventory/item';
import CountBadge from '@/components/ui/countBadge'; import CountBadge from '@/components/ui/countBadge';
import ItemRows from '@/components/ui/itemRows'; import ItemRows from '@/components/ui/itemRows';
import toggleSwitch from '@/components/ui/toggleSwitch'; import toggleSwitch from '@/components/ui/toggleSwitch';
import Avatar from '@/components/avatar';
import buyMixin from '@/mixins/buy'; import buyMixin from '@/mixins/buy';
import pinUtils from '@/mixins/pinUtils'; import pinUtils from '@/mixins/pinUtils';
import currencyMixin from '../_currencyMixin'; import currencyMixin from '../_currencyMixin';
@@ -507,7 +517,6 @@ export default {
ItemRows, ItemRows,
toggleSwitch, toggleSwitch,
Avatar,
BuyModal, BuyModal,
QuestInfo, QuestInfo,
}, },

View File

@@ -25,6 +25,7 @@
</div> </div>
<div <div
v-for="drop in getDropsList(item.drop.items, false)" v-for="drop in getDropsList(item.drop.items, false)"
:key="drop.key"
class="reward-item" class="reward-item"
> >
<span class="icon"> <span class="icon">
@@ -46,6 +47,7 @@
</h3> </h3>
<div <div
v-for="drop in getDropsList(item.drop.items, true)" v-for="drop in getDropsList(item.drop.items, true)"
:key="drop.key"
class="reward-item" class="reward-item"
> >
<span class="icon"> <span class="icon">

View File

@@ -9,7 +9,10 @@
> >
<dt>{{ $t('collect') + ':' }}</dt> <dt>{{ $t('collect') + ':' }}</dt>
<dd> <dd>
<div v-for="(collect, key) of quest.collect"> <div
v-for="(collect, key) of quest.collect"
:key="key"
>
<span>{{ collect.count }} {{ getCollectText(collect) }}</span> <span>{{ collect.count }} {{ getCollectText(collect) }}</span>
</div> </div>
</dd> </dd>
@@ -26,6 +29,7 @@
<dd> <dd>
<div <div
v-for="star of stars()" v-for="star of stars()"
:key="star"
class="svg-icon inline" class="svg-icon inline"
:class="smallVersion ? 'icon-12' : 'icon-16'" :class="smallVersion ? 'icon-12' : 'icon-16'"
v-html="icons[star]" v-html="icons[star]"

View File

@@ -139,7 +139,10 @@
</b-dropdown> </b-dropdown>
</div> </div>
</div> </div>
<div v-for="(groupSets, categoryGroup) in getGroupedCategories(categories)"> <div
v-for="(groupSets, categoryGroup) in getGroupedCategories(categories)"
:key="categoryGroup"
>
<h3 <h3
v-if="categoryGroup !== 'spells' && categoryGroup !== 'quests'" v-if="categoryGroup !== 'spells' && categoryGroup !== 'quests'"
class="classgroup" class="classgroup"
@@ -156,10 +159,12 @@
<div class="grouped-parent"> <div class="grouped-parent">
<div <div
v-for="category in groupSets" v-for="category in groupSets"
:key="category.identifier"
class="group" class="group"
> >
<h3>{{ category.text }}</h3> <h3>{{ category.text }}</h3>
<div class="items"> <div class="items">
<!-- eslint-disable max-len -->
<shopItem <shopItem
v-for="item in seasonalItems(category, selectedSortItemsBy, searchTextThrottled, viewOptions, hidePinned)" v-for="item in seasonalItems(category, selectedSortItemsBy, searchTextThrottled, viewOptions, hidePinned)"
:key="item.key" :key="item.key"
@@ -170,6 +175,7 @@
:show-event-badge="false" :show-event-badge="false"
@click="itemSelected(item)" @click="itemSelected(item)"
> >
<!-- eslint-enable max-len -->
<template <template
slot="itemBadge" slot="itemBadge"
slot-scope="ctx" slot-scope="ctx"
@@ -194,6 +200,7 @@
</div> </div>
</template> </template>
<!-- eslint-disable max-len -->
<style lang="scss"> <style lang="scss">
@import '~@/assets/scss/colors.scss'; @import '~@/assets/scss/colors.scss';
@import '~@/assets/scss/variables.scss'; @import '~@/assets/scss/variables.scss';
@@ -366,6 +373,7 @@
} }
} }
</style> </style>
<!-- eslint-enable max-len -->
<style scoped> <style scoped>
.margin-center { .margin-center {
@@ -385,12 +393,8 @@ import _reverse from 'lodash/reverse';
import { mapState } from '@/libs/store'; import { mapState } from '@/libs/store';
import ShopItem from '../shopItem'; import ShopItem from '../shopItem';
import Item from '@/components/inventory/item';
import CountBadge from '@/components/ui/countBadge';
import ItemRows from '@/components/ui/itemRows';
import Checkbox from '@/components/ui/checkbox'; import Checkbox from '@/components/ui/checkbox';
import toggleSwitch from '@/components/ui/toggleSwitch'; import toggleSwitch from '@/components/ui/toggleSwitch';
import Avatar from '@/components/avatar';
import buyMixin from '@/mixins/buy'; import buyMixin from '@/mixins/buy';
import currencyMixin from '../_currencyMixin'; import currencyMixin from '../_currencyMixin';
import pinUtils from '@/mixins/pinUtils'; import pinUtils from '@/mixins/pinUtils';
@@ -412,13 +416,8 @@ import shops from '@/../../common/script/libs/shops';
export default { export default {
components: { components: {
ShopItem, ShopItem,
Item,
CountBadge,
ItemRows,
toggleSwitch, toggleSwitch,
Checkbox, Checkbox,
Avatar,
}, },
mixins: [buyMixin, currencyMixin, pinUtils], mixins: [buyMixin, currencyMixin, pinUtils],
data () { data () {

View File

@@ -92,11 +92,15 @@
</b-dropdown-item> </b-dropdown-item>
</b-dropdown> </b-dropdown>
</div> </div>
</div><div </div>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div
v-for="category in categories" v-for="category in categories"
v-if="!anyFilterSelected || (!closed && viewOptions[category.identifier].selected)" v-if="!anyFilterSelected || (!closed && viewOptions[category.identifier].selected)"
:key="category.identifier"
:class="category.identifier" :class="category.identifier"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<h2 class="mb-3"> <h2 class="mb-3">
{{ category.text }} {{ category.text }}
</h2><itemRows </h2><itemRows
@@ -121,11 +125,15 @@
v-if="category !== 'quests'" v-if="category !== 'quests'"
slot="popoverContent" slot="popoverContent"
slot-scope="ctx" slot-scope="ctx"
><div><h4 class="popover-content-title">{{ ctx.item.text }}</h4></div></span><span ><div><h4 class="popover-content-title">{{ ctx.item.text }}</h4></div></span>
<span
v-if="category === 'quests'" v-if="category === 'quests'"
slot="popoverContent" slot="popoverContent"
slot-scope="ctx" ><div class="questPopover">
><div class="questPopover"><h4 class="popover-content-title">{{ item.text }}</h4><questInfo :quest="item" /></div></span><template <h4 class="popover-content-title">{{ item.text }}</h4>
<questInfo :quest="item" />
</div></span>
<template
slot="itemBadge" slot="itemBadge"
slot-scope="ctx" slot-scope="ctx"
> >
@@ -164,6 +172,7 @@
</div> </div>
</template> </template>
<!-- eslint-disable max-len -->
<style lang="scss"> <style lang="scss">
@import '~@/assets/scss/colors.scss'; @import '~@/assets/scss/colors.scss';
@import '~@/assets/scss/variables.scss'; @import '~@/assets/scss/variables.scss';
@@ -297,7 +306,7 @@
} }
</style> </style>
<!-- eslint-enable max-len -->
<script> <script>
import _filter from 'lodash/filter'; import _filter from 'lodash/filter';
@@ -309,13 +318,10 @@ import { mapState } from '@/libs/store';
import ShopItem from '../shopItem'; import ShopItem from '../shopItem';
import Item from '@/components/inventory/item'; import Item from '@/components/inventory/item';
import CountBadge from '@/components/ui/countBadge';
import ItemRows from '@/components/ui/itemRows'; import ItemRows from '@/components/ui/itemRows';
import toggleSwitch from '@/components/ui/toggleSwitch'; import toggleSwitch from '@/components/ui/toggleSwitch';
import Avatar from '@/components/avatar';
import QuestInfo from '../quests/questInfo.vue'; import QuestInfo from '../quests/questInfo.vue';
import BuyModal from '../buyModal.vue';
import BuyQuestModal from '../quests/buyQuestModal.vue'; import BuyQuestModal from '../quests/buyQuestModal.vue';
import svgPin from '@/assets/svg/pin.svg'; import svgPin from '@/assets/svg/pin.svg';
@@ -331,13 +337,10 @@ export default {
components: { components: {
ShopItem, ShopItem,
Item, Item,
CountBadge,
ItemRows, ItemRows,
toggleSwitch, toggleSwitch,
QuestInfo, QuestInfo,
Avatar,
BuyModal,
BuyQuestModal, BuyQuestModal,
}, },
mixins: [pinUtils], mixins: [pinUtils],

View File

@@ -186,8 +186,17 @@
<ul> <ul>
<li>{{ $t('commGuideAKA', {habitName: 'Beffymaroo', realName: 'Beth'}) }}</li> <li>{{ $t('commGuideAKA', {habitName: 'Beffymaroo', realName: 'Beth'}) }}</li>
<li>{{ $t('commGuideAKA', {habitName: 'Viirus', realName: 'Phillip'}) }}</li> <li>{{ $t('commGuideAKA', {habitName: 'Viirus', realName: 'Phillip'}) }}</li>
<li>{{ $t('commGuideAKA', {habitName: 'redphoenix', realName: 'Vicky'}) }} ({{ $t('commGuideOnTrello', {trelloName: 'caffeinatedvee'}) }}, {{ $t('commGuideOnGitHub', {gitHubName: 'veeeeeee'}) }})</li> <li>
<li>{{ $t('commGuideAKA', {habitName: 'Lemoness', realName: 'Leslie'}) }} ({{ $t('commGuideOnTrello', {trelloName: 'lemonesstree'}) }})</li> {{ $t('commGuideAKA', {
habitName: 'redphoenix', realName: 'Vicky'}) }} ({{ $t('commGuideOnTrello', {
trelloName: 'caffeinatedvee'}) }}, {{ $t('commGuideOnGitHub', {
gitHubName: 'veeeeeee'}) }})
</li>
<li>
{{ $t('commGuideAKA', {
habitName: 'Lemoness', realName: 'Leslie'}) }} ({{ $t('commGuideOnTrello', {
trelloName: 'lemonesstree'}) }})
</li>
<li>{{ $t('commGuideAKA', {habitName: 'SabreCat', realName: 'Sabe'}) }}</li> <li>{{ $t('commGuideAKA', {habitName: 'SabreCat', realName: 'Sabe'}) }}</li>
<li>{{ $t('commGuideAKA', {habitName: 'paglias', realName: 'Matteo'}) }}</li> <li>{{ $t('commGuideAKA', {habitName: 'paglias', realName: 'Matteo'}) }}</li>
<li>{{ $t('commGuideAKA', {habitName: 'TheHollidayInn', realName: 'Keith'}) }}</li> <li>{{ $t('commGuideAKA', {habitName: 'TheHollidayInn', realName: 'Keith'}) }}</li>

View File

@@ -18,7 +18,7 @@
target="_blank" target="_blank"
href="https://github.com/HabitRPG/habitica/issues?q=is%3Aopen" href="https://github.com/HabitRPG/habitica/issues?q=is%3Aopen"
>GitHub</a> >GitHub</a>
<span v-if="this.user"> <span v-if="user">
<br> <br>
{{ $t('reportCommunityIssues') }} {{ $t('reportCommunityIssues') }}
&colon;&nbsp; &colon;&nbsp;

View File

@@ -249,7 +249,6 @@
import * as Analytics from '@/libs/analytics'; import * as Analytics from '@/libs/analytics';
import { setup as setupPayments } from '@/libs/payments'; import { setup as setupPayments } from '@/libs/payments';
import amazonPaymentsModal from '@/components/payments/amazonModal'; import amazonPaymentsModal from '@/components/payments/amazonModal';
import StaticHeader from './header.vue';
import AuthForm from '../auth/authForm.vue'; import AuthForm from '../auth/authForm.vue';
import CreateGroupModalPages from '../group-plans/createGroupModalPages.vue'; import CreateGroupModalPages from '../group-plans/createGroupModalPages.vue';
@@ -257,7 +256,6 @@ import party from '../../assets/images/group-plans-static/party.svg';
export default { export default {
components: { components: {
StaticHeader,
AuthForm, AuthForm,
CreateGroupModalPages, CreateGroupModalPages,
amazonPaymentsModal, amazonPaymentsModal,

View File

@@ -68,10 +68,12 @@
:placeholder="$t('username')" :placeholder="$t('username')"
:class="{'input-valid': usernameValid, 'input-invalid': usernameInvalid}" :class="{'input-valid': usernameValid, 'input-invalid': usernameInvalid}"
> >
<!-- eslint-disable vue/require-v-for-key -->
<div <div
v-for="issue in usernameIssues" v-for="issue in usernameIssues"
class="input-error" class="input-error"
> >
<!-- eslint-enable vue/require-v-for-key -->
{{ issue }} {{ issue }}
</div> </div>
<input <input
@@ -93,7 +95,9 @@
class="form-control" class="form-control"
type="password" type="password"
:placeholder="$t('confirmPassword')" :placeholder="$t('confirmPassword')"
:class="{'input-invalid': passwordConfirmInvalid, 'input-valid': passwordConfirmValid}" :class="{
'input-invalid': passwordConfirmInvalid,
'input-valid': passwordConfirmValid}"
> >
<p <p
v-once v-once

View File

@@ -3,9 +3,11 @@
<div class="row"> <div class="row">
<div class="col-md-6 offset-3"> <div class="col-md-6 offset-3">
<h1>{{ $t('merch') }}</h1> <h1>{{ $t('merch') }}</h1>
<!-- @TODO: Visual experience: Separate each merch items with new line? Or to show items in a table?--> <!-- @TODO: Visual experience: Separate each
merch items with new line? Or to show items in a table?-->
<div <div
v-for="(merchant, index) in merchants" v-for="(merchant) in merchants"
:key="merchant.key"
class="col-lg-6 col-md-6 col-sm-12" class="col-lg-6 col-md-6 col-sm-12"
> >
<div class="merch-block"> <div class="merch-block">

View File

@@ -4,13 +4,19 @@
<div class="col-md-6 offset-3"> <div class="col-md-6 offset-3">
<h1>{{ $t('overview') }}</h1> <h1>{{ $t('overview') }}</h1>
<p>{{ $t('needTips') }}</p> <p>{{ $t('needTips') }}</p>
<div v-for="step in stepsNum"> <div
v-for="step in stepsNum"
:key="step"
>
<h3>{{ $t('step'+step) }}</h3> <h3>{{ $t('step'+step) }}</h3>
<p v-markdown="$t('webStep'+step+'Text', stepVars[step])"></p> <p v-markdown="$t('webStep'+step+'Text', stepVars[step])"></p>
<hr> <hr>
</div> </div>
<p <p
v-markdown="$t('overviewQuestions', {faqUrl: '/static/faq/', helpGuildUrl: '/groups/guild/5481ccf3-5d2d-48a9-a871-70a7380cee5a'})" v-markdown="$t('overviewQuestions', {
faqUrl: '/static/faq/',
helpGuildUrl: '/groups/guild/5481ccf3-5d2d-48a9-a871-70a7380cee5a'
})"
></p> ></p>
</div> </div>
</div> </div>

View File

@@ -8,10 +8,16 @@
href="/static/presskit/presskit.zip" href="/static/presskit/presskit.zip"
>presskit.zip</a> >presskit.zip</a>
</p> </p>
<div v-for="(images, category) in imgs"> <div
v-for="(images, category) in imgs"
:key="category"
>
<h2>{{ $t('pk' + category) }}</h2> <h2>{{ $t('pk' + category) }}</h2>
<div v-if="Array.isArray(images)"> <div v-if="Array.isArray(images)">
<div v-for="img in images"> <div
v-for="img in images"
:key="img"
>
<img <img
class="img-fluid img-rendering-auto press-img" class="img-fluid img-rendering-auto press-img"
:src="`/static/presskit/${category}/${img}`" :src="`/static/presskit/${category}/${img}`"
@@ -19,9 +25,15 @@
</div> </div>
</div> </div>
<div v-else> <div v-else>
<div v-for="(images, secondaryCategory) in images"> <div
v-for="(images, secondaryCategory) in images"
:key="secondaryCategory"
>
<h3>{{ $t('pk' + secondaryCategory) }}</h3> <h3>{{ $t('pk' + secondaryCategory) }}</h3>
<div v-for="img in images"> <div
v-for="img in images"
:key="img"
>
<img <img
class="img-fluid img-rendering-auto press-img" class="img-fluid img-rendering-auto press-img"
:src="`/static/presskit/${category}/${secondaryCategory}/${img}`" :src="`/static/presskit/${category}/${secondaryCategory}/${img}`"
@@ -37,6 +49,7 @@
> >
<div <div
v-for="(QA, index) in faq" v-for="(QA, index) in faq"
:key="index"
class="faq-question" class="faq-question"
> >
<h2 <h2
@@ -70,7 +83,7 @@ const PRESS_ENQUIRY_EMAIL = 'admin@habitica.com';
export default { export default {
data () { data () {
return { return Object.freeze({
PRESS_ENQUIRY_EMAIL, PRESS_ENQUIRY_EMAIL,
imgs: { imgs: {
Promo: [ Promo: [
@@ -157,7 +170,7 @@ export default {
answer: 'pkAnswer8', answer: 'pkAnswer8',
}, },
], ],
}; });
}, },
}; };
</script> </script>

View File

@@ -1,4 +1,5 @@
<template> <template>
<!-- eslint-disable max-len -->
<div class="container-fluid"> <div class="container-fluid">
<h1>Privacy Policy</h1> <h1>Privacy Policy</h1>
<p class="pagemeta"> <p class="pagemeta">
@@ -317,4 +318,5 @@
<a href="mailto:admin@habitica.com">admin@habitica.com</a> <a href="mailto:admin@habitica.com">admin@habitica.com</a>
</address> </address>
</div> </div>
<!-- eslint-enable max-len -->
</template> </template>

View File

@@ -2,7 +2,10 @@
<div> <div>
<static-header <static-header
v-if="showContentWrap" v-if="showContentWrap"
:class="{'home-header': ['home', 'front'].indexOf($route.name) !== -1, 'white-header': this.$route.name === 'plans'}" :class="{
'home-header': ['home', 'front'].indexOf($route.name) !== -1,
'white-header': this.$route.name === 'plans'
}"
/> />
<div class="static-wrapper"> <div class="static-wrapper">
<router-view /> <router-view />

View File

@@ -1,4 +1,5 @@
<template> <template>
<!-- eslint-disable max-len -->
<div class="container-fluid"> <div class="container-fluid">
<h1>Terms of Use</h1> <h1>Terms of Use</h1>
<p class="pagemeta"> <p class="pagemeta">
@@ -599,4 +600,5 @@
<a href="mailto:admin@habitica.com">admin@habitica.com</a> <a href="mailto:admin@habitica.com">admin@habitica.com</a>
</p> </p>
</div> </div>
<!-- eslint-enable max-len -->
</template> </template>

View File

@@ -47,7 +47,7 @@
</div> </div>
</template> </template>
<style lang="scss", scoped> <style lang="scss" scoped>
@import '~@/assets/scss/colors.scss'; @import '~@/assets/scss/colors.scss';
.claim-bottom-message { .claim-bottom-message {
background-color: $gray-700; background-color: $gray-700;

View File

@@ -6,6 +6,7 @@
:hide-footer="true" :hide-footer="true"
> >
<div class="modal-body"> <div class="modal-body">
<!-- eslint-disable-next-line vue/require-v-for-key -->
<div <div
v-for="(approval, index) in task.approvals" v-for="(approval, index) in task.approvals"
class="row approval" class="row approval"

View File

@@ -10,7 +10,8 @@
class="modal-body" class="modal-body"
> >
<div <div
v-if="brokenChallengeTask.challenge.broken === 'TASK_DELETED' || brokenChallengeTask.challenge.broken === 'CHALLENGE_TASK_NOT_FOUND'" v-if="brokenChallengeTask.challenge.broken === 'TASK_DELETED'
|| brokenChallengeTask.challenge.broken === 'CHALLENGE_TASK_NOT_FOUND'"
> >
<h2>{{ $t('brokenTask') }}</h2> <h2>{{ $t('brokenTask') }}</h2>
<div> <div>
@@ -63,7 +64,8 @@
</div> </div>
</div> </div>
<!-- @TODO: I ported this over, but do we use it anymore?--> <!-- @TODO: I ported this over, but do we use it anymore?-->
<!--div(v-if='brokenChallengeTask.challenge.broken === "UNSUBSCRIBED"')p {{ $t('unsubChallenge') }} <!--div(v-if='brokenChallengeTask.challenge.broken
=== "UNSUBSCRIBED"')p {{ $t('unsubChallenge') }}
p p
a(@click="unlink('keep-all')") {{ $t('keepThem') }} a(@click="unlink('keep-all')") {{ $t('keepThem') }}
| &nbsp;|&nbsp; | &nbsp;|&nbsp;

View File

@@ -24,6 +24,7 @@
<div class="filters d-flex justify-content-end"> <div class="filters d-flex justify-content-end">
<div <div
v-for="filter in typeFilters" v-for="filter in typeFilters"
:key="filter"
class="filter small-text" class="filter small-text"
:class="{active: activeFilter.label === filter}" :class="{active: activeFilter.label === filter}"
@click="activateFilter(type, filter)" @click="activateFilter(type, filter)"
@@ -341,7 +342,7 @@ import {
getTypeLabel, getTypeLabel,
getFilterLabels, getFilterLabels,
getActiveFilter, getActiveFilter,
} from '@/libs/store/helpers/filterTasks.js'; } from '@/libs/store/helpers/filterTasks';
import svgPin from '@/assets/svg/pin.svg'; import svgPin from '@/assets/svg/pin.svg';
import habitIcon from '@/assets/svg/habit.svg'; import habitIcon from '@/assets/svg/habit.svg';
@@ -484,7 +485,11 @@ export default {
return this.taskList.length; return this.taskList.length;
} if (this.activeFilter.label === 'all') { } if (this.activeFilter.label === 'all') {
return this.taskList return this.taskList
.reduce((count, t) => (!t.completed && shouldDo(new Date(), t, this.getUserPreferences) ? count + 1 : count), 0); .reduce(
(count, t) => (!t.completed
&& shouldDo(new Date(), t, this.getUserPreferences) ? count + 1 : count),
0,
);
} }
} }
@@ -700,14 +705,15 @@ export default {
filteredTaskList = taskList.filter( filteredTaskList = taskList.filter(
task => task =>
// eslint rule disabled for block to allow nested binary expression // eslint rule disabled for block to allow nested binary expression
/* eslint-disable no-extra-parens */ /* eslint-disable no-extra-parens, implicit-arrow-linebreak, max-len */
( (
task.text.toLowerCase().indexOf(searchTextLowerCase) > -1 task.text.toLowerCase().indexOf(searchTextLowerCase) > -1
|| (task.notes && task.notes.toLowerCase().indexOf(searchTextLowerCase) > -1) || (task.notes && task.notes.toLowerCase().indexOf(searchTextLowerCase) > -1)
|| (task.checklist && task.checklist.length > 0 || (task.checklist && task.checklist.length > 0
&& task.checklist.some(checkItem => checkItem.text.toLowerCase().indexOf(searchTextLowerCase) > -1)) && task.checklist
.some(checkItem => checkItem.text.toLowerCase().indexOf(searchTextLowerCase) > -1))
), ),
/* eslint-enable no-extra-parens */ /* eslint-enable no-extra-parens, implicit-arrow-linebreak, max-len */
); );
} }
return filteredTaskList; return filteredTaskList;

View File

@@ -35,13 +35,16 @@
<div slot="drawer-slider"> <div slot="drawer-slider">
<div class="container spell-container"> <div class="container spell-container">
<div class="row"> <div class="row">
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="(skill, key) in spells[user.stats.class]" v-for="(skill, key) in spells[user.stats.class]"
v-if="user.stats.lvl >= skill.lvl" v-if="user.stats.lvl >= skill.lvl"
:key="key"
v-b-popover.hover.auto="skill.notes()" v-b-popover.hover.auto="skill.notes()"
class="col-12 col-md-3" class="col-12 col-md-3"
@click="castStart(skill)" @click="castStart(skill)"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div class="spell col-12 row"> <div class="spell col-12 row">
<div class="col-8 details"> <div class="col-8 details">
<a :class="{'disabled': spellDisabled(key)}"></a> <a :class="{'disabled': spellDisabled(key)}"></a>

View File

@@ -1,18 +1,21 @@
<template> <template>
<div class="tags-popup"> <div class="tags-popup">
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="tagsType in tagsByType" v-for="tagsType in tagsByType"
v-if="tagsType.tags.length > 0 || tagsType.key === 'tags'" v-if="tagsType.tags.length > 0 || tagsType.key === 'tags'"
:key="tagsType.key" :key="tagsType.key"
class="tags-category d-flex" class="tags-category d-flex"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div class="tags-header"> <div class="tags-header">
<strong v-once>{{ $t(tagsType.key) }}</strong> <strong v-once>{{ $t(tagsType.key) }}</strong>
</div> </div>
<div class="tags-list container"> <div class="tags-list container">
<div class="row"> <div class="row">
<div <div
v-for="(tag, tagIndex) in tagsType.tags" v-for="(tag) in tagsType.tags"
:key="tag.id"
class="col-4" class="col-4"
> >
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">

View File

@@ -18,7 +18,10 @@
<div <div
v-if="task.type === 'habit'" v-if="task.type === 'habit'"
class="left-control d-flex align-items-center justify-content-center" class="left-control d-flex align-items-center justify-content-center"
:class="[{'control-bottom-box': this.task.group.id, 'control-top-box': approvalsClass}, controlClass.up.bg]" :class="[{
'control-bottom-box': task.group.id,
'control-top-box': approvalsClass
}, controlClass.up.bg]"
> >
<div <div
class="task-control habit-control" class="task-control habit-control"
@@ -26,7 +29,7 @@
@click="(isUser && task.up) ? score('up') : null" @click="(isUser && task.up) ? score('up') : null"
> >
<div <div
v-if="this.task.group.id && !isUser" v-if="task.group.id && !isUser"
class="svg-icon lock" class="svg-icon lock"
:class="controlClass.up.icon" :class="controlClass.up.icon"
v-html="icons.lock" v-html="icons.lock"
@@ -42,7 +45,9 @@
<div <div
v-if="task.type === 'daily' || task.type === 'todo'" v-if="task.type === 'daily' || task.type === 'todo'"
class="left-control d-flex justify-content-center" class="left-control d-flex justify-content-center"
:class="[{'control-bottom-box': this.task.group.id, 'control-top-box': approvalsClass}, controlClass.bg]" :class="[{
'control-bottom-box': task.group.id,
'control-top-box': approvalsClass}, controlClass.bg]"
> >
<div <div
class="task-control daily-todo-control" class="task-control daily-todo-control"
@@ -50,7 +55,7 @@
@click="isUser ? score(task.completed ? 'down' : 'up') : null" @click="isUser ? score(task.completed ? 'down' : 'up') : null"
> >
<div <div
v-if="this.task.group.id && !isUser && !task.completed" v-if="task.group.id && !isUser && !task.completed"
class="svg-icon lock" class="svg-icon lock"
:class="controlClass.icon" :class="controlClass.icon"
v-html="icons.lock" v-html="icons.lock"
@@ -161,7 +166,8 @@
<div class="d-inline-flex"> <div class="d-inline-flex">
<div <div
v-if="isUser" v-if="isUser"
v-b-tooltip.hover.bottom="$t(`${task.collapseChecklist ? 'expand': 'collapse'}Checklist`)" v-b-tooltip.hover.bottom="$t(`${task.collapseChecklist
? 'expand': 'collapse'}Checklist`)"
class="collapse-checklist d-flex align-items-center expand-toggle" class="collapse-checklist d-flex align-items-center expand-toggle"
:class="{open: !task.collapseChecklist}" :class="{open: !task.collapseChecklist}"
@click="collapseChecklist(task)" @click="collapseChecklist(task)"
@@ -173,12 +179,15 @@
<span>{{ checklistProgress }}</span> <span>{{ checklistProgress }}</span>
</div> </div>
</div> </div>
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="item in task.checklist" v-for="item in task.checklist"
v-if="!task.collapseChecklist" v-if="!task.collapseChecklist"
:key="item.id"
class="custom-control custom-checkbox checklist-item" class="custom-control custom-checkbox checklist-item"
:class="{'checklist-item-done': item.completed}" :class="{'checklist-item-done': item.completed}"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<input <input
:id="`checklist-${item.id}-${random}`" :id="`checklist-${item.id}-${random}`"
class="custom-control-input" class="custom-control-input"
@@ -277,6 +286,7 @@
</div> </div>
<div <div
v-for="tag in getTagsFor(task)" v-for="tag in getTagsFor(task)"
:key="tag"
v-markdown="tag" v-markdown="tag"
class="tag-label" class="tag-label"
></div> ></div>
@@ -290,7 +300,9 @@
<div <div
v-if="task.type === 'habit'" v-if="task.type === 'habit'"
class="right-control d-flex align-items-center justify-content-center" class="right-control d-flex align-items-center justify-content-center"
:class="[{'control-bottom-box': this.task.group.id, 'control-top-box': approvalsClass}, controlClass.down.bg]" :class="[{
'control-bottom-box': task.group.id,
'control-top-box': approvalsClass}, controlClass.down.bg]"
> >
<div <div
class="task-control habit-control" class="task-control habit-control"
@@ -298,7 +310,7 @@
@click="(isUser && task.down) ? score('down') : null" @click="(isUser && task.down) ? score('down') : null"
> >
<div <div
v-if="this.task.group.id && !isUser" v-if="task.group.id && !isUser"
class="svg-icon lock" class="svg-icon lock"
:class="controlClass.down.icon" :class="controlClass.down.icon"
v-html="icons.lock" v-html="icons.lock"
@@ -335,6 +347,7 @@
</div> </div>
</template> </template>
<!-- eslint-disable max-len -->
<style lang="scss" scoped> <style lang="scss" scoped>
@import '~@/assets/scss/colors.scss'; @import '~@/assets/scss/colors.scss';
@@ -769,7 +782,7 @@
} }
} }
</style> </style>
<!-- eslint-enable max-len -->
<script> <script>
import moment from 'moment'; import moment from 'moment';
@@ -992,7 +1005,7 @@ export default {
return; return;
} }
switch (this.task.type) { switch (this.task.type) { // eslint-disable-line default-case
case 'habit': case 'habit':
this.$root.$emit('playSound', direction === 'up' ? 'Plus_Habit' : 'Minus_Habit'); this.$root.$emit('playSound', direction === 'up' ? 'Plus_Habit' : 'Minus_Habit');
break; break;
@@ -1010,7 +1023,8 @@ export default {
Analytics.updateUser(); Analytics.updateUser();
const response = await axios.post(`/api/v4/tasks/${task._id}/score/${direction}`); const response = await axios.post(`/api/v4/tasks/${task._id}/score/${direction}`);
const tmp = response.data.data._tmp || {}; // used to notify drops, critical hits and other bonuses // used to notify drops, critical hits and other bonuses
const tmp = response.data.data._tmp || {};
const { crit } = tmp; const { crit } = tmp;
const { drop } = tmp; const { drop } = tmp;
const { quest } = tmp; const { quest } = tmp;
@@ -1025,7 +1039,7 @@ export default {
if (quest.progressDelta && userQuest.boss) { if (quest.progressDelta && userQuest.boss) {
this.quest('questDamage', quest.progressDelta.toFixed(1)); this.quest('questDamage', quest.progressDelta.toFixed(1));
} else if (quest.collection && userQuest.collect) { } else if (quest.collection && userQuest.collect) {
user.party.quest.progress.collectedItems++; user.party.quest.progress.collectedItems += 1;
this.quest('questCollection', quest.collection); this.quest('questCollection', quest.collection);
} }
} }
@@ -1052,7 +1066,7 @@ export default {
if (!user.items[type][drop.key]) { if (!user.items[type][drop.key]) {
Vue.set(user, `items.${type}.${drop.key}`, 0); Vue.set(user, `items.${type}.${drop.key}`, 0);
} }
user.items[type][drop.key]++; user.items[type][drop.key] += 1;
} }
if (drop.type === 'HatchingPotion') { if (drop.type === 'HatchingPotion') {

View File

@@ -113,6 +113,7 @@
> >
<div <div
v-for="(item, $index) in checklist" v-for="(item, $index) in checklist"
:key="item.id"
class="inline-edit-input-group checklist-group input-group" class="inline-edit-input-group checklist-group input-group"
> >
<span class="grippy"></span> <span class="grippy"></span>
@@ -455,6 +456,7 @@
> >
<div <div
v-for="tagName in truncatedSelectedTags" v-for="tagName in truncatedSelectedTags"
:key="tagName"
v-markdown="tagName" v-markdown="tagName"
class="category-label" class="category-label"
:title="tagName" :title="tagName"
@@ -512,7 +514,8 @@
:text="$t(sharedCompletion)" :text="$t(sharedCompletion)"
> >
<b-dropdown-item <b-dropdown-item
v-for="completionOption in ['recurringCompletion', 'singleCompletion', 'allAssignedCompletion']" v-for="completionOption in [
'recurringCompletion', 'singleCompletion', 'allAssignedCompletion']"
:key="completionOption" :key="completionOption"
:class="{active: sharedCompletion === completionOption}" :class="{active: sharedCompletion === completionOption}"
@click="sharedCompletion = completionOption" @click="sharedCompletion = completionOption"
@@ -541,6 +544,7 @@
> >
<span <span
v-for="memberId in assignedMembers" v-for="memberId in assignedMembers"
:key="memberId"
class="mr-1" class="mr-1"
>{{ memberNamesById[memberId] }}</span> >{{ memberNamesById[memberId] }}</span>
</span> </span>
@@ -640,7 +644,8 @@
</div> </div>
</div> </div>
<div <div
v-if="task.type === 'habit' && isUserTask && purpose === 'edit' && (task.up || task.down)" v-if="task.type === 'habit'
&& isUserTask && purpose === 'edit' && (task.up || task.down)"
class="option" class="option"
> >
<div class="form-group"> <div class="form-group">
@@ -692,11 +697,17 @@
<!--.option(v-if="isUserTask && task.type !== 'reward'").form-group <!--.option(v-if="isUserTask && task.type !== 'reward'").form-group
label(v-once) label(v-once)
span.float-left {{ $t('attributeAllocation') }} span.float-left {{ $t('attributeAllocation') }}
.svg-icon.info-icon(v-html="icons.information", v-b-tooltip.hover.righttop.html="$t('attributeAllocationHelp')") .svg-icon.info-icon(v-html="ic
ons.information", v-b-tooltip.hover.righttop.html="$t('attributeAllocationHelp')")
.attributes .attributes
.custom-control.custom-radio.custom-control-inline(v-for="attr in ATTRIBUTES", :key="attr") .custom-control.custom-radio.custom-
input.custom-control-input(:id="`attribute-${attr}`", type="radio", :value="attr", v-model="task.attribute", :disabled="user.preferences.allocationMode !== 'taskbased'") control-inline(v-for="attr in ATTRIBUTES", :key="attr")
label.custom-control-label.attr-description(:for="`attribute-${attr}`", v-once, v-b-popover.hover="$t(`${attr}Text`)") {{ $t(attributesStrings[attr]) }}--> input.custom-control-input(:id="`attribute-${a
ttr}`", type="radio", :value="attr", v-model="task.attribute", :disabled="us
er.preferences.allocationMode !== 'taskbased'")
label.custom-control-label.attr-
description(:for="`attribute-${attr}`", v-once, v-b-pop
over.hover="$t(`${attr}Text`)") {{ $t(attributesStrings[attr]) }}-->
</div> </div>
</b-collapse> </b-collapse>
</div> </div>

View File

@@ -35,12 +35,14 @@
class="filter-panel" class="filter-panel"
@mouseleave="checkMouseOver" @mouseleave="checkMouseOver"
> >
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
<div <div
v-for="tagsType in tagsByType" v-for="tagsType in tagsByType"
v-if="tagsType.tags.length > 0 || tagsType.key === 'tags'" v-if="tagsType.tags.length > 0 || tagsType.key === 'tags'"
:key="tagsType.key" :key="tagsType.key"
class="tags-category d-flex" class="tags-category d-flex"
> >
<!-- eslint-enable vue/no-use-v-if-with-v-for -->
<div class="tags-header"> <div class="tags-header">
<strong v-once>{{ $t(tagsType.key) }}</strong> <strong v-once>{{ $t(tagsType.key) }}</strong>
<a <a
@@ -62,6 +64,7 @@
> >
<div <div
v-for="(tag, tagIndex) in tagsSnap[tagsType.key]" v-for="(tag, tagIndex) in tagsSnap[tagsType.key]"
:key="tag.id"
class="col-6" class="col-6"
> >
<div class="inline-edit-input-group tag-edit-item input-group"> <div class="inline-edit-input-group tag-edit-item input-group">
@@ -99,6 +102,7 @@
<template v-if="editingTags && tagsType.key === 'challenges'"> <template v-if="editingTags && tagsType.key === 'challenges'">
<div <div
v-for="(tag, tagIndex) in tagsSnap[tagsType.key]" v-for="(tag, tagIndex) in tagsSnap[tagsType.key]"
:key="tag.id"
class="col-6" class="col-6"
> >
<div class="inline-edit-input-group tag-edit-item input-group"> <div class="inline-edit-input-group tag-edit-item input-group">
@@ -121,7 +125,8 @@
</template> </template>
<template v-if="!editingTags || tagsType.key === 'groups'"> <template v-if="!editingTags || tagsType.key === 'groups'">
<div <div
v-for="(tag, tagIndex) in tagsType.tags" v-for="(tag) in tagsType.tags"
:key="tag.id"
class="col-6" class="col-6"
> >
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
@@ -414,13 +419,10 @@ import { mapState, mapActions } from '@/libs/store';
import taskDefaults from '@/../../common/script/libs/taskDefaults'; import taskDefaults from '@/../../common/script/libs/taskDefaults';
import brokenTaskModal from './brokenTaskModal'; import brokenTaskModal from './brokenTaskModal';
import Item from '@/components/inventory/item.vue';
export default { export default {
components: { components: {
TaskColumn, TaskColumn,
TaskModal, TaskModal,
Item,
spells, spells,
brokenTaskModal, brokenTaskModal,
draggable, draggable,

View File

@@ -3,6 +3,7 @@
<ul class="drawer-tab-container"> <ul class="drawer-tab-container">
<li <li
v-for="(tab, index) in tabs" v-for="(tab, index) in tabs"
:key="tab.key"
class="drawer-tab" class="drawer-tab"
> >
<a <a

View File

@@ -31,9 +31,12 @@
@resized="currentWidth = $event.width - 120" @resized="currentWidth = $event.width - 120"
> >
<div class="items items-one-line"> <div class="items items-one-line">
<template v-for="item in showItems"> <template
v-for="item in showItems"
>
<div <div
v-if="shouldAddVerticalLine(item)" v-if="shouldAddVerticalLine(item)"
:key="item.key"
class="vertical-divider" class="vertical-divider"
:style="dividerMargins" :style="dividerMargins"
></div> ></div>

View File

@@ -2,13 +2,15 @@
<div class="standard-page container"> <div class="standard-page container">
<div <div
v-for="(category, key) in achievements" v-for="(category, key) in achievements"
:key="key"
class="row" class="row"
> >
<h2 class="col-12"> <h2 class="col-12">
{{ $t(key+'Achievs') }} {{ $t(key+'Achievs') }}
</h2> </h2>
<div <div
v-for="achievment in category.achievements" v-for="(achievment, achievmentKey) in category.achievements"
:key="achievmentKey"
class="col-3 text-center" class="col-3 text-center"
> >
<div <div
@@ -46,13 +48,19 @@
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<h2>Challeges Won</h2> <h2>Challeges Won</h2>
<div v-for="chal in user.achievements.challenges"> <div
v-for="chal in user.achievements.challenges"
:key="chal"
>
<span>{{ chal }}</span> <span>{{ chal }}</span>
</div> </div>
</div> </div>
<div class="col-6"> <div class="col-6">
<h2>Quests Completed</h2> <h2>Quests Completed</h2>
<div v-for="(value, key) in user.achievements.quests"> <div
v-for="(value, key) in user.achievements.quests"
:key="key"
>
<span>{{ content.quests[k].text() }}</span> <span>{{ content.quests[k].text() }}</span>
<span>{{ value }}</span> <span>{{ value }}</span>
</div> </div>

View File

@@ -34,7 +34,7 @@
<toggle-switch <toggle-switch
class="float-right" class="float-right"
:label="optTextSet.switchDescription" :label="optTextSet.switchDescription"
:checked="!this.user.inbox.optOut" :checked="!user.inbox.optOut"
:hover-text="optTextSet.popoverText" :hover-text="optTextSet.popoverText"
@change="toggleOpt()" @change="toggleOpt()"
/> />
@@ -80,6 +80,7 @@
> >
<div <div
v-for="conversation in filtersConversations" v-for="conversation in filtersConversations"
:key="conversation.key"
class="conversation" class="conversation"
:class="{active: selectedConversation.key === conversation.key}" :class="{active: selectedConversation.key === conversation.key}"
@click="selectConversation(conversation.key)" @click="selectConversation(conversation.key)"
@@ -103,7 +104,8 @@
<div <div
class="messagePreview" class="messagePreview"
> >
{{ conversation.lastMessageText ? removeTags(parseMarkdown(conversation.lastMessageText)) : '' }} {{ conversation.lastMessageText
? removeTags(parseMarkdown(conversation.lastMessageText)) : '' }}
</div> </div>
</div> </div>
</div> </div>
@@ -421,12 +423,14 @@ export default {
} }
// Create conversation objects // Create conversation objects
const convos = []; const convos = [];
for (const key in inboxGroup) { for (const key of Object.keys(inboxGroup)) {
const recentMessage = inboxGroup[key][0]; const recentMessage = inboxGroup[key][0];
const convoModel = { const convoModel = {
key: recentMessage.uuid, key: recentMessage.uuid,
name: recentMessage.user, // Handles case where from user sent the only message or the to user sent the only message // Handles case where from user sent
// the only message or the to user sent the only message
name: recentMessage.user,
username: !recentMessage.text ? recentMessage.username : recentMessage.toUserName, username: !recentMessage.text ? recentMessage.username : recentMessage.toUserName,
date: recentMessage.timestamp, date: recentMessage.timestamp,
lastMessageText: recentMessage.text, lastMessageText: recentMessage.text,
@@ -439,14 +443,15 @@ export default {
return convos; return convos;
}, },
// Separate from selectedConversation which is not computed so messages don't update automatically // Separate from selectedConversation which
// is not computed so messages don't update automatically
selectedConversationMessages () { selectedConversationMessages () {
// Vue-subscribe to changes // Vue-subscribe to changes
const subScribeToUpdate = this.messagesLoading || this.updateConversionsCounter > -1; const subScribeToUpdate = this.messagesLoading || this.updateConversionsCounter > -1;
const selectedConversationKey = this.selectedConversation.key; const selectedConversationKey = this.selectedConversation.key;
const selectedConversation = this.messagesByConversation[selectedConversationKey]; const selectedConversation = this.messagesByConversation[selectedConversationKey];
this.messages = selectedConversation || []; // eslint-disable-line vue/no-side-effects-in-computed-properties this.messages = selectedConversation || []; // eslint-disable-line vue/no-side-effects-in-computed-properties, max-len
const ordered = orderBy(this.messages, [m => m.timestamp], ['asc']); const ordered = orderBy(this.messages, [m => m.timestamp], ['asc']);
@@ -462,7 +467,10 @@ export default {
const filtered = subScribeToUpdate && !this.search const filtered = subScribeToUpdate && !this.search
? this.conversations ? this.conversations
: filter(this.conversations, conversation => conversation.name.toLowerCase().indexOf(this.search.toLowerCase()) !== -1); : filter(
this.conversations,
conversation => conversation.name.toLowerCase().indexOf(this.search.toLowerCase()) !== -1,
);
const ordered = orderBy(filtered, [o => moment(o.date).toDate()], ['desc']); const ordered = orderBy(filtered, [o => moment(o.date).toDate()], ['desc']);
@@ -677,9 +685,9 @@ export default {
const res = await axios.get(requestUrl); const res = await axios.get(requestUrl);
const loadedMessages = res.data.data; const loadedMessages = res.data.data;
this.messagesByConversation[this.selectedConversation.key] = this.messagesByConversation[this.selectedConversation.key] || []; this.messagesByConversation[this.selectedConversation.key] = this.messagesByConversation[this.selectedConversation.key] || []; // eslint-disable-line max-len
const loadedMessagesToAdd = loadedMessages const loadedMessagesToAdd = loadedMessages
.filter(m => this.messagesByConversation[this.selectedConversation.key].findIndex(mI => mI.id === m.id) === -1); .filter(m => this.messagesByConversation[this.selectedConversation.key].findIndex(mI => mI.id === m.id) === -1); // eslint-disable-line max-len
this.messagesByConversation[this.selectedConversation.key].push(...loadedMessagesToAdd); this.messagesByConversation[this.selectedConversation.key].push(...loadedMessagesToAdd);
// only show the load more Button if the max count was returned // only show the load more Button if the max count was returned

View File

@@ -26,7 +26,7 @@
></div> ></div>
</button> </button>
<button <button
v-if="user._id !== this.userLoggedIn._id && userLoggedIn.inbox.blocks.indexOf(user._id) === -1" v-if="user._id !== userLoggedIn._id && userLoggedIn.inbox.blocks.indexOf(user._id) === -1"
v-b-tooltip.hover.right="$t('blockWarning')" v-b-tooltip.hover.right="$t('blockWarning')"
class="btn btn-secondary remove-icon" class="btn btn-secondary remove-icon"
@click="blockUser()" @click="blockUser()"
@@ -37,7 +37,7 @@
></div> ></div>
</button> </button>
<button <button
v-if="user._id !== this.userLoggedIn._id && userLoggedIn.inbox.blocks.indexOf(user._id) !== -1" v-if="user._id !== userLoggedIn._id && userLoggedIn.inbox.blocks.indexOf(user._id) !== -1"
v-b-tooltip.hover.right="$t('unblock')" v-b-tooltip.hover.right="$t('unblock')"
class="btn btn-secondary positive-icon" class="btn btn-secondary positive-icon"
@click="unblockUser()" @click="unblockUser()"
@@ -48,7 +48,7 @@
></div> ></div>
</button> </button>
<button <button
v-if="this.userLoggedIn.contributor.admin" v-if="userLoggedIn.contributor.admin"
v-b-tooltip.hover.right="'Admin - Toggle Tools'" v-b-tooltip.hover.right="'Admin - Toggle Tools'"
class="btn btn-secondary positive-icon" class="btn btn-secondary positive-icon"
@click="toggleAdminTools()" @click="toggleAdminTools()"
@@ -60,7 +60,7 @@
</button> </button>
</div> </div>
<div <div
v-if="this.userLoggedIn.contributor.admin && adminToolsLoaded" v-if="userLoggedIn.contributor.admin && adminToolsLoaded"
class="row admin-profile-actions" class="row admin-profile-actions"
> >
<div class="col-12 text-right"> <div class="col-12 text-right">
@@ -299,22 +299,24 @@
> >
<div <div
v-for="(category, key) in achievements" v-for="(category, key) in achievements"
:key="key"
class="row" class="row"
> >
<h2 class="col-12 text-center"> <h2 class="col-12 text-center">
{{ $t(key+'Achievs') }} {{ $t(key+'Achievs') }}
</h2> </h2>
<div <div
v-for="(achievement, key) in category.achievements" v-for="(achievement, achievKey) in category.achievements"
:key="achievKey"
class="col-12 col-md-3 text-center" class="col-12 col-md-3 text-center"
> >
<div <div
:id="key + '-achievement'" :id="achievKey + '-achievement'"
class="box achievement-container" class="box achievement-container"
:class="{'achievement-unearned': !achievement.earned}" :class="{'achievement-unearned': !achievement.earned}"
> >
<b-popover <b-popover
:target="'#' + key + '-achievement'" :target="'#' + achievKey + '-achievement'"
triggers="hover" triggers="hover"
placement="top" placement="top"
> >
@@ -355,7 +357,10 @@
<h2 class="text-center"> <h2 class="text-center">
{{ $t('challengesWon') }} {{ $t('challengesWon') }}
</h2> </h2>
<div v-for="chal in user.achievements.challenges"> <div
v-for="chal in user.achievements.challenges"
:key="chal"
>
<span v-markdown="chal"></span> <span v-markdown="chal"></span>
<hr> <hr>
</div> </div>
@@ -368,7 +373,10 @@
<h2 class="text-center"> <h2 class="text-center">
{{ $t('questsCompleted') }} {{ $t('questsCompleted') }}
</h2> </h2>
<div v-for="(value, key) in user.achievements.quests"> <div
v-for="(value, key) in user.achievements.quests"
:key="key"
>
<span>{{ content.quests[key].text() }} ({{ value }})</span> <span>{{ content.quests[key].text() }} ({{ value }})</span>
</div> </div>
</div> </div>
@@ -781,7 +789,7 @@ export default {
}, },
selectPage (page) { selectPage (page) {
this.selectedPage = page; this.selectedPage = page;
history.replaceState(null, null, ''); window.history.replaceState(null, null, '');
}, },
sendMessage () { sendMessage () {
this.$root.$emit('habitica::new-inbox-message', { this.$root.$emit('habitica::new-inbox-message', {
@@ -810,7 +818,8 @@ export default {
if (!currentLoginDay) return 0; if (!currentLoginDay) return 0;
const previousRewardDay = currentLoginDay.prevRewardKey; const previousRewardDay = currentLoginDay.prevRewardKey;
const { nextRewardAt } = currentLoginDay; const { nextRewardAt } = currentLoginDay;
return ((this.user.loginIncentives - previousRewardDay) / (nextRewardAt - previousRewardDay)) * 100; return ((this.user.loginIncentives - previousRewardDay)
/ (nextRewardAt - previousRewardDay)) * 100;
}, },
save () { save () {
const values = {}; const values = {};

View File

@@ -50,7 +50,7 @@ export default {
}, },
methods: { methods: {
onShown () { onShown () {
history.pushState('', null, this.path); window.history.pushState('', null, this.path);
}, },
onHidden () { onHidden () {
if (this.$route.path !== window.location.pathname) { if (this.$route.path !== window.location.pathname) {

View File

@@ -11,6 +11,7 @@
<div class="well"> <div class="well">
<div <div
v-for="(label, key) in equipTypes" v-for="(label, key) in equipTypes"
:key="key"
class="col-12 col-md-4 item-wrapper" class="col-12 col-md-4 item-wrapper"
> >
<div <div
@@ -22,7 +23,8 @@
<div :class="`shop_${equippedItems[key]}`"></div> <div :class="`shop_${equippedItems[key]}`"></div>
</div> </div>
<b-popover <b-popover
v-if="label !== 'skip' && equippedItems[key] && equippedItems[key].indexOf('base_0') === -1" v-if="label !== 'skip'
&& equippedItems[key] && equippedItems[key].indexOf('base_0') === -1"
:target="key" :target="key"
triggers="hover" triggers="hover"
:placement="'bottom'" :placement="'bottom'"
@@ -51,6 +53,7 @@
<!-- Use similar for loop for costume items, except show background if label is 'skip'.--> <!-- Use similar for loop for costume items, except show background if label is 'skip'.-->
<div <div
v-for="(label, key) in equipTypes" v-for="(label, key) in equipTypes"
:key="key"
class="col-12 col-md-4 item-wrapper" class="col-12 col-md-4 item-wrapper"
> >
<!-- Append a "C" to the key name since HTML IDs have to be unique.--> <!-- Append a "C" to the key name since HTML IDs have to be unique.-->
@@ -72,7 +75,8 @@
<div :class="'icon_background_' + user.preferences.background"></div> <div :class="'icon_background_' + user.preferences.background"></div>
</div> </div>
<b-popover <b-popover
v-if="label !== 'skip' && costumeItems[key] && costumeItems[key].indexOf('base_0') === -1" v-if="label !== 'skip'
&& costumeItems[key] && costumeItems[key].indexOf('base_0') === -1"
:target="key + 'C'" :target="key + 'C'"
triggers="hover" triggers="hover"
:placement="'bottom'" :placement="'bottom'"
@@ -177,6 +181,7 @@
</h2> </h2>
<div <div
v-for="(statInfo, stat) in stats" v-for="(statInfo, stat) in stats"
:key="stat"
class="col-12 col-md-6" class="col-12 col-md-6"
> >
<div class="row col-12 stats-column"> <div class="row col-12 stats-column">
@@ -257,6 +262,7 @@
<div class="row"> <div class="row">
<div <div
v-for="(statInfo, stat) in allocateStatsList" v-for="(statInfo, stat) in allocateStatsList"
:key="stat"
class="col-12 col-md-3" class="col-12 col-md-3"
> >
<div class="box white row col-12"> <div class="box white row col-12">
@@ -300,7 +306,7 @@
:disabled="loading" :disabled="loading"
@click="saveAttributes()" @click="saveAttributes()"
> >
{{ this.loading ? $t('loading') : $t('save') }} {{ loading ? $t('loading') : $t('save') }}
</button> </button>
</div> </div>
</div> </div>
@@ -424,21 +430,23 @@ export default {
}, },
formatAnimal (animalName, type) { formatAnimal (animalName, type) {
if (type === 'pet') { if (type === 'pet') {
if (Content.petInfo.hasOwnProperty(animalName)) { if (Content.petInfo[animalName]) {
return Content.petInfo[animalName].text(); return Content.petInfo[animalName].text();
} }
return this.$t('noActivePet'); return this.$t('noActivePet');
} if (type === 'mount') { } if (type === 'mount') {
if (Content.mountInfo.hasOwnProperty(animalName)) { if (Content.mountInfo[animalName]) {
return Content.mountInfo[animalName].text(); return Content.mountInfo[animalName].text();
} }
return this.$t('noActiveMount'); return this.$t('noActiveMount');
} }
return null;
}, },
formatBackground (background) { formatBackground (background) {
const bg = Content.appearances.background; const bg = Content.appearances.background;
if (bg.hasOwnProperty(background)) { if (bg[background]) {
return `${bg[background].text()} (${this.$t(bg[background].set.text)})`; return `${bg[background].text()} (${this.$t(bg[background].set.text)})`;
} }

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