mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
New client random catchup (#8891)
* Added initial challenge pages * Added challenge item and find guilds page * Added challenge detail * Added challenge modals * Ported over challenge service code * Ported over challenge ctrl code * Added styles and column * Minor modal updates * Removed duplicate keys * Fixed casing * Added initial chat component * Added copy as todo modal * Added sync * Added chat to groups * Fixed lint * Added notification service * Added tag services * Added notifications * Added hall * Added analytics * Added http interceptor * Added initial autocomplete * Added initial footer component * Began coding and designing footer * Added inital hall * Ported over inital group plan ctrl code * Added initial invite modal * Added initial member detail modal * Added initial notification menu * Ported over inital notification code * Fixed import line * Fixed autocomplete import casing
This commit is contained in:
223
website/client/components/appFooter.vue
Normal file
223
website/client/components/appFooter.vue
Normal file
@@ -0,0 +1,223 @@
|
||||
<template lang="pug">
|
||||
.row
|
||||
footer.container-fluid
|
||||
.row
|
||||
.col-2
|
||||
h3 iOS App
|
||||
h3 Android App
|
||||
.col-2
|
||||
h3 Company
|
||||
ul
|
||||
li How it Works
|
||||
li Blog
|
||||
li Tumblr
|
||||
li FAQ
|
||||
li News
|
||||
li Merchandis
|
||||
li Press Kit
|
||||
li Contact Us
|
||||
.col-2
|
||||
h3 Community
|
||||
ul
|
||||
li Community Guidelines
|
||||
li Submit a Bug
|
||||
li Request a Feature
|
||||
li Add-Ons & Extensions
|
||||
li Forum
|
||||
li Kickstarter
|
||||
li Facebook
|
||||
li Reddit
|
||||
.col-6
|
||||
.row
|
||||
.col-6
|
||||
h3 Developers
|
||||
ul
|
||||
li APIv3
|
||||
li Data Display Tool
|
||||
li Guidance for Blacksmiths
|
||||
li The Forge - Developer Blog
|
||||
.col-6
|
||||
h3 Social
|
||||
.social-circle Twitter
|
||||
.social-circle Instagram
|
||||
.social-circle Facebook
|
||||
.row
|
||||
.col-10
|
||||
| We’re an open source project that depends on our users for support. The money you donate helps us keep the servers running, maintain a small staff, develop new features, and provide incentives for our volunteers.
|
||||
.col-2
|
||||
button.btn.btn-primary Donate
|
||||
.row
|
||||
hr.col-12
|
||||
.row
|
||||
.col-4
|
||||
| © 2017 Habitica. All rights reserved.
|
||||
.col-4.text-center
|
||||
.logo.svg-icon(v-html='icons.gryphon')
|
||||
.col-4.text-right
|
||||
span Privacy Policy
|
||||
span Terms of Use
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
footer {
|
||||
background-color: #e1e0e3;
|
||||
height: 376px;
|
||||
padding-left: 6em;
|
||||
padding-right: 6em;
|
||||
padding-top: 3em;
|
||||
margin: 0;
|
||||
color: #878190;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: #878190;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
.social-circle {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background-color: #c3c0c7;
|
||||
display: inline-block;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.logo.svg-icon {
|
||||
width: 24px;
|
||||
margin: 0 auto;
|
||||
color: #c3c0c7;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import gryphon from 'assets/svg/gryphon.svg';
|
||||
|
||||
// const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
gryphon,
|
||||
}),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// @TODO: add https://github.com/HabitRPG/habitica/blob/develop/website/client-old/js/controllers/footerCtrl.js$scope.setHealthLow = function(){
|
||||
// $scope.setHealthLow = function(){
|
||||
// User.set({
|
||||
// 'stats.hp': 1
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// $scope.addMissedDay = function(numberOfDays){
|
||||
// if (!confirm("Are you sure you want to reset the day by " + numberOfDays + " day(s)?")) return;
|
||||
//
|
||||
// User.setCron(numberOfDays);
|
||||
// };
|
||||
//
|
||||
// $scope.addTenGems = function(){
|
||||
// User.addTenGems();
|
||||
// };
|
||||
//
|
||||
// $scope.addHourglass = function(){
|
||||
// User.addHourglass();
|
||||
// };
|
||||
//
|
||||
// $scope.addGold = function(){
|
||||
// User.set({
|
||||
// 'stats.gp': User.user.stats.gp + 500,
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// $scope.addMana = function(){
|
||||
// User.set({
|
||||
// 'stats.mp': User.user.stats.mp + 500,
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// $scope.addLevelsAndGold = function(){
|
||||
// User.set({
|
||||
// 'stats.exp': User.user.stats.exp + 10000,
|
||||
// 'stats.gp': User.user.stats.gp + 10000,
|
||||
// 'stats.mp': User.user.stats.mp + 10000
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// $scope.addOneLevel = function(){
|
||||
// User.set({
|
||||
// 'stats.exp': User.user.stats.exp + (Math.round(((Math.pow(User.user.stats.lvl, 2) * 0.25) + (10 * User.user.stats.lvl) + 139.75) / 10) * 10)
|
||||
// });
|
||||
// };
|
||||
//
|
||||
// $scope.addQuestProgress = function(){
|
||||
// $http({
|
||||
// method: "POST",
|
||||
// url: 'api/v3/debug/quest-progress'
|
||||
// })
|
||||
// .then(function (response) {
|
||||
// Notification.text('Quest progress increased');
|
||||
// User.sync();
|
||||
// })
|
||||
// };
|
||||
//
|
||||
// $scope.makeAdmin = function () {
|
||||
// User.makeAdmin();
|
||||
// };
|
||||
//
|
||||
// $scope.openModifyInventoryModal = function () {
|
||||
// $rootScope.openModal('modify-inventory', {controller: 'FooterCtrl', scope: $scope });
|
||||
// $scope.showInv = { };
|
||||
// $scope.inv = {
|
||||
// gear: {},
|
||||
// special: {},
|
||||
// pets: {},
|
||||
// mounts: {},
|
||||
// eggs: {},
|
||||
// hatchingPotions: {},
|
||||
// food: {},
|
||||
// quests: {},
|
||||
// };
|
||||
// $scope.setAllItems = function (type, value) {
|
||||
// var set = $scope.inv[type];
|
||||
//
|
||||
// for (var item in set) {
|
||||
// if (set.hasOwnProperty(item)) {
|
||||
// set[item] = value;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// };
|
||||
//
|
||||
// $scope.modifyInventory = function () {
|
||||
// $http({
|
||||
// method: "POST",
|
||||
// url: 'api/v3/debug/modify-inventory',
|
||||
// data: {
|
||||
// gear: $scope.showInv.gear ? $scope.inv.gear : null,
|
||||
// special: $scope.showInv.special ? $scope.inv.special : null,
|
||||
// pets: $scope.showInv.pets ? $scope.inv.pets : null,
|
||||
// mounts: $scope.showInv.mounts ? $scope.inv.mounts : null,
|
||||
// eggs: $scope.showInv.eggs ? $scope.inv.eggs : null,
|
||||
// hatchingPotions: $scope.showInv.hatchingPotions ? $scope.inv.hatchingPotions : null,
|
||||
// food: $scope.showInv.food ? $scope.inv.food : null,
|
||||
// quests: $scope.showInv.quests ? $scope.inv.quests : null,
|
||||
// }
|
||||
// })
|
||||
// .then(function (response) {
|
||||
// Notification.text('Inventory updated. Refresh or sync.');
|
||||
// })
|
||||
// };
|
||||
// }
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -24,59 +24,59 @@
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
@import '~client/assets/scss/colors.scss';
|
||||
|
||||
#app-header {
|
||||
padding-left: 14px;
|
||||
margin-top: 56px;
|
||||
background: $purple-50;
|
||||
height: 204px;
|
||||
color: $header-color;
|
||||
flex-wrap: nowrap;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.no-party, .party-members {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.party-members {
|
||||
}
|
||||
|
||||
.view-party {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
right: 0;
|
||||
padding-right: 40px;
|
||||
height: 100%;
|
||||
background-image: linear-gradient(to right, rgba($purple-50, 0), $purple-50);
|
||||
|
||||
.btn {
|
||||
margin-top: 75%;
|
||||
}
|
||||
}
|
||||
|
||||
.no-party {
|
||||
.small-text {
|
||||
#app-header {
|
||||
padding-left: 14px;
|
||||
margin-top: 56px;
|
||||
background: $purple-50;
|
||||
height: 204px;
|
||||
color: $header-color;
|
||||
flex-wrap: nowrap;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: $white;
|
||||
margin-bottom: 4px;
|
||||
.no-party, .party-members {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-top: 16px;
|
||||
.party-members {
|
||||
}
|
||||
|
||||
.view-party {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
right: 0;
|
||||
padding-right: 40px;
|
||||
height: 100%;
|
||||
background-image: linear-gradient(to right, rgba($purple-50, 0), $purple-50);
|
||||
|
||||
.btn {
|
||||
margin-top: 75%;
|
||||
}
|
||||
}
|
||||
|
||||
.no-party {
|
||||
.small-text {
|
||||
color: $header-color;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: $white;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'client/libs/store';
|
||||
import MemberDetails from './memberDetails';
|
||||
import createPartyModal from './guilds/createPartyModal';
|
||||
import createPartyModal from './groups/createPartyModal';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
||||
@@ -24,6 +24,8 @@ div
|
||||
router-link.dropdown-item(:to="{name: 'tavern'}") {{ $t('tavern') }}
|
||||
router-link.dropdown-item(:to="{name: 'myGuilds'}") {{ $t('myGuilds') }}
|
||||
router-link.dropdown-item(:to="{name: 'guildsDiscovery'}") {{ $t('guildsDiscovery') }}
|
||||
router-link.nav-item.dropdown(tag="li", :to="{name: 'groupPlan'}", :class="{'active': $route.path.startsWith('/group-plan')}")
|
||||
a.nav-link(v-once) {{ $t('group') }}
|
||||
router-link.nav-item(tag="li", :to="{name: 'myChallenges'}", exact)
|
||||
a.nav-link(v-once) {{ $t('challenges') }}
|
||||
router-link.nav-item.dropdown(tag="li", to="/help", :class="{'active': $route.path.startsWith('/help')}")
|
||||
@@ -42,8 +44,7 @@ div
|
||||
.item-with-icon
|
||||
.svg-icon(v-html="icons.gold")
|
||||
span {{user.stats.gp | roundBigNumber}}
|
||||
.item-with-icon.item-notifications
|
||||
.svg-icon(v-html="icons.notifications")
|
||||
notification-menu
|
||||
router-link.dropdown.item-with-icon.item-user(:to="{name: 'avatar'}")
|
||||
.svg-icon(v-html="icons.user")
|
||||
.dropdown-menu.dropdown-menu-right.user-dropdown
|
||||
@@ -203,21 +204,21 @@ div
|
||||
import { mapState, mapGetters } from 'client/libs/store';
|
||||
import gemIcon from 'assets/svg/gem.svg';
|
||||
import goldIcon from 'assets/svg/gold.svg';
|
||||
import notificationsIcon from 'assets/svg/notifications.svg';
|
||||
import userIcon from 'assets/svg/user.svg';
|
||||
import logo from 'assets/svg/logo.svg';
|
||||
import InboxModal from './userMenu/inbox.vue';
|
||||
import notificationMenu from './notificationMenu';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
InboxModal,
|
||||
notificationMenu,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
gem: gemIcon,
|
||||
gold: goldIcon,
|
||||
notifications: notificationsIcon,
|
||||
user: userIcon,
|
||||
logo,
|
||||
}),
|
||||
|
||||
66
website/client/components/chat/autoComplete.vue
Normal file
66
website/client/components/chat/autoComplete.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template lang="pug">
|
||||
div.autocomplete-selection
|
||||
div(v-for='result in searchResults', @click='select(result)') {{ result }}
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['selections', 'text'],
|
||||
data () {
|
||||
return {
|
||||
currentSearch: '',
|
||||
searchActive: false,
|
||||
currentSearchPosition: 0,
|
||||
// @TODO: HAve this passed
|
||||
tmpSelections: [
|
||||
'TheHollidayInn',
|
||||
'Paglias',
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
searchResults () {
|
||||
if (!this.searchActive) return [];
|
||||
let currentSearch = this.text.substring(this.currentSearchPosition + 1, this.text.length);
|
||||
return this.tmpSelections.filter((option) => {
|
||||
return option.toLowerCase().indexOf(currentSearch.toLowerCase()) !== -1;
|
||||
});
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
text (newText) {
|
||||
if (newText[newText.length - 1] !== '@') return;
|
||||
this.searchActive = true;
|
||||
this.currentSearchPosition = newText.length - 1;
|
||||
},
|
||||
// @TODO: implement position
|
||||
// caretChanged = function(newCaretPos) {
|
||||
// var relativeelement = $('.chat-form div:first');
|
||||
// var textarea = $('.chat-form textarea');
|
||||
// var userlist = $('.list-at-user');
|
||||
// var offset = {
|
||||
// x: textarea.offset().left - relativeelement.offset().left,
|
||||
// y: textarea.offset().top - relativeelement.offset().top,
|
||||
// };
|
||||
// if(relativeelement) {
|
||||
// var caretOffset = InputCaret.getPosition(textarea);
|
||||
// userlist.css({
|
||||
// left: caretOffset.left + offset.x,
|
||||
// top: caretOffset.top + offset.y + 16
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
},
|
||||
methods: {
|
||||
select (result) {
|
||||
let newText = this.text.slice(0, this.currentSearchPosition + 1) + result;
|
||||
this.searchActive = false;
|
||||
this.$emit('select', newText);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
192
website/client/components/groups/groupPlan.vue
Normal file
192
website/client/components/groups/groupPlan.vue
Normal file
@@ -0,0 +1,192 @@
|
||||
<template lang="pug">
|
||||
.standard-page
|
||||
div(v-if='activePage === PAGES.CREATE_GROUP')
|
||||
h2.text-center {{ $t('createAGroup') }}
|
||||
|
||||
.col-xs-12
|
||||
.col-md-12.form-horizontal
|
||||
.form-group
|
||||
label.control-label(for='new-group-name') {{ $t('newGroupName', {groupType: 'text'}) }}
|
||||
input.form-control#new-group-name.input-medium.option-content(required, type='text', :placeholder="$t('newGroupName', {groupType: 'text'})", v-model='newGroup.name')
|
||||
.form-group
|
||||
label(for='new-group-description') {{ $t('description') }}
|
||||
textarea.form-control#new-group-description.option-content(cols='3', :placeholder="$t('description')", v-model='newGroup.description')
|
||||
.form-group(v-if='type === "guild"')
|
||||
.radio
|
||||
label
|
||||
input(type='radio', name='new-group-privacy', value='public', v-model='newGroup.privacy')
|
||||
| {{ $t('public') }}
|
||||
.radio
|
||||
label
|
||||
input(type='radio', name='new-group-privacy', value='private', v-model='newGroup.privacy')
|
||||
| {{ $t('inviteOnly') }}
|
||||
br
|
||||
input.btn.btn-default(type='submit', :disabled='!newGroup.privacy && !newGroup.name', :value="$t('create')")
|
||||
span.gem-cost {{ '4 ' + $t('gems') }}
|
||||
p
|
||||
small {{ $t('gemCost') }}
|
||||
.form-group
|
||||
.checkbox
|
||||
label
|
||||
input(type='checkbox', v-model='newGroup.leaderOnly.challenges')
|
||||
| {{ $t('leaderOnlyChallenges') }}
|
||||
.form-group(v-if='type === "party"')
|
||||
input.btn.btn-default.form-control(type='submit', :value="$t('create')")
|
||||
br
|
||||
br
|
||||
.row
|
||||
.col-sm-6.col-sm-offset-3
|
||||
a.btn.btn-primary.btn-lg.btn-block(@click="createGroup()", :disabled="!newGroupIsReady") {{ $t('create') }}
|
||||
|
||||
div(v-if='activePage === PAGES.UPGRADE_GROUP')
|
||||
h2.text-center {{ $t('upgradeTitle') }}
|
||||
|
||||
.row.text-center
|
||||
.col-6.col-offset-3
|
||||
a.purchase.btn.btn-primary(@click='upgradeGroup(PAYMENTS.STRIPE)') {{ $t('card') }}
|
||||
a.purchase(@click='upgradeGroup(PAYMENTS.AMAZON)')
|
||||
img(src='https://payments.amazon.com/gp/cba/button', :alt="$t('amazonPayments')")
|
||||
// @TODO: Add paypal
|
||||
.row
|
||||
.col-md-6.col-md-offset-3
|
||||
br
|
||||
.text-center {{ $t('groupSubscriptionPrice') }}
|
||||
|
||||
div(v-if='activePage === PAGES.BENEFITS')
|
||||
h2.text-center {{ $t('groupBenefitsTitle') }}
|
||||
.row(style="font-size: 2rem;")
|
||||
.col-md-6.col-md-offset-3.text-center {{ $t('groupBenefitsDescription') }}
|
||||
.row.row-margin
|
||||
.col-md-4
|
||||
h2 {{ $t('teamBasedTasks') }}
|
||||
div
|
||||
// shared tasks
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitOneTitle') }}
|
||||
span {{ $t('groupBenefitOneDescription') }}
|
||||
div
|
||||
// assign tasks
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitTwoTitle') }}
|
||||
span {{ $t('groupBenefitTwoDescription') }}
|
||||
div
|
||||
// claim tasks
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitThreeTitle') }}
|
||||
span {{ $t('groupBenefitThreeDescription') }}
|
||||
div
|
||||
// mark tasks
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitFourTitle') }}
|
||||
span {{ $t('groupBenefitFourDescription') }}
|
||||
div
|
||||
// group managers
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitEightTitle') }}
|
||||
span {{ $t('groupBenefitEightDescription') }}
|
||||
|
||||
.col-md-4
|
||||
h2 {{ $t('specializedCommunication') }}
|
||||
div
|
||||
// chat privately
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitFiveTitle') }}
|
||||
span {{ $t('groupBenefitFiveDescription') }}
|
||||
div
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitMessageLimitTitle') }}
|
||||
span {{ $t('groupBenefitMessageLimitDescription') }}
|
||||
.col-md-4
|
||||
h2 {{ $t('funExtras') }}
|
||||
div
|
||||
// free subscription
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitSixTitle') }}
|
||||
span {{ $t('groupBenefitSixDescription') }}
|
||||
div
|
||||
// exclusive mount
|
||||
h3
|
||||
span.glyphicon.glyphicon-ok-circle(style='margin-right: 1.5rem;')
|
||||
| {{ $t('groupBenefitSevenTitle') }}
|
||||
|
||||
br
|
||||
br
|
||||
.row
|
||||
.col-sm-6.col-sm-offset-3
|
||||
a.btn.btn-primary.btn-lg.btn-block(ui-sref="options.social.newGroup") {{ $t('createAGroup') }}
|
||||
|
||||
.row
|
||||
.col-md-6.col-md-offset-3
|
||||
br
|
||||
.text-center {{ $t('groupSubscriptionPrice') }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
PAGES: {
|
||||
CREATE_GROUP: 'create-group',
|
||||
UPGRADE_GROUP: 'upgrade-group',
|
||||
},
|
||||
// @TODO: Import from payment library?
|
||||
PAYMENTS: {
|
||||
AMAZON: 'amazon',
|
||||
STRIPE: 'stripe',
|
||||
},
|
||||
newGroup: {
|
||||
type: 'guild',
|
||||
privacy: 'private',
|
||||
name: '',
|
||||
leaderOnly: {
|
||||
challenges: false,
|
||||
},
|
||||
},
|
||||
activePage: '',
|
||||
type: 'guild', // Guild or Party @TODO enum this
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.activePage = this.PAGES.CREATE_GROUP;
|
||||
},
|
||||
computed: {
|
||||
newGroupIsReady () {
|
||||
return Boolean(this.newGroup.name);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
changePage (page) {
|
||||
this.activePage = page;
|
||||
window.scrollTo(0, 0);
|
||||
},
|
||||
createGroup () {
|
||||
this.changePage(this.PAGES.UPGRADE_GROUP);
|
||||
},
|
||||
upgradeGroup (paymentType) {
|
||||
// let subscriptionKey = 'group_monthly'; // @TODO: Get from content API?
|
||||
if (paymentType === this.PAYMENTS.STRIPE) {
|
||||
// Payments.showStripe({
|
||||
// subscription: subscriptionKey,
|
||||
// coupon: null,
|
||||
// groupToCreate: this.newGroup
|
||||
// });
|
||||
} else if (paymentType === this.PAYMENTS.AMAZON) {
|
||||
// Payments.amazonPayments.init({
|
||||
// type: 'subscription',
|
||||
// subscription: subscriptionKey,
|
||||
// coupon: null,
|
||||
// groupToCreate: this.newGroup
|
||||
// });
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,6 +1,7 @@
|
||||
<template lang="pug">
|
||||
.row(v-if="group")
|
||||
group-form-modal
|
||||
invite-modal
|
||||
.clearfix.col-8
|
||||
.row
|
||||
.col-6.title-details
|
||||
@@ -40,7 +41,7 @@
|
||||
.button-container
|
||||
button.btn.btn-success(class='btn-success', v-if='!isMember') {{ $t('join') }}
|
||||
.button-container
|
||||
button.btn.btn-primary(v-once) {{$t('invite')}}
|
||||
button.btn.btn-primary(v-once, @click='showInviteModal()') {{$t('invite')}}
|
||||
.button-container
|
||||
button.btn.btn-primary(v-once, v-if='!isLeader') {{$t('messageGuildLeader')}}
|
||||
.button-container
|
||||
@@ -355,6 +356,8 @@ import ownedQuestsModal from './ownedQuestsModal';
|
||||
import quests from 'common/script/content/quests';
|
||||
import percent from 'common/script/libs/percent';
|
||||
import groupFormModal from './groupFormModal';
|
||||
import inviteModal from './inviteModal';
|
||||
import memberModal from '../members/memberModal';
|
||||
import chatMessage from '../chat/chatMessages';
|
||||
|
||||
import bCollapse from 'bootstrap-vue/lib/components/collapse';
|
||||
@@ -380,12 +383,14 @@ export default {
|
||||
props: ['groupId'],
|
||||
components: {
|
||||
membersModal,
|
||||
memberModal,
|
||||
ownedQuestsModal,
|
||||
bCollapse,
|
||||
bCard,
|
||||
bTooltip,
|
||||
groupFormModal,
|
||||
chatMessage,
|
||||
inviteModal,
|
||||
},
|
||||
directives: {
|
||||
bToggle,
|
||||
@@ -507,6 +512,9 @@ export default {
|
||||
this.$store.state.editingGroup = this.group;
|
||||
this.$root.$emit('show::modal', 'guild-form');
|
||||
},
|
||||
showInviteModal () {
|
||||
this.$root.$emit('show::modal', 'invite-modal');
|
||||
},
|
||||
async fetchGuild () {
|
||||
let group = await this.$store.dispatch('guilds:getGroup', {groupId: this.groupId});
|
||||
if (this.isParty) {
|
||||
147
website/client/components/groups/inviteModal.vue
Normal file
147
website/client/components/groups/inviteModal.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<template lang="pug">
|
||||
b-modal#invite-modal(:title="$t('inviteFriends')", size='lg')
|
||||
.modal-body
|
||||
p.alert.alert-info(v-html="$t('inviteAlertInfo')")
|
||||
.form-horizontal
|
||||
table.table.table-striped
|
||||
thead
|
||||
tr
|
||||
th {{ $t('userId') }}
|
||||
tbody
|
||||
tr(v-for='user in invitees')
|
||||
td
|
||||
input.form-control(type='text', v-model='user.uuid')
|
||||
tr
|
||||
td
|
||||
button.btn.btn-xs.pull-right(@click='addUuid()')
|
||||
i.glyphicon.glyphicon-plus
|
||||
| +
|
||||
tr
|
||||
td
|
||||
.col-6.col-offset-6
|
||||
button.btn.btn-primary.btn-block(@click='inviteNewUsers("uuid")') {{sendInviteText}}
|
||||
hr
|
||||
p.alert.alert-info {{ $t('inviteByEmail') }}
|
||||
.form-horizontal
|
||||
table.table.table-striped
|
||||
thead
|
||||
tr
|
||||
th {{ $t('name') }}
|
||||
th {{ $t('email') }}
|
||||
tbody
|
||||
tr(v-for='email in emails')
|
||||
td
|
||||
input.form-control(type='text', v-model='email.name')
|
||||
td
|
||||
input.form-control(type='email', v-model='email.email')
|
||||
tr
|
||||
td(colspan=2)
|
||||
a.btn.btn-xs.pull-right(@click='addEmail()')
|
||||
i.glyphicon.glyphicon-plus
|
||||
| +
|
||||
tr
|
||||
td.form-group(colspan=2)
|
||||
label.col-sm-1.control-label {{ $t('byColon') }}
|
||||
.col-sm-5
|
||||
input.form-control(type='text', v-model='inviter')
|
||||
.col-sm-6
|
||||
button.btn.btn-primary.btn-block(@click='inviteNewUsers("email")') {{sendInviteText}}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
import filter from 'lodash/filter';
|
||||
import map from 'lodash/map';
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
props: ['group'],
|
||||
data () {
|
||||
return {
|
||||
invitees: [],
|
||||
emails: [],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
inviter () {
|
||||
return this.user.profile.name;
|
||||
},
|
||||
sendInviteText () {
|
||||
if (!this.group) return 'Send Invites';
|
||||
return this.group.sendInviteText;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addUuid () {
|
||||
this.invitees.push({uuid: ''});
|
||||
},
|
||||
addEmail () {
|
||||
this.emails.push({name: '', email: ''});
|
||||
},
|
||||
inviteNewUsers (inviteMethod) {
|
||||
if (!this.group._id) {
|
||||
if (!this.group.name) this.group.name = this.$t('possessiveParty', {name: this.user.profile.name});
|
||||
|
||||
// @TODO: Add dispatch
|
||||
// return Groups.Group.create(this.group)
|
||||
// .then(function(response) {
|
||||
// this.group = response.data.data;
|
||||
// _inviteByMethod(inviteMethod);
|
||||
// });
|
||||
}
|
||||
|
||||
this.inviteByMethod(inviteMethod);
|
||||
},
|
||||
// inviteByMethod (inviteMethod) {
|
||||
// let invitationDetails;
|
||||
//
|
||||
// if (inviteMethod === 'email') {
|
||||
// let emails = this.getEmails();
|
||||
// invitationDetails = { inviter: this.inviter, emails };
|
||||
// } else if (inviteMethod === 'uuid') {
|
||||
// let uuids = this.getOnlyUuids();
|
||||
// invitationDetails = { uuids };
|
||||
// } else {
|
||||
// return alert('Invalid invite method.');
|
||||
// }
|
||||
|
||||
// @TODO: Add dispatch
|
||||
// Groups.Group.invite(this.group._id, invitationDetails)
|
||||
// .then(function () {
|
||||
// let invitesSent = invitationDetails.emails || invitationDetails.uuids;
|
||||
// let invitationString = invitesSent.length > 1 ? 'invitationsSent' : 'invitationSent';
|
||||
//
|
||||
// Notification.text(window.env.t(invitationString));
|
||||
//
|
||||
// _resetInvitees();
|
||||
//
|
||||
// if (this.group.type === 'party') {
|
||||
// $rootScope.hardRedirect('/#/options/groups/party');
|
||||
// } else {
|
||||
// $rootScope.hardRedirect('/#/options/groups/guilds/' + this.group._id);
|
||||
// }
|
||||
// }, function(){
|
||||
// _resetInvitees();
|
||||
// });
|
||||
// },
|
||||
getOnlyUuids () {
|
||||
let uuids = map(this.invitees, 'uuid');
|
||||
let filteredUuids = filter(uuids, (id) => {
|
||||
return id !== '';
|
||||
});
|
||||
return filteredUuids;
|
||||
},
|
||||
getEmails () {
|
||||
let emails = filter(this.emails, (obj) => {
|
||||
return obj.email !== '';
|
||||
});
|
||||
return emails;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -10,6 +10,7 @@
|
||||
h3(v-once) {{ $t('welcomeToTavern') }}
|
||||
|
||||
textarea(:placeholder="$t('chatPlaceHolder')", v-model='newMessage')
|
||||
autocomplete(:text='newMessage', v-on:select="selectedAutocomplete")
|
||||
button.btn.btn-secondary.send-chat.float-right(v-once, @click='sendMessage()') {{ $t('send') }}
|
||||
|
||||
.container.community-guidelines(v-if='communityGuidelinesAccepted')
|
||||
@@ -282,6 +283,7 @@ import { mapState } from 'client/libs/store';
|
||||
|
||||
import { TAVERN_ID } from '../../../common/script/constants';
|
||||
import chatMessage from '../chat/chatMessages';
|
||||
import autocomplete from '../chat/autoComplete';
|
||||
|
||||
import gemIcon from 'assets/svg/gem.svg';
|
||||
import questIcon from 'assets/svg/quest.svg';
|
||||
@@ -294,6 +296,7 @@ import downIcon from 'assets/svg/down.svg';
|
||||
export default {
|
||||
components: {
|
||||
chatMessage,
|
||||
autocomplete,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -399,6 +402,9 @@ export default {
|
||||
this.group = await this.$store.dispatch('guilds:getGroup', {groupId: TAVERN_ID});
|
||||
},
|
||||
methods: {
|
||||
selectedAutocomplete (newText) {
|
||||
this.newMessage = newText;
|
||||
},
|
||||
aggreeToGuideLines () {
|
||||
// @TODO:
|
||||
},
|
||||
175
website/client/components/hall/heroes.vue
Normal file
175
website/client/components/hall/heroes.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template lang="pug">
|
||||
.row
|
||||
small.muted(v-html="$t('blurbHallContributors')")
|
||||
.well(v-if='user.contributor.admin')
|
||||
h2 {{ $t('rewardUser') }}
|
||||
form(v-submit='loadHero(_heroID)')
|
||||
.form-group
|
||||
input.form-control(type='text', v-model='_heroID', placeholder {{ $t('UUID') }})
|
||||
.form-group
|
||||
input.btn.btn-default(type='submit')
|
||||
| {{ $t('loadUser') }}
|
||||
form(v-show='hero', v-submit='saveHero(hero)')
|
||||
a(v-click='clickMember(hero._id, true)')
|
||||
h3 {{hero.profile.name}}
|
||||
.form-group
|
||||
input.form-control(type='text', v-model='hero.contributor.text', placeholder {{ $t('contribTitle') }})
|
||||
.form-group
|
||||
label {{ $t('contribLevel') }}
|
||||
input.form-control(type='number', v-model='hero.contributor.level')
|
||||
small {{ $t('contribHallText') }}
|
||||
|
|
||||
a(target='_blank', href='https://trello.com/c/wkFzONhE/277-contributor-gear') {{ $t('moreDetails') }}
|
||||
|,
|
||||
a(target='_blank', href='https://github.com/HabitRPG/habitica/issues/3801') {{ $t('moreDetails2') }}
|
||||
.form-group
|
||||
textarea.form-control(cols=5, placeholder {{ $t('contributions') }}, v-model='hero.contributor.contributions')
|
||||
//include ../../shared/formattiv-help
|
||||
hr
|
||||
|
||||
.form-group
|
||||
label {{ $t('balance') }}
|
||||
input.form-control(type='number', step="any", v-model='hero.balance')
|
||||
small {{ '`user.balance`' + this.$t('notGems') }}
|
||||
accordion
|
||||
accordion-group(heading='Items')
|
||||
h4 Update Item
|
||||
.form-group.well
|
||||
input.form-control(type='text',placeholder='Path (eg, items.pets.BearCub-Base)',v-model='hero.itemPath')
|
||||
small.muted Enter the <strong>item path</strong>. E.g., <code>items.pets.BearCub-Zombie</code> or <code>items.gear.owned.head_special_0</code> or <code>items.gear.equipped.head</code>. You can find all the item paths below.
|
||||
br
|
||||
input.form-control(type='text',placeholder='Value (eg, 5)',v-model='hero.itemVal')
|
||||
small.muted Enter the <strong>item value</strong>. E.g., <code>5</code> or <code>false</code> or <code>head_warrior_3</code>. All values are listed in the All Item Paths section below.
|
||||
accordion
|
||||
accordion-group(heading='All Item Paths')
|
||||
pre {{allItemPaths}}
|
||||
accordion-group(heading='Current Items')
|
||||
pre {{toJson(hero.items, true)}}
|
||||
accordion-group(heading='Auth')
|
||||
h4 Auth
|
||||
pre {{toJson(hero.auth)}}
|
||||
.form-group
|
||||
.checkbox
|
||||
label
|
||||
input(type='checkbox', v-model='hero.flags.chatRevoked')
|
||||
| Chat Privileges Revoked
|
||||
.form-group
|
||||
.checkbox
|
||||
label
|
||||
input(type='checkbox', v-model='hero.auth.blocked')
|
||||
| Blocked
|
||||
|
||||
// h4 Backer Status
|
||||
// Add backer stuff like tier, disable adds, etcs
|
||||
.form-group
|
||||
input.form-control.btn.btn-primary(type='submit')
|
||||
| {{ $t('save') }}
|
||||
|
||||
.table-responsive
|
||||
table.table.table-striped
|
||||
thead
|
||||
tr
|
||||
th {{ $t('name') }}
|
||||
th(v-if='user.contributor.admin') {{ $t('UUID') }}
|
||||
th {{ $t('contribLevel') }}
|
||||
th {{ $t('title') }}
|
||||
th {{ $t('contributions') }}
|
||||
tbody
|
||||
tr(v-repeat='hero in heroes')
|
||||
td
|
||||
span(v-if='hero.contributor.admin', :popover="$t('gamemaster')", popover-trigger='mouseenter', popover-placement='right')
|
||||
a.label.label-default(v-class='userLevelStyle(hero)', v-click='clickMember(hero._id, true)')
|
||||
| {{hero.profile.name}}
|
||||
span(v-class='userAdminGlyphiconStyle(hero)')
|
||||
span(v-if='!hero.contributor.admin')
|
||||
a.label.label-default(v-class='userLevelStyle(hero)', v-click='clickMember(hero._id, true)') {{hero.profile.name}}
|
||||
td(v-if='user.contributor.admin', v-click='populateContributorInput(hero._id, $index)').btn-link {{hero._id}}
|
||||
td {{hero.contributor.level}}
|
||||
td {{hero.contributor.text}}
|
||||
td
|
||||
markdown(text='hero.contributor.contributions', target='_blank')
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import keys from 'lodash/keys';
|
||||
import each from 'lodash/each';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
import quests from 'common/script/content/quests';
|
||||
import { mountInfo, petInfo } from 'common/script/content/stable';
|
||||
import { food, hatchingPotions, special } from 'common/script/content';
|
||||
import gear from 'common/script/content/gear';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
heroes: [],
|
||||
hero: {},
|
||||
currentHeroIndex: -1,
|
||||
allItemPaths: this.getAllItemPaths(),
|
||||
quests,
|
||||
mountInfo,
|
||||
petInfo,
|
||||
food,
|
||||
hatchingPotions,
|
||||
special,
|
||||
gear,
|
||||
};
|
||||
},
|
||||
async mounted () {
|
||||
this.heroes = await this.$store.dispatch('hall:getHeroes');
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
getAllItemPaths () {
|
||||
let questsFormat = this.getFormattedItemReference('items.quests', keys(this.quests), 'Numeric Quantity');
|
||||
let mountsFormat = this.getFormattedItemReference('items.mounts', keys(this.mountInfo), 'Boolean');
|
||||
let foodFormat = this.getFormattedItemReference('items.food', keys(this.food), 'Numeric Quantity');
|
||||
let eggsFormat = this.getFormattedItemReference('items.eggs', keys(this.eggs), 'Numeric Quantity');
|
||||
let hatchingPotionsFormat = this.getFormattedItemReference('items.hatchingPotions', keys(this.hatchingPotions), 'Numeric Quantity');
|
||||
let petsFormat = this.getFormattedItemReference('items.pets', keys(this.petInfo), '-1: Owns Mount, 0: Not Owned, 1-49: Progress to mount');
|
||||
let specialFormat = this.getFormattedItemReference('items.special', keys(this.special), 'Numeric Quantity');
|
||||
let gearFormat = this.getFormattedItemReference('items.gear.owned', keys(this.gear.flat), 'Boolean');
|
||||
|
||||
let equippedGearFormat = '\nEquipped Gear:\n\titems.gear.{equipped/costume}.{head/headAccessory/eyewear/armor/body/back/shield/weapon}.{gearKey}\n';
|
||||
let equippedPetFormat = '\nEquipped Pet:\n\titems.currentPet.{petKey}\n';
|
||||
let equippedMountFormat = '\nEquipped Mount:\n\titems.currentMount.{mountKey}\n';
|
||||
|
||||
let data = questsFormat.concat(mountsFormat, foodFormat, eggsFormat, hatchingPotionsFormat, petsFormat, specialFormat, gearFormat, equippedGearFormat, equippedPetFormat, equippedMountFormat);
|
||||
|
||||
return data;
|
||||
},
|
||||
getFormattedItemReference (pathPrefix, itemKeys, values) {
|
||||
let finishedString = '\n'.concat('path: ', pathPrefix, ', ', 'value: {', values, '}\n');
|
||||
|
||||
each(itemKeys, (key) => {
|
||||
finishedString = finishedString.concat('\t', pathPrefix, '.', key, '\n');
|
||||
});
|
||||
|
||||
return finishedString;
|
||||
},
|
||||
async loadHero (uuid, heroIndex) {
|
||||
this.currentHeroIndex = heroIndex;
|
||||
let hero = await this.$store.dispatch('hall:getHero', { uuid });
|
||||
this.hero = hero;
|
||||
},
|
||||
async saveHero (hero) {
|
||||
this.hero.contributor.admin = this.hero.contributor.level > 7 ? true : false;
|
||||
let heroUpdated = await this.$store.dispatch('hall:updateHero', { heroDetails: hero });
|
||||
// @TODO: Import
|
||||
// Notification.text("User updated");
|
||||
this.hero = {};
|
||||
this._heroID = -1;
|
||||
this.heroes[this.currentHeroIndex] = heroUpdated;
|
||||
this.currentHeroIndex = -1;
|
||||
},
|
||||
populateContributorInput (id, index) {
|
||||
this._heroID = id;
|
||||
window.scrollTo(0, 200);
|
||||
this.loadHero(id, index);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
19
website/client/components/hall/index.vue
Normal file
19
website/client/components/hall/index.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template lang="pug">
|
||||
.row
|
||||
secondary-menu.col-12
|
||||
router-link.nav-link(:to="{name: 'contributors'}", exact, :class="{'active': $route.name === 'contributors'}") {{ $t('hallContributors') }}
|
||||
router-link.nav-link(:to="{name: 'patrons'}", :class="{'active': $route.name === 'patrons'}") {{ $t('hallPatrons') }}
|
||||
|
||||
.col-12
|
||||
router-view
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SecondaryMenu from 'client/components/secondaryMenu';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SecondaryMenu,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
53
website/client/components/hall/patrons.vue
Normal file
53
website/client/components/hall/patrons.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template lang="pug">
|
||||
.row
|
||||
small.muted {{ $t('blurbHallPatrons') }}
|
||||
.table-responsive
|
||||
table.table.table-striped(infinite-scroll="loadMore()")
|
||||
thead
|
||||
tr
|
||||
th {{ $t('name') }}
|
||||
th(v-if='user.contributor.admin') {{ $t('UUID') }}
|
||||
th {{ $t('backerTier') }}
|
||||
tbody
|
||||
tr(v-for='patron in patrons')
|
||||
td
|
||||
a.label.label-default(v-class='userLevelStyle(patron)', @click='clickMember(patron._id, true)')
|
||||
| {{patron.profile.name}}
|
||||
td(v-if='user.contributor.admin') {{patron._id}}
|
||||
td {{patron.backer.tier}}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
patrons: [],
|
||||
};
|
||||
},
|
||||
async mounted () {
|
||||
this.patrons = await this.$store.dispatch('hall:getPatrons', { page: 0 });
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
methods: {
|
||||
// @TODO: This is used to style usernames. WE should abstract this to helper mixer
|
||||
userLevelStyle (user, style) {
|
||||
style = style || '';
|
||||
let npc = user && user.backer && user.backer.npc ? user.backer.npc : '';
|
||||
let level = user && user.contributor && user.contributor.level ? user.contributor.level : '';
|
||||
style += this.userLevelStyleFromLevel(level, npc, style);
|
||||
return style;
|
||||
},
|
||||
userLevelStyleFromLevel (level, npc, style) {
|
||||
style = style || '';
|
||||
if (npc) style += ' label-npc';
|
||||
if (level) style += ` label-contributor-${level}`;
|
||||
return style;
|
||||
},
|
||||
//@TODO: Import member modal - clickMember()
|
||||
},
|
||||
};
|
||||
</script>
|
||||
143
website/client/components/members/memberModal.vue
Normal file
143
website/client/components/members/memberModal.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template lang="pug">
|
||||
b-modal#member-detail-modal(title="Empty", size='lg')
|
||||
.modal-header
|
||||
h4
|
||||
span {{profile.profile.name}}
|
||||
span(v-if='contribText && profile.contributor.level') - {{contribText(profile.contributor, profile.backer)}}
|
||||
.modal-body
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-6
|
||||
img.img-renderiv-auto(v-if='profile.profile.imageUrl', :src='profile.profile.imageUrl')
|
||||
markdown(v-if='profile.profile.blurb', text='profile.profile.blurb')
|
||||
ul.muted.list-unstyled(v-if='profile.auth.timestamps')
|
||||
li {{profile._id}}
|
||||
li(v-if='profile.auth.timestamps.created')
|
||||
|
|
||||
| {{ $t('memberSince') }}
|
||||
|
|
||||
| {{profile.auth.timestamps.created | date:user.preferences.dateFormat}} -
|
||||
li(v-if='profile.auth.timestamps.loggedin')
|
||||
|
|
||||
| {{ $t('lastLoggedIn') }}
|
||||
|
|
||||
| {{profile.auth.timestamps.loggedin | date:user.preferences.dateFormat}} -
|
||||
h3 {{ $t('stats') }}
|
||||
// @TODO: Figure out why this isn't showing up in front page
|
||||
.label.label-info {{ {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer")}[profile.stats.class] }}
|
||||
// include ../profiles/stats_all
|
||||
.col-md-6
|
||||
.row
|
||||
//@TODO: +herobox()
|
||||
.row
|
||||
h3 {{ $t('achievements') }}
|
||||
//include ../profiles/achievements
|
||||
.modal-footer
|
||||
.btn-group.pull-left(v-if='user')
|
||||
button.btn.btn-md.btn-default(v-if='user.inbox.blocks.indexOf(profile._id) !== -1', :tooltip="$t('unblock')", @click="User.blockUser({params:{uuid:profile._id}})", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-plus
|
||||
button.btn.btn-md.btn-default(v-if='profile._id != user._id && !profile.contributor.admin && !(user.inbox.blocks | contains:profile._id)', tooltip {{ $t('block') }}, @click="User.blockUser({params:{uuid:profile._id}})", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-ban-circle
|
||||
button.btn.btn-md.btn-default(:tooltip="$t('sendPM')", @click="openModal('private-message',{controller:'MemberModalCtrl'})", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-envelope
|
||||
button.btn.btn-md.btn-default(:tooltip="$t('sendGift')", @click="openModal('send-gift',{controller:'MemberModalCtrl'})", tooltip-placement='right')
|
||||
span.glyphicon.glyphicon-gift
|
||||
button.btn.btn-default(@click='close()') {{ $t('close') }}
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
import moment from 'moment';
|
||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||
|
||||
export default {
|
||||
// @TODO: We should probably use a store. Only view one member at a time?
|
||||
props: ['profile'],
|
||||
data () {
|
||||
return {
|
||||
// @TODO: We don't send subscriptions so the structure has changed in the back. Update this when we update the views.
|
||||
gift: {
|
||||
type: 'gems',
|
||||
gems: {amount: 0, fromBalance: true},
|
||||
subscription: {key: ''},
|
||||
message: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
components: {
|
||||
bModal,
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
},
|
||||
mounted () {
|
||||
// @TODO: This.$store.selectmember
|
||||
// if (member) {
|
||||
// this.profile = member;
|
||||
//
|
||||
// this.achievements = Shared.achievements.getAchievementsForProfile(this.profile);
|
||||
// this.achievPopoverPlacement = 'left';
|
||||
// this.achievAppendToBody = 'false'; // append-to-body breaks popovers in modal windows
|
||||
// }
|
||||
},
|
||||
methods: {
|
||||
timestamp (timestamp) {
|
||||
return moment(timestamp).format(this.user.preferences.dateFormat.toUpperCase());
|
||||
},
|
||||
// @TODO: create mixin for stats: this.statCalc = Stats;
|
||||
// @TODO: create mixin or library for constume functions this.costume = Costume;
|
||||
keyDownListener (e) {
|
||||
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
|
||||
this.sendPrivateMessage(this.profile._id, this._message);
|
||||
}
|
||||
},
|
||||
// @TODO: Inbox?
|
||||
sendPrivateMessage (uuid, message) {
|
||||
if (!message) return;
|
||||
|
||||
// Members.sendPrivateMessage(message, uuid)
|
||||
// .then(function (response) {
|
||||
// Notification.text(window.env.t('messageSentAlert'));
|
||||
// $rootScope.User.sync();
|
||||
// this.$close();
|
||||
// });
|
||||
},
|
||||
async sendGift (uuid) {
|
||||
await this.$store.dispatch('members:transferGems', {
|
||||
message: this.gift.message,
|
||||
toUserId: uuid,
|
||||
gemAmount: this.gift.gems.amount,
|
||||
});
|
||||
|
||||
// @TODO: Notification.text(this.$t('sentGems'));
|
||||
// @TODO: What needs to be synced? $rootScope.User.sync();
|
||||
this.close();
|
||||
},
|
||||
async reportAbuse (reporter, message, groupId) {
|
||||
let response = await this.$store.dispatch('chat:flag', {
|
||||
groupId,
|
||||
chatId: message.id,
|
||||
});
|
||||
|
||||
message.flags = response.flags;
|
||||
message.flagCount = response.flagCount;
|
||||
// @TODO: Notification.text(this.$t('abuseReported'));
|
||||
this.close();
|
||||
},
|
||||
async clearFlagCount (message, groupId) {
|
||||
await this.$store.dispatch('chat:clearFlagCount', {
|
||||
groupId,
|
||||
chatId: message.id,
|
||||
});
|
||||
|
||||
message.flagCount = 0;
|
||||
// @TODO: Notification.text("Flags cleared");
|
||||
this.close();
|
||||
},
|
||||
close () {
|
||||
this.$root.$emit('hide::modal', 'member-detail-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
198
website/client/components/notificationMenu.vue
Normal file
198
website/client/components/notificationMenu.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template lang="pug">
|
||||
.item-with-icon.item-notifications.dropdown
|
||||
.svg-icon(v-html="icons.notifications")
|
||||
// span.glyphicon(:class='iconClasses()')
|
||||
// span.notification-counter(v-if='getNotificationsCount()') {{getNotificationsCount()}}
|
||||
.dropdown-menu.dropdown-menu-right.user-dropdown
|
||||
a.dropdown-item test
|
||||
h4 {{ $t('notifications') }}
|
||||
div
|
||||
ul.toolbar-notifs-notifs
|
||||
li.toolbar-notifs-no-messages(v-if='hasNoNotifications()') {{ $t('noNotifications') }}
|
||||
li(v-if='user.purchased.plan.mysteryItems.length')
|
||||
a(@click='$state.go("options.inventory.drops"); ')
|
||||
span.glyphicon.glyphicon-gift
|
||||
span {{ $t('newSubscriberItem') }}
|
||||
li(v-for='party in user.invitations.parties')
|
||||
a(ui-sref='options.social.party')
|
||||
span.glyphicon.glyphicon-user
|
||||
span {{ $t('invitedTo', {name: party.name}) }}
|
||||
li(v-if='user.flags.cardReceived')
|
||||
a(@click='$state.go("options.inventory.drops"); ')
|
||||
span.glyphicon.glyphicon-envelope
|
||||
span {{ $t('cardReceived') }}
|
||||
a(@click='clearCards()', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
|
||||
span.glyphicon.glyphicon-remove-circle
|
||||
li(v-for='guild in user.invitations.guilds')
|
||||
a(ui-sref='options.social.guilds.public')
|
||||
span.glyphicon.glyphicon-user
|
||||
span {{ $t('invitedTo', {name: guild.name}) }}
|
||||
li(v-if='user.flags.classSelected && !user.preferences.disableClasses && user.stats.points')
|
||||
a(ui-sref='options.profile.stats')
|
||||
span.glyphicon.glyphicon-plus-sign
|
||||
span {{ $t('haveUnallocated', {points: user.stats.points}) }}
|
||||
li(v-for='(k,v) in user.newMessages', v-if='v.value')
|
||||
a(@click='(k === party._id || k === user.party._id) ? $state.go("options.social.party") : $state.go("options.social.guilds.detail",{gid:k}); ')
|
||||
span.glyphicon.glyphicon-comment
|
||||
span {{v.name}}
|
||||
a(@click='clearMessages(k)', :popover="$t('clear')", popover-placement='right', popover-trigger='mouseenter',popover-append-to-body='true')
|
||||
span.glyphicon.glyphicon-remove-circle
|
||||
li(v-for='notification in user.groupNotifications')
|
||||
a(@click='viewGroupApprovalNotification(notification, $index, true)')
|
||||
span(:class="groupApprovalNotificationIcon(notification)")
|
||||
span
|
||||
| {{notification.data.message}}
|
||||
a(@click='viewGroupApprovalNotification(notification, $index)',
|
||||
:popover="$t('clear')",
|
||||
popover-placement='right',
|
||||
popover-trigger='mouseenter',
|
||||
popover-append-to-body='true')
|
||||
span.glyphicon.glyphicon-remove-circle
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import map from 'lodash/map';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
import quests from 'common/script/content/quests';
|
||||
import notificationsIcon from 'assets/svg/notifications.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
notifications: notificationsIcon,
|
||||
}),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
party () {
|
||||
return {name: ''};
|
||||
// return this.user.party;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// @TODO: I hate this function, we can do better with a hashmap
|
||||
selectNotificationValue (mysteryValue, invitationValue, cardValue,
|
||||
unallocatedValue, messageValue, noneValue, groupApprovalRequested, groupApproved) {
|
||||
let user = this.user;
|
||||
|
||||
if (user.purchased && user.purchased.plan && user.purchased.plan.mysteryItems && user.purchased.plan.mysteryItems.length) {
|
||||
return mysteryValue;
|
||||
} else if (user.invitations.parties && user.invitations.parties.length > 0 || user.invitations.guilds && user.invitations.guilds.length > 0) {
|
||||
return invitationValue;
|
||||
} else if (user.flags.cardReceived) {
|
||||
return cardValue;
|
||||
} else if (user.flags.classSelected && !(user.preferences && user.preferences.disableClasses) && user.stats.points) {
|
||||
return unallocatedValue;
|
||||
} else if (!isEmpty(user.newMessages)) {
|
||||
return messageValue;
|
||||
} else if (!isEmpty(user.groupNotifications)) {
|
||||
let groupNotificationTypes = map(user.groupNotifications, 'type');
|
||||
if (groupNotificationTypes.indexOf('GROUP_TASK_APPROVAL') !== -1) {
|
||||
return groupApprovalRequested;
|
||||
} else if (groupNotificationTypes.indexOf('GROUP_TASK_APPROVED') !== -1) {
|
||||
return groupApproved;
|
||||
}
|
||||
return noneValue;
|
||||
} else {
|
||||
return noneValue;
|
||||
}
|
||||
},
|
||||
hasQuestProgress () {
|
||||
let user = this.user;
|
||||
if (user.party.quest) {
|
||||
let userQuest = quests[user.party.quest.key];
|
||||
|
||||
if (!userQuest) {
|
||||
return false;
|
||||
}
|
||||
if (userQuest.boss && user.party.quest.progress.up > 0) {
|
||||
return true;
|
||||
}
|
||||
if (userQuest.collect && user.party.quest.progress.collectedItems > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
getQuestInfo () {
|
||||
let user = this.user;
|
||||
let questInfo = {};
|
||||
if (user.party.quest) {
|
||||
let userQuest = quests[user.party.quest.key];
|
||||
|
||||
questInfo.title = userQuest.text();
|
||||
|
||||
if (userQuest.boss) {
|
||||
questInfo.body = this.$t('questTaskDamage', { damage: user.party.quest.progress.up.toFixed(1) });
|
||||
} else if (userQuest.collect) {
|
||||
questInfo.body = this.$t('questTaskCollection', { items: user.party.quest.progress.collectedItems });
|
||||
}
|
||||
}
|
||||
return questInfo;
|
||||
},
|
||||
clearMessages () {
|
||||
this.$store.dispatch('chat:markChatSeen');
|
||||
},
|
||||
clearCards () {
|
||||
this.$store.dispatch('chat:clearCards');
|
||||
},
|
||||
getNotificationsCount () {
|
||||
let count = 0;
|
||||
|
||||
if (this.user.invitations.parties) {
|
||||
count += this.user.invitations.parties.length;
|
||||
}
|
||||
|
||||
if (this.user.purchased.plan && this.user.purchased.plan.mysteryItems.length) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (this.user.invitations.guilds) {
|
||||
count += this.user.invitations.guilds.length;
|
||||
}
|
||||
|
||||
if (this.user.flags.classSelected && !this.user.preferences.disableClasses && this.user.stats.points) {
|
||||
count += this.user.stats.points > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
if (this.user.newMessages) {
|
||||
count += Object.keys(this.user.newMessages).length;
|
||||
}
|
||||
|
||||
return count;
|
||||
},
|
||||
iconClasses () {
|
||||
return this.selectNotificationValue(
|
||||
'glyphicon-gift',
|
||||
'glyphicon-user',
|
||||
'glyphicon-envelope',
|
||||
'glyphicon-plus-sign',
|
||||
'glyphicon-comment',
|
||||
'glyphicon-comment inactive',
|
||||
'glyphicon-question-sign',
|
||||
'glyphicon-ok-sign'
|
||||
);
|
||||
},
|
||||
hasNoNotifications () {
|
||||
return this.selectNotificationValue(false, false, false, false, false, true, false, false);
|
||||
},
|
||||
viewGroupApprovalNotification (notification, index, navigate) {
|
||||
// @TODO: USe notifications: User.readNotification(notification.id);
|
||||
this.user.groupNotifications.splice(index, 1);
|
||||
return navigate; // @TODO: remove
|
||||
// @TODO: this.$route.go if (navigate) $state.go('options.social.guilds.detail', {gid: notification.data.groupId});
|
||||
},
|
||||
groupApprovalNotificationIcon (notification) {
|
||||
if (notification.type === 'GROUP_TASK_APPROVAL') {
|
||||
return 'glyphicon glyphicon-question-sign';
|
||||
} else if (notification.type === 'GROUP_TASK_APPROVED') {
|
||||
return 'glyphicon glyphicon-ok-sign';
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
401
website/client/components/notifications.vue
Normal file
401
website/client/components/notifications.vue
Normal file
@@ -0,0 +1,401 @@
|
||||
<template lang="pug">
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import moment from 'moment';
|
||||
|
||||
import { mapState } from 'client/libs/store';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
// Levels that already display modals and should not trigger generic Level Up
|
||||
let unlockLevels = {
|
||||
3: 'drop system',
|
||||
10: 'class system',
|
||||
50: 'Orb of Rebirth',
|
||||
};
|
||||
|
||||
// Avoid showing the same notiication more than once
|
||||
let lastShownNotifications = [];
|
||||
let alreadyReadNotification = [];
|
||||
|
||||
return {
|
||||
unlockLevels,
|
||||
lastShownNotifications,
|
||||
alreadyReadNotification,
|
||||
isRunningYesterdailies: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({user: 'user.data'}),
|
||||
// https://stackoverflow.com/questions/42133894/vue-js-how-to-properly-watch-for-nested-properties/42134176#42134176
|
||||
baileyShouldShow () {
|
||||
return this.user.flags.newStuff;
|
||||
},
|
||||
userHp () {
|
||||
return this.user.stats.hp;
|
||||
},
|
||||
userExp () {
|
||||
return this.user.stats.exp;
|
||||
},
|
||||
userGp () {
|
||||
return this.user.stats.gp;
|
||||
},
|
||||
userMp () {
|
||||
return this.user.stats.mp;
|
||||
},
|
||||
userLvl () {
|
||||
return this.user.stats.lvl;
|
||||
},
|
||||
userClassSelect () {
|
||||
return !this.user.flags.classSelected && this.user.stats.lvl >= 10;
|
||||
},
|
||||
userNotifications () {
|
||||
return this.user.notifications;
|
||||
},
|
||||
userAchievements () {
|
||||
// @TODO: does this watch deeply?
|
||||
return this.user.achievements;
|
||||
},
|
||||
armoireEmpty () {
|
||||
return this.user.flags.armoireEmpty;
|
||||
},
|
||||
questCompleted () {
|
||||
return this.user.party.quest.completed;
|
||||
},
|
||||
invitedToQuest () {
|
||||
return this.user.party.quest.RSVPNeeded && !this.user.party.quest.completed;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
baileyShouldShow () {
|
||||
// @TODO: this.openModal('newStuff', {size:'lg'});
|
||||
},
|
||||
userHp (after, before) {
|
||||
if (after <= 0) {
|
||||
this.playSound('Death');
|
||||
// @TODO: this.openModal('death', {keyboard:false, backdrop:'static'});
|
||||
} else if (after <= 30 && !this.user.flags.warnedLowHealth) {
|
||||
// @TODO: this.openModal('lowHealth', {keyboard:false, backdrop:'static', controller:'UserCtrl', track:'Health Warning'});
|
||||
}
|
||||
if (after === before) return;
|
||||
if (this.user.stats.lvl === 0) return;
|
||||
// @TODO: Notification.hp(after - before, 'hp');
|
||||
|
||||
// @TODO: I am pretty sure we no long need this with $store
|
||||
// this.$broadcast('syncPartyRequest', {
|
||||
// type: 'user_update',
|
||||
// user: this.user,
|
||||
// });
|
||||
|
||||
if (after < 0) this.playSound('Minus_Habit');
|
||||
},
|
||||
userExp (after, before) {
|
||||
if (after === before) return;
|
||||
if (this.user.stats.lvl === 0) return;
|
||||
// @TODO: Notification.exp(after - before);
|
||||
},
|
||||
userGp (after, before) {
|
||||
if (after === before) return;
|
||||
if (this.user.stats.lvl === 0) return;
|
||||
|
||||
let money = after - before;
|
||||
let bonus;
|
||||
if (this.user._tmp) {
|
||||
bonus = this.user._tmp.streakBonus || 0;
|
||||
}
|
||||
// @TODO: Notification.gp(money, bonus || 0);
|
||||
|
||||
// Append Bonus
|
||||
if (money > 0 && Boolean(bonus)) {
|
||||
if (bonus < 0.01) bonus = 0.01;
|
||||
// @TODO: Notification.text("+ " + Notification.coins(bonus) + ' ' + window.env.t('streakCoins'));
|
||||
delete this.user._tmp.streakBonus;
|
||||
}
|
||||
},
|
||||
userMp (after, before) {
|
||||
if (after === before) return;
|
||||
if (!this.user.flags.classSelected || this.user.preferences.disableClasses) return;
|
||||
// let mana = after - before;
|
||||
// @TODO: Notification.mp(mana);
|
||||
},
|
||||
userLvl (after, before) {
|
||||
if (after <= before) return;
|
||||
// @TODO: Notification.lvl();
|
||||
this.playSound('Level_Up');
|
||||
if (this.user._tmp && this.user._tmp.drop && this.user._tmp.drop.type === 'Quest') return;
|
||||
if (this.unlockLevels[`${after}`]) return;
|
||||
// @TODO: if (!this.user.preferences.suppressModals.levelUp) this.openModal('levelUp', {controller:'UserCtrl', size:'sm'});
|
||||
},
|
||||
userClassSelect (after) {
|
||||
if (!after) return;
|
||||
// @TODO: this.openModal('chooseClass', {controller:'UserCtrl', keyboard:false, backdrop:'static'});
|
||||
},
|
||||
userNotifications (after) {
|
||||
if (!this.user._wrapped) return;
|
||||
if (this.user.needsCron) return;
|
||||
this.handleUserNotifications(after);
|
||||
},
|
||||
userAchievements () {
|
||||
this.playSound('Achievement_Unlocked');
|
||||
},
|
||||
armoireEmpty (after, before) {
|
||||
if (after === before || after === false) return;
|
||||
// @TODO: this.openModal('armoireEmpty');
|
||||
},
|
||||
questCompleted (after) {
|
||||
if (!after) return;
|
||||
// @TODO: this.openModal('questCompleted', {controller:'InventoryCtrl'});
|
||||
},
|
||||
invitedToQuest (after) {
|
||||
if (after !== true) return;
|
||||
// @TODO: this.openModal('questInvitation', {controller:'PartyCtrl'});
|
||||
},
|
||||
},
|
||||
async mounted () {
|
||||
},
|
||||
methods: {
|
||||
playSound () {
|
||||
// @TODO:
|
||||
},
|
||||
runYesterDailies () {
|
||||
// @TODO: Hopefully we don't need this even we load correctly
|
||||
if (this.isRunningYesterdailies) return;
|
||||
|
||||
// let userLastCron = moment(this.user.lastCron).local();
|
||||
// let userDayStart = moment().startOf('day').add({ hours: this.user.preferences.dayStart });
|
||||
|
||||
if (!this.user.needsCron) return;
|
||||
let dailys = this.user.dailys;
|
||||
|
||||
if (!this.appLoaded) return;
|
||||
|
||||
this.isRunningYesterdailies = true;
|
||||
|
||||
// let yesterDay = moment().subtract('1', 'day').startOf('day').add({ hours: this.user.preferences.dayStart });
|
||||
let yesterDailies = [];
|
||||
dailys.forEach((task) => {
|
||||
if (task && task.group.approval && task.group.approval.requested) return;
|
||||
if (task.completed) return;
|
||||
// @TODO: let shouldDo = Shared.shouldDo(yesterDay, task);
|
||||
let shouldDo = false;
|
||||
|
||||
if (task.yesterDaily && shouldDo) yesterDailies.push(task);
|
||||
});
|
||||
|
||||
if (yesterDailies.length === 0) {
|
||||
// @TODO:
|
||||
// User.runCron().then(function () {
|
||||
// isRunningYesterdailies = false;
|
||||
// handleUserNotifications(this.user);
|
||||
// });
|
||||
return;
|
||||
}
|
||||
|
||||
// @TODO:
|
||||
// let modalScope = this.$new();
|
||||
// modalScope.obj = this.user;
|
||||
// modalScope.taskList = yesterDailies;
|
||||
// modalScope.list = {
|
||||
// showCompleted: false,
|
||||
// type: 'daily',
|
||||
// };
|
||||
// modalScope.processingYesterdailies = true;
|
||||
//
|
||||
// $scope.yesterDailiesModalOpen = true;
|
||||
// $modal.open({
|
||||
// templateUrl: 'modals/yesterDailies.html',
|
||||
// scope: modalScope,
|
||||
// backdrop: 'static',
|
||||
// controller: ['$scope', 'Tasks', 'User', '$rootScope', function ($scope, Tasks, User, $rootScope) {
|
||||
// this.$on('task:scored', function (event, data) {
|
||||
// let task = data.task;
|
||||
// let indexOfTask = _.findIndex($scope.taskList, function (taskInList) {
|
||||
// return taskInList._id === task._id;
|
||||
// });
|
||||
// if (!$scope.taskList[indexOfTask]) return;
|
||||
// $scope.taskList[indexOfTask].group.approval.requested = task.group.approval.requested;
|
||||
// if ($scope.taskList[indexOfTask].group.approval.requested) return;
|
||||
// $scope.taskList[indexOfTask].completed = task.completed;
|
||||
// });
|
||||
//
|
||||
// $scope.ageDailies = function () {
|
||||
// User.runCron()
|
||||
// .then(function () {
|
||||
// isRunningYesterdailies = false;
|
||||
// handleUserNotifications(this.user);
|
||||
// });
|
||||
// };
|
||||
// }],
|
||||
// });
|
||||
},
|
||||
transferGroupNotification (notification) {
|
||||
if (!this.user.groupNotifications) this.user.groupNotifications = [];
|
||||
this.user.groupNotifications.push(notification);
|
||||
},
|
||||
handleUserNotifications (after) {
|
||||
if (!after || after.length === 0) return;
|
||||
|
||||
let notificationsToRead = [];
|
||||
let scoreTaskNotification = [];
|
||||
|
||||
this.user.groupNotifications = []; // Flush group notifictions
|
||||
|
||||
after.forEach((notification) => {
|
||||
if (this.lastShownNotifications.indexOf(notification.id) !== -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Some notifications are not marked read here, so we need to fix this system
|
||||
// to handle notifications differently
|
||||
if (['GROUP_TASK_APPROVED', 'GROUP_TASK_APPROVAL'].indexOf(notification.type) === -1) {
|
||||
this.lastShownNotifications.push(notification.id);
|
||||
if (this.lastShownNotifications.length > 10) {
|
||||
this.lastShownNotifications.splice(0, 9);
|
||||
}
|
||||
}
|
||||
|
||||
let markAsRead = true;
|
||||
// @TODO: Use factory function instead
|
||||
switch (notification.type) {
|
||||
case 'GUILD_PROMPT':
|
||||
if (notification.data.textletiant === -1) {
|
||||
// @TODO: this.openModal('testing');
|
||||
} else {
|
||||
// @TODO: this.openModal('testingletiant');
|
||||
}
|
||||
break;
|
||||
case 'DROPS_ENABLED':
|
||||
// @TODO: this.openModal('dropsEnabled');
|
||||
break;
|
||||
case 'REBIRTH_ENABLED':
|
||||
// @TODO: this.openModal('rebirthEnabled');
|
||||
break;
|
||||
case 'WON_CHALLENGE':
|
||||
// @TODO:
|
||||
// User.sync().then( function() {
|
||||
// Achievement.displayAchievement('wonChallenge');
|
||||
// });
|
||||
break;
|
||||
case 'STREAK_ACHIEVEMENT':
|
||||
// @TODO: Notification.streak(this.user.achievements.streak);
|
||||
this.playSound('Achievement_Unlocked');
|
||||
if (!this.user.preferences.suppressModals.streak) {
|
||||
// @TODO: Achievement.displayAchievement('streak', {size: 'md'});
|
||||
}
|
||||
break;
|
||||
case 'ULTIMATE_GEAR_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('ultimateGear', {size: 'md'});
|
||||
break;
|
||||
case 'REBIRTH_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('rebirth');
|
||||
break;
|
||||
case 'GUILD_JOINED_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('joinedGuild', {size: 'md'});
|
||||
break;
|
||||
case 'CHALLENGE_JOINED_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('joinedChallenge', {size: 'md'});
|
||||
break;
|
||||
case 'INVITED_FRIEND_ACHIEVEMENT':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('invitedFriend', {size: 'md'});
|
||||
break;
|
||||
case 'NEW_CONTRIBUTOR_LEVEL':
|
||||
this.playSound('Achievement_Unlocked');
|
||||
// @TODO: Achievement.displayAchievement('contributor', {size: 'md'});
|
||||
break;
|
||||
case 'CRON':
|
||||
if (notification.data) {
|
||||
// @TODO: if (notification.data.hp) Notification.hp(notification.data.hp, 'hp');
|
||||
// @TODO: if (notification.data.mp) Notification.mp(notification.data.mp);
|
||||
}
|
||||
break;
|
||||
case 'GROUP_TASK_APPROVAL':
|
||||
this.transferGroupNotification(notification);
|
||||
markAsRead = false;
|
||||
break;
|
||||
case 'GROUP_TASK_APPROVED':
|
||||
this.transferGroupNotification(notification);
|
||||
markAsRead = false;
|
||||
break;
|
||||
case 'SCORED_TASK':
|
||||
// Search if it is a read notification
|
||||
for (let i = 0; i < this.alreadyReadNotification.length; i++) {
|
||||
if (this.alreadyReadNotification[i] === notification.id) {
|
||||
markAsRead = false; // Do not let it be read again
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only process the notification if it is an unread notification
|
||||
if (markAsRead) {
|
||||
scoreTaskNotification.push(notification);
|
||||
|
||||
// Add to array of read notifications
|
||||
this.alreadyReadNotification.push(notification.id);
|
||||
}
|
||||
break;
|
||||
case 'LOGIN_INCENTIVE':
|
||||
// @TODO: Notification.showLoginIncentive(this.user, notification.data, Social.loadWidgets);
|
||||
break;
|
||||
default:
|
||||
if (notification.data.headerText && notification.data.bodyText) {
|
||||
// @TODO:
|
||||
// let modalScope = this.$new();
|
||||
// modalScope.data = notification.data;
|
||||
// this.openModal('generic', {scope: modalScope});
|
||||
} else {
|
||||
markAsRead = false; // If the notification is not implemented, skip it
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (markAsRead) notificationsToRead.push(notification.id);
|
||||
});
|
||||
|
||||
let userReadNotifsPromise = false;
|
||||
// @TODO: User.readNotifications(notificationsToRead);
|
||||
|
||||
if (userReadNotifsPromise) {
|
||||
userReadNotifsPromise.then(() => {
|
||||
// Only run this code for scoring approved tasks
|
||||
if (scoreTaskNotification.length > 0) {
|
||||
let approvedTasks = [];
|
||||
for (let i = 0; i < scoreTaskNotification.length; i++) {
|
||||
// Array with all approved tasks
|
||||
approvedTasks.push({
|
||||
params: {
|
||||
task: scoreTaskNotification[i].data.scoreTask,
|
||||
direction: 'up',
|
||||
},
|
||||
});
|
||||
|
||||
// Show notification of task approved
|
||||
// @TODO: Notification.markdown(scoreTaskNotification[i].data.message);
|
||||
}
|
||||
|
||||
// Score approved tasks
|
||||
// TODO: User.bulkScore(approvedTasks);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.user.notifications = []; // reset the notifications
|
||||
},
|
||||
// @TODO: I think I have these handled in the http interceptor
|
||||
// this.$on('responseError500', function(ev, error){
|
||||
// Notification.error(error);
|
||||
// });
|
||||
// this.$on('responseError', function(ev, error){
|
||||
// Notification.error(error, true);
|
||||
// });
|
||||
// this.$on('responseText', function(ev, error){
|
||||
// Notification.text(error);
|
||||
// });
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user