From 36a933d0c462bf348d8bca1efd426ae88890c33f Mon Sep 17 00:00:00 2001 From: Keith Holliday Date: Tue, 5 Sep 2017 12:34:00 -0600 Subject: [PATCH] Client fixed sept 4 (#9019) * Fixed background purchasing * Added challenge export * Fixed is leader filter * Fixed staff icon * Add block to profile modal * Added initial send gems modal * Added modal stack * Fixed lint issues * Updated notification styles * Updated level up styles * Fixed many achievement styles * Fixed notification navigate to same route with different param * Added mark chat seen and remove new messages * Added scroll to notifications * Updated hall loading --- website/client/app.vue | 36 +++++ .../achievements/achievementAvatar.vue | 2 +- .../achievements/achievementFooter.vue | 67 ++++++++- .../components/achievements/contributor.vue | 8 +- .../client/components/achievements/death.vue | 40 ++--- .../components/achievements/invitedFriend.vue | 19 ++- .../achievements/joinedChallenge.vue | 19 ++- .../components/achievements/joinedGuild.vue | 19 ++- .../components/achievements/levelUp.vue | 108 ++++++++++---- .../components/achievements/lowHealth.vue | 9 +- .../achievements/questCompleted.vue | 2 - .../achievements/questInvitation.vue | 2 - .../components/achievements/rebirth.vue | 29 ++-- .../client/components/achievements/streak.vue | 35 +++-- .../components/achievements/ultimateGear.vue | 61 ++++---- .../components/achievements/wonChallenge.vue | 7 +- website/client/components/appFooter.vue | 2 +- .../components/challenges/challengeDetail.vue | 8 + .../client/components/chat/chatMessages.vue | 4 +- website/client/components/creatorIntro.vue | 10 +- website/client/components/groups/group.vue | 38 +++-- website/client/components/hall/heroes.vue | 141 +++++++++--------- .../client/components/notificationMenu.vue | 22 ++- .../components/payments/sendGemsModal.vue | 105 +++++++++++++ website/client/components/shops/buyModal.vue | 3 +- .../components/snackbars/notification.vue | 6 +- .../client/components/userMenu/profile.vue | 27 ++++ website/client/mixins/groupsUtilities.js | 2 +- website/client/store/actions/chat.js | 2 +- website/client/store/index.js | 1 + website/common/locales/en/achievements.json | 6 + website/common/locales/en/challenge.json | 3 +- website/common/locales/en/subscriber.json | 1 + 33 files changed, 606 insertions(+), 238 deletions(-) create mode 100644 website/client/components/payments/sendGemsModal.vue create mode 100644 website/common/locales/en/achievements.json diff --git a/website/client/app.vue b/website/client/app.vue index e191bc580b..b16ff2beab 100644 --- a/website/client/app.vue +++ b/website/client/app.vue @@ -162,6 +162,42 @@ export default { console.error('Impossible to fetch user. Clean up localStorage and refresh.', err); // eslint-disable-line no-console }); } + + // Manage modals + this.$root.$on('show::modal', (modalId, data) => { + if (data && data.fromRoot) return; + + // Get last modal on stack and hide + let modalStackLength = this.$store.state.modalStack.length; + let modalOnTop = this.$store.state.modalStack[modalStackLength - 1]; + + // Add new modal to the stack + this.$store.state.modalStack.push(modalId); + + // Hide the previous top modal + if (modalOnTop) this.$root.$emit('hide::modal', modalOnTop, {fromRoot: true}); + }); + + // @TODO: This part is hacky and could be solved with two options: + // 1 - Find a way to pass fromRoot to hidden + // 2 - Enforce that all modals use the hide::modal event + this.$root.$on('hidden::modal', (modalId) => { + let modalStackLength = this.$store.state.modalStack.length; + let modalOnTop = this.$store.state.modalStack[modalStackLength - 1]; + let modalSecondToTop = this.$store.state.modalStack[modalStackLength - 2]; + // Don't remove modal if hid was called from main app + // @TODO: I'd reather use this, but I don't know how to pass data to hidden event + // if (data && data.fromRoot) return; + if (modalId === modalSecondToTop) return; + + // Remove modal from stack + this.$store.state.modalStack.pop(); + + // Recalculate and show the last modal if there is one + modalStackLength = this.$store.state.modalStack.length; + modalOnTop = this.$store.state.modalStack[modalStackLength - 1]; + if (modalOnTop) this.$root.$emit('show::modal', modalOnTop, {fromRoot: true}); + }); }, methods: { resetItemToBuy ($event) { diff --git a/website/client/components/achievements/achievementAvatar.vue b/website/client/components/achievements/achievementAvatar.vue index e2503c4abf..ccbfdc17e5 100644 --- a/website/client/components/achievements/achievementAvatar.vue +++ b/website/client/components/achievements/achievementAvatar.vue @@ -1,7 +1,7 @@ diff --git a/website/client/components/chat/chatMessages.vue b/website/client/components/chat/chatMessages.vue index e4b915ccf6..a29a73f808 100644 --- a/website/client/components/chat/chatMessages.vue +++ b/website/client/components/chat/chatMessages.vue @@ -203,8 +203,8 @@ import tier5 from 'assets/svg/tier-5.svg'; import tier6 from 'assets/svg/tier-6.svg'; import tier7 from 'assets/svg/tier-7.svg'; import tier8 from 'assets/svg/tier-mod.svg'; -import tier9 from 'assets/svg/tier-npc.svg'; -import tier10 from 'assets/svg/tier-staff.svg'; +import tier9 from 'assets/svg/tier-staff.svg'; +import tier10 from 'assets/svg/tier-npc.svg'; export default { props: ['chat', 'groupId', 'groupName', 'inbox'], diff --git a/website/client/components/creatorIntro.vue b/website/client/components/creatorIntro.vue index 937c22ca75..c75015675d 100644 --- a/website/client/components/creatorIntro.vue +++ b/website/client/components/creatorIntro.vue @@ -176,7 +176,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru strong {{backgroundShopSets[0].text}} .row.incentive-background-row .col-2(v-for='bg in backgroundShopSets[0].items', - @click='unlock("background." + bg.key)', + @click='buy("background." + bg.key)', :popover-title='bg.text', :popover='bg.notes', popover-trigger='mouseenter') @@ -197,7 +197,7 @@ b-modal#avatar-modal(title="", size='lg', :hide-header='true', :hide-footer='tru strong {{set.text}} .col-12(v-if='showPlainBackgroundBlurb(set.identifier, set.items)') {{ $t('incentiveBackgroundsUnlockedWithCheckins') }} .col-4.text-center.customize-option.background-button(v-for='bg in set.items', - @click='backgroundSelected(bg)', + @click='!user.purchased.background[bg.key] ? backgroundSelected(bg) : unlock("background." + bg.key)', :popover-title='bg.text', :popover='bg.notes', popover-trigger='mouseenter') @@ -868,6 +868,9 @@ export default { }, mounted () { if (this.editing) this.modalPage = 2; + + // Buy modal is global, so we listen at root. I'd like to not + this.$root.$on('buyModal::boughtItem', this.backgroundPurchased); }, data () { let backgroundShopSets = getBackgroundShopSets(); @@ -1066,6 +1069,9 @@ export default { backgroundSelected (bg) { this.$root.$emit('buyModal::showItem', bg); }, + backgroundPurchased () { + this.backgroundUpdate = new Date(); + }, }, }; diff --git a/website/client/components/groups/group.vue b/website/client/components/groups/group.vue index 1498850597..51436843d4 100644 --- a/website/client/components/groups/group.vue +++ b/website/client/components/groups/group.vue @@ -542,20 +542,17 @@ export default { }, }, mounted () { - this.searchId = this.groupId; - if (this.isParty) { - this.searchId = 'party'; - // @TODO: Set up from old client. Decide what we need and what we don't - // Check Desktop notifs - // Mark Chat seen - // Load invites - } - this.fetchGuild(); + if (!this.searchId) this.searchId = this.groupId; - this.$root.$on('updatedGroup', group => { - let updatedGroup = extend(this.group, group); - this.$set(this.group, updatedGroup); - }); + this.load(); + + if (this.user.newMessages[this.searchId]) { + this.$store.dispatch('chat:markChatSeen', {groupId: this.searchId}); + } + }, + beforeRouteUpdate (to, from, next) { + this.searchId = to.params.groupId; + next(); }, watch: { // call again the method if the route changes (when this route is already active) @@ -570,6 +567,21 @@ export default { }, }, methods: { + load () { + if (this.isParty) { + this.searchId = 'party'; + // @TODO: Set up from old client. Decide what we need and what we don't + // Check Desktop notifs + // Mark Chat seen + // Load invites + } + this.fetchGuild(); + + this.$root.$on('updatedGroup', group => { + let updatedGroup = extend(this.group, group); + this.$set(this.group, updatedGroup); + }); + }, // @TODO: abstract autocomplete // https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a getCoord (e, text) { diff --git a/website/client/components/hall/heroes.vue b/website/client/components/hall/heroes.vue index 9b8a17b4fa..2ec6ca91b0 100644 --- a/website/client/components/hall/heroes.vue +++ b/website/client/components/hall/heroes.vue @@ -1,69 +1,73 @@ diff --git a/website/client/components/shops/buyModal.vue b/website/client/components/shops/buyModal.vue index 7b027c0112..73c1272a8e 100644 --- a/website/client/components/shops/buyModal.vue +++ b/website/client/components/shops/buyModal.vue @@ -66,9 +66,8 @@ :currencyNeeded="getPriceClass()", :amountNeeded="item.value" ).float-right - - + diff --git a/website/client/mixins/groupsUtilities.js b/website/client/mixins/groupsUtilities.js index 291daa68e0..52645c932c 100644 --- a/website/client/mixins/groupsUtilities.js +++ b/website/client/mixins/groupsUtilities.js @@ -19,7 +19,7 @@ export default { return false; }, isLeaderOfGroup (user, group) { - return user._id === group.leader._id; + return user._id === group.leader || user._id === group.leader._id; }, filterGuild (group, filters, search, user) { let passedSearch = true; diff --git a/website/client/store/actions/chat.js b/website/client/store/actions/chat.js index 0d6bffaf42..6ae075903f 100644 --- a/website/client/store/actions/chat.js +++ b/website/client/store/actions/chat.js @@ -52,7 +52,7 @@ export async function clearFlagCount (store, payload) { } export async function markChatSeen (store, payload) { - if (store.user.newMessages) delete store.user.newMessages[payload.groupId]; + if (store.state.user.newMessages) delete store.state.user.newMessages[payload.groupId]; let url = `/api/v3/groups/${payload.groupId}/chat/seen`; let response = await axios.post(url); return response.data.data; diff --git a/website/client/store/index.js b/website/client/store/index.js index 52353e05f4..d50b778247 100644 --- a/website/client/store/index.js +++ b/website/client/store/index.js @@ -104,6 +104,7 @@ export default function () { profileUser: {}, upgradingGroup: {}, notificationStore: [], + modalStack: [], }, }); diff --git a/website/common/locales/en/achievements.json b/website/common/locales/en/achievements.json new file mode 100644 index 0000000000..c986f2bd4f --- /dev/null +++ b/website/common/locales/en/achievements.json @@ -0,0 +1,6 @@ +{ + "share": "Share", + "onwards": "Onwards!", + "levelup": "By accomplishing your real life goals, you leveled up and are now fully healed!", + "reachedLevel": "You Reached Level <%= level %>" +} diff --git a/website/common/locales/en/challenge.json b/website/common/locales/en/challenge.json index 97baf5d357..f259dd1771 100644 --- a/website/common/locales/en/challenge.json +++ b/website/common/locales/en/challenge.json @@ -114,5 +114,6 @@ "shortNamePlaceholder": "What short tag should be used to identify your Challenge?", "updateChallenge": "Update Challenge", "haveNoChallenges": "You don't have any Challenges", - "loadMore": "Load More" + "loadMore": "Load More", + "exportChallengeCsv": "Export Challenge" } diff --git a/website/common/locales/en/subscriber.json b/website/common/locales/en/subscriber.json index 63a3f7eec5..d348823489 100644 --- a/website/common/locales/en/subscriber.json +++ b/website/common/locales/en/subscriber.json @@ -2,6 +2,7 @@ "subscription": "Subscription", "subscriptions": "Subscriptions", "subDescription": "Buy Gems with gold, get monthly mystery items, retain progress history, double daily drop-caps, support the devs. Click for more info.", + "sendGems": "Send Gems", "buyGemsGold": "Buy Gems with Gold", "buyGemsGoldText": "Alexander the Merchant will sell you Gems at a cost of 20 Gold per Gem. His monthly shipments are initially capped at 25 Gems per month, but for every 3 consecutive months that you are subscribed, this cap increases by 5 Gems, up to a maximum of 50 Gems per month!", "mustSubscribeToPurchaseGems": "Must subscribe to purchase gems with GP",