From a8b58815b4d6eb631519d665a261510a49543859 Mon Sep 17 00:00:00 2001 From: negue Date: Fri, 28 May 2021 23:11:43 +0200 Subject: [PATCH] Update Party / Group Sidebar / Quest states (#12793) * move groups/sidebar to groupSidebar.vue * lint files * extract group/party sidebar to rightSidebar.vue * wip stories with example data * update stories - wip sidebar re-styling * message party / group leader + move items to the menu * update paddings /place for quest section * invite to party / guild * update labels (* Party / Guild ) * guild-background to group-background * correct menu order + missing a label based on the group type * no quest - styles / layout applied * quest owner / not started - styles applied + extracted questActions from questDetailsModal.vue to a mixin * no challenge style * hover with underlines * quest-pending area layout / margins * "Collection Quest/Quest Owner Participating" Styling Done * group sidebar menu with icons / background * remove most participate button styles * fix quest-invite panel * move "Start Quest" + add "Leave Quest" * Not Participating + Boss + Rage Quests restyling * party quest changes - invitedToQuest + button styles + no-items style + view details * fix icons + rage value + colors * fix duplicate key * hide items label if 0 items found + hide pending damage if there is none + sidebar section margin + fix percent calculation 0 => 0% * combine quest abandon / cancel to one call + hide begin if quest has already started + close modal if quest was canceled * remove unused translate string * allow leaving an accepted but inactive quest + disable leave when user is quest leader * update "are you sure" questions - remove "doubleSureAbort" - add "sureLeaveInactive" * sidebar margins + menu icon color * refactored css rules * improve some styles * fix button spacing * fix dropmenu with icon hover * hide leave quest for leaders + fix quest buttons spacing * add pending items label * remove "X items found" label * first round of fixes * last v-once * Update Quest Dialogs (#13112) * new quest rewards panel + extract questPopover and itemWithLabel * WIP: questInfo still not applying the row-height.. * split up start-quest-modal into select and detail modal - also rename the current quest-details to be the group-quest-details modal * remove start-quest-modal from modal-scss * update package-lock * WIP before using the quest sidebar branch as a base * move quest detail actions to the "new" details dialog * quest details layout for owner / participant * fix quest rewards - open details modal from sidebar * apply quest-details dialog styles to the buyQuestModal one * fix quest reward icons / popover / texts * WIP back to quest selection * fix lint * merge selectQuestModal.vue with questDetailModal.vue + UI for the select quest * fix margins / layout / labels * fix quest detail + wip invitationListModal.vue / participantListModal.vue * fix questmodal user label centered * fix centered reward items + grouping items and adding a count-badge * sort quests by AZ or quantity * invitations modal * remove console.info * complete participantListModal.vue + extracted getClassName * missed a file for getClassName extraction * fix invitations * select the actual quest on details * fix margins on invite to party / start quest buttons * replace buyQuestModal close button and title * fix recursion due to the same name * missing import * sort quantity by highest first * fix "Can't find a Quest to start" styles * fix "your balance" padding * fix quest collections / drop items * fix member details in participants list * fix quest info * remove nullable because the build doesn't like it (on this file..) * add questCompleted to the stories + fix getDropName * replace quest-rewards in questCompleted.vue * fix questCompleted.vue style * delete obsolete components * add missing spritesheets to storebook * requested pr changes * refactored fetchMember * revert optional chaining * fix merge conflicts * fix rightSidebar hover colors - $scss var to css var * overflow auto instead of scroll * prevent wrapping of quest collections * rollback to multi line quest items * use min-width for the quest popover --- .../POST-groups_groupid_quests_leave.test.js | 46 +- website/client/config/storybook/config.js | 28 +- website/client/config/storybook/margin.css | 11 +- website/client/config/storybook/mock.data.js | 9 + website/client/src/assets/scss/dropdown.scss | 21 +- website/client/src/assets/scss/icon.scss | 11 + website/client/src/assets/scss/item.scss | 2 +- website/client/src/assets/scss/modal.scss | 82 --- .../src/assets/svg/health_no_padding.svg | 21 + website/client/src/assets/svg/leave.svg | 3 + website/client/src/assets/svg/level.svg | 1 + .../client/src/assets/svg/navigation_back.svg | 14 + website/client/src/assets/svg/rage.svg | 38 +- .../client/src/assets/svg/sparklesIcon.svg | 3 + website/client/src/assets/svg/users.svg | 20 + .../achievements/questCompleted.vue | 23 +- .../components/challenges/groupChallenges.vue | 26 +- .../src/components/group-plans/billing.vue | 2 +- .../src/components/groups/discovery.vue | 2 +- .../src/components/groups/group.stories.js | 362 +++++++++++ .../components/groups/group.stories.utils.js | 342 ++++++++++ .../client/src/components/groups/group.vue | 153 +---- .../groups/{sidebar.vue => groupSidebar.vue} | 0 .../components/groups/invitationListModal.vue | 273 ++++++++ .../client/src/components/groups/myGuilds.vue | 2 +- .../groups/participantListModal.vue | 62 +- .../components/groups/quest-dialog.stories.js | 89 +++ .../components/groups/questActions.mixin.js | 72 +++ .../components/groups/questDetailModal.vue | 450 +++++++++++++ .../components/groups/questDetailsModal.vue | 287 --------- .../components/groups/questSidebarSection.vue | 603 +++++++++++++----- .../src/components/groups/rightSidebar.vue | 240 +++++++ .../src/components/groups/startQuestModal.vue | 242 ------- .../inventory/equipment/equipGearModal.vue | 7 +- .../src/components/inventory/items/index.vue | 12 +- .../src/components/memberDetails.stories.js | 34 + .../src/components/memberDetailsNew.vue | 330 ++++++++++ .../src/components/members/classBadge.vue | 19 +- .../components/members/inlineClassBadge.vue | 44 ++ .../components/payments/selectUserModal.vue | 4 +- .../{sidebarButton.vue => sectionButton.vue} | 32 +- .../src/components/shops/itemWithLabel.vue | 221 +++++++ .../shops/market/equipmentSection.vue | 6 +- .../components/shops/quests/buyQuestModal.vue | 53 +- .../src/components/shops/quests/index.vue | 41 +- .../shops/quests/quest-dialog.stories.js | 78 +++ .../shops/quests/quest-helper.mixin.js | 56 ++ .../shops/quests/questDialogContent.vue | 64 +- .../shops/quests/questDialogDrops.vue | 159 ----- .../src/components/shops/quests/questInfo.vue | 110 ++-- .../components/shops/quests/questPopover.vue | 70 ++ .../components/shops/quests/questRewards.vue | 213 +++++++ .../src/components/shops/seasonal/index.vue | 6 +- .../client/src/components/sidebarSection.vue | 44 +- .../modal-controls/selectMulti.stories.js | 9 - .../client/src/components/ui/countBadge.vue | 2 +- website/client/src/components/ui/statsbar.vue | 17 +- website/client/src/components/userLabel.vue | 4 + website/client/src/components/userLink.vue | 34 +- .../src/components/userMenu/profile.vue | 5 +- website/client/src/store/actions/members.js | 13 +- website/common/locales/en/groups.json | 13 +- website/common/locales/en/npc.json | 1 + website/common/locales/en/quests.json | 28 +- .../script/content/gear/sets/special/index.js | 7 +- website/common/script/libs/getClassName.js | 3 + website/common/script/libs/percent.js | 4 +- website/common/script/libs/shops.js | 10 +- website/server/controllers/api-v3/quests.js | 1 - 69 files changed, 3967 insertions(+), 1327 deletions(-) create mode 100644 website/client/src/assets/svg/health_no_padding.svg create mode 100644 website/client/src/assets/svg/leave.svg create mode 100644 website/client/src/assets/svg/level.svg create mode 100644 website/client/src/assets/svg/navigation_back.svg create mode 100644 website/client/src/assets/svg/sparklesIcon.svg create mode 100644 website/client/src/assets/svg/users.svg create mode 100644 website/client/src/components/groups/group.stories.js create mode 100644 website/client/src/components/groups/group.stories.utils.js rename website/client/src/components/groups/{sidebar.vue => groupSidebar.vue} (100%) create mode 100644 website/client/src/components/groups/invitationListModal.vue create mode 100644 website/client/src/components/groups/quest-dialog.stories.js create mode 100644 website/client/src/components/groups/questActions.mixin.js create mode 100644 website/client/src/components/groups/questDetailModal.vue delete mode 100644 website/client/src/components/groups/questDetailsModal.vue create mode 100644 website/client/src/components/groups/rightSidebar.vue delete mode 100644 website/client/src/components/groups/startQuestModal.vue create mode 100644 website/client/src/components/memberDetails.stories.js create mode 100644 website/client/src/components/memberDetailsNew.vue create mode 100644 website/client/src/components/members/inlineClassBadge.vue rename website/client/src/components/{sidebarButton.vue => sectionButton.vue} (56%) create mode 100644 website/client/src/components/shops/itemWithLabel.vue create mode 100644 website/client/src/components/shops/quests/quest-dialog.stories.js create mode 100644 website/client/src/components/shops/quests/quest-helper.mixin.js delete mode 100644 website/client/src/components/shops/quests/questDialogDrops.vue create mode 100644 website/client/src/components/shops/quests/questPopover.vue create mode 100644 website/client/src/components/shops/quests/questRewards.vue create mode 100644 website/common/script/libs/getClassName.js diff --git a/test/api/v3/integration/quests/POST-groups_groupid_quests_leave.test.js b/test/api/v3/integration/quests/POST-groups_groupid_quests_leave.test.js index d8e6e9c70b..1e2f7d6983 100644 --- a/test/api/v3/integration/quests/POST-groups_groupid_quests_leave.test.js +++ b/test/api/v3/integration/quests/POST-groups_groupid_quests_leave.test.js @@ -61,15 +61,6 @@ describe('POST /groups/:groupId/quests/leave', () => { }); }); - it('returns an error when quest is not active', async () => { - await expect(partyMembers[0].post(`/groups/${questingGroup._id}/quests/leave`)) - .to.eventually.be.rejected.and.eql({ - code: 404, - error: 'NotFound', - message: t('noActiveQuestToLeave'), - }); - }); - it('returns an error when quest leader attempts to leave', async () => { await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`); await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`); @@ -97,18 +88,14 @@ describe('POST /groups/:groupId/quests/leave', () => { }); }); - it('leaves a quest', async () => { - await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`); - await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`); - await partyMembers[1].post(`/groups/${questingGroup._id}/quests/accept`); - - const leaveResult = await partyMembers[0].post(`/groups/${questingGroup._id}/quests/leave`); + async function letPartyMemberLeaveAndCheckChanges (partyMember) { + const leaveResult = await partyMember.post(`/groups/${questingGroup._id}/quests/leave`); await Promise.all([ - partyMembers[0].sync(), + partyMember.sync(), questingGroup.sync(), ]); - expect(partyMembers[0].party.quest).to.eql({ + expect(partyMember.party.quest).to.eql({ key: null, progress: { up: 0, @@ -120,6 +107,29 @@ describe('POST /groups/:groupId/quests/leave', () => { RSVPNeeded: false, }); expect(questingGroup.quest).to.deep.equal(leaveResult); - expect(questingGroup.quest.members[partyMembers[0]._id]).to.be.false; + expect(questingGroup.quest.members[partyMember._id]).to.be.false; + } + + it('leaves an active quest', async () => { + await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`); + await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`); + await partyMembers[1].post(`/groups/${questingGroup._id}/quests/accept`); + + await questingGroup.sync(); + + expect(questingGroup.quest.active).to.eql(true); + + await letPartyMemberLeaveAndCheckChanges(partyMembers[0]); + }); + + it('leaves an inactive quest ', async () => { + await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`); + await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`); + + await questingGroup.sync(); + + expect(questingGroup.quest.active).to.eql(false); + + await letPartyMemberLeaveAndCheckChanges(partyMembers[0]); }); }); diff --git a/website/client/config/storybook/config.js b/website/client/config/storybook/config.js index f7eca53d5d..a5761b4580 100644 --- a/website/client/config/storybook/config.js +++ b/website/client/config/storybook/config.js @@ -31,19 +31,45 @@ import '../../src/assets/css/sprites/spritesmith-main-23.css'; import '../../src/assets/css/sprites/spritesmith-main-24.css'; import '../../src/assets/css/sprites/spritesmith-main-25.css'; import '../../src/assets/css/sprites/spritesmith-main-26.css'; +import '../../src/assets/css/sprites/spritesmith-main-27.css'; +import '../../src/assets/css/sprites/spritesmith-main-28.css'; +import '../../src/assets/css/sprites/spritesmith-main-29.css'; import Vue from 'vue'; import BootstrapVue from 'bootstrap-vue'; import StoreModule from '@/libs/store'; +import getStore from '@/store'; + +import i18n from '../../../common/script/i18n'; // couldn't inject the languages easily, // so just a "$t()" string to show that this will be translated -Vue.prototype.$t = function translateString (...args) { +i18n.t = function translateString (...args) { return `$t(${JSON.stringify(args)})`; }; +Vue.prototype.$t = i18n.t; Vue.use(BootstrapVue); Vue.use(StoreModule); +const store = getStore(); +store.state.user.data = { + stats: {}, + tags: [], + items: { + quests: { + moon1: 3, + }, + }, + party: { + quest: { + + }, + }, +}; + +Vue.prototype.$store = store; + + const req = require.context('../../src', true, /.stories.js$/); function loadStories () { diff --git a/website/client/config/storybook/margin.css b/website/client/config/storybook/margin.css index eaad293c27..53a5938870 100644 --- a/website/client/config/storybook/margin.css +++ b/website/client/config/storybook/margin.css @@ -3,11 +3,12 @@ display: inline-block; } -.content { - color: white; - background: grey; -} - .inline-block { display: inline-block; } + +.component-showcase { + position: absolute; + margin: 20px; + width: calc(100% - 40px); +} diff --git a/website/client/config/storybook/mock.data.js b/website/client/config/storybook/mock.data.js index 543793e84d..0d9a57a8b2 100644 --- a/website/client/config/storybook/mock.data.js +++ b/website/client/config/storybook/mock.data.js @@ -1,3 +1,5 @@ +import { v4 as generateUUID } from 'uuid'; + export const userStyles = { contributor: { admin: true, @@ -72,4 +74,11 @@ export const userStyles = { maxHealth: 50, maxMP: 158, }, + profile: { + name: 'user', + }, + _id: generateUUID(), + flags: { + classSelected: true, + }, }; diff --git a/website/client/src/assets/scss/dropdown.scss b/website/client/src/assets/scss/dropdown.scss index 6eb060003a..f2e027bca2 100644 --- a/website/client/src/assets/scss/dropdown.scss +++ b/website/client/src/assets/scss/dropdown.scss @@ -39,6 +39,7 @@ // shared dropdown-item styles .dropdown-item { // header items & not selectList-items + padding-left: 24px; padding-top: 8px; padding-bottom: 8px; @@ -53,14 +54,13 @@ background-color: inherit; } - &:active, &:hover, &:focus, &.active { background-color: inherit !important; - color: $purple-300 !important; + color: var(--hover-color, $purple-300) !important; } &:hover { - background-color: rgba($purple-600, 0.25) !important; + background-color: var(--hover-background, rgba($purple-600, 0.25)) !important; } &.dropdown-inactive { @@ -71,6 +71,21 @@ color: inherit !important; } } + + .with-icon { + display: flex; + align-items: center; + + .svg-icon { + margin: 0 0.5rem 0 0; + } + } + + &:not(:hover) { + .with-icon .svg-icon { + color: $gray-200; + } + } } .dropdown + .dropdown { diff --git a/website/client/src/assets/scss/icon.scss b/website/client/src/assets/scss/icon.scss index 1b409ca4df..92930f1124 100644 --- a/website/client/src/assets/scss/icon.scss +++ b/website/client/src/assets/scss/icon.scss @@ -16,6 +16,12 @@ fill: currentColor; } } + + &.color-stroke { + svg path { + stroke: currentColor; + } + } } .icon-16 { @@ -33,6 +39,11 @@ height: 24px; } +.icon-48 { + width: 48px; + height: 48px; +} + .icon-10 { width: 10px; height: 10px; diff --git a/website/client/src/assets/scss/item.scss b/website/client/src/assets/scss/item.scss index ffe1ae5807..ab52d935d1 100644 --- a/website/client/src/assets/scss/item.scss +++ b/website/client/src/assets/scss/item.scss @@ -107,5 +107,5 @@ } .questPopover { - width: 200px; + min-width: 200px; } diff --git a/website/client/src/assets/scss/modal.scss b/website/client/src/assets/scss/modal.scss index b9d1d51e27..1c88d6a775 100644 --- a/website/client/src/assets/scss/modal.scss +++ b/website/client/src/assets/scss/modal.scss @@ -41,88 +41,6 @@ } } -#start-quest-modal, #buy-quest-modal { - @media only screen and (max-width: 1200px) { - .modal-dialog { - max-width: 33%; - - .left-panel { - left: initial; - width: 100%; - right: 100%; - - .col-4 { - width: 100px; - } - } - - .side-panel, .right-sidebar { - left: calc(100% - 10px); - max-width: 100%; - right: initial; - - .questRewards { - width: 90%; - - .reward-item { - width: 100%; - } - } - } - } - } - - @media only screen and (max-width: 1000px) { - .modal-dialog { - max-width: 80%; - width: 80% !important; - - .modal-body { - flex-direction: column; - display: flex; - - div:nth-child(1) { order: 3; } - div:nth-child(2) { order: 1; } - div:nth-child(3) { order: 4; } - div:nth-child(4) { order: 5; } - div:nth-child(5) { order: 2; } - - .left-panel { - border-radius: 8px; - position: static; - right: initial; - margin: 20px 0; - height: auto; - width: 100%; - z-index: 0; - order: 3; - - .col-4 { - max-width: 100px; - } - } - - .side-panel, .right-sidebar { - margin: 20px 0 0 0; - position: static; - box-shadow: none; - height: auto; - width: 100%; - z-index: 0; - order: 2; - left: 0; - - .questRewards { - padding: 0 2em 2em 2em; - width: 100%; - z-index: 0; - } - } - } - } - } -} - #subscription-cancel-modal, #subscription-canceled-modal { .modal-content { background: transparent; diff --git a/website/client/src/assets/svg/health_no_padding.svg b/website/client/src/assets/svg/health_no_padding.svg new file mode 100644 index 0000000000..6507c06438 --- /dev/null +++ b/website/client/src/assets/svg/health_no_padding.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/website/client/src/assets/svg/leave.svg b/website/client/src/assets/svg/leave.svg new file mode 100644 index 0000000000..bf502a7c4d --- /dev/null +++ b/website/client/src/assets/svg/leave.svg @@ -0,0 +1,3 @@ + + + diff --git a/website/client/src/assets/svg/level.svg b/website/client/src/assets/svg/level.svg new file mode 100644 index 0000000000..325437ce95 --- /dev/null +++ b/website/client/src/assets/svg/level.svg @@ -0,0 +1 @@ + diff --git a/website/client/src/assets/svg/navigation_back.svg b/website/client/src/assets/svg/navigation_back.svg new file mode 100644 index 0000000000..1d29645b04 --- /dev/null +++ b/website/client/src/assets/svg/navigation_back.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/website/client/src/assets/svg/rage.svg b/website/client/src/assets/svg/rage.svg index d215fe223c..216b66e458 100644 --- a/website/client/src/assets/svg/rage.svg +++ b/website/client/src/assets/svg/rage.svg @@ -1,18 +1,26 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/client/src/assets/svg/sparklesIcon.svg b/website/client/src/assets/svg/sparklesIcon.svg new file mode 100644 index 0000000000..eae0e27fb2 --- /dev/null +++ b/website/client/src/assets/svg/sparklesIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/website/client/src/assets/svg/users.svg b/website/client/src/assets/svg/users.svg new file mode 100644 index 0000000000..ca1d736b16 --- /dev/null +++ b/website/client/src/assets/svg/users.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/website/client/src/components/achievements/questCompleted.vue b/website/client/src/components/achievements/questCompleted.vue index 2a709a58c7..90c68775d0 100644 --- a/website/client/src/components/achievements/questCompleted.vue +++ b/website/client/src/components/achievements/questCompleted.vue @@ -18,11 +18,11 @@ v-if="questData.completion && typeof questData.completion === 'function'" v-html="questData.completion()" >

-
+

{{ $t('paymentYouReceived') }}

- +
@@ -343,7 +343,7 @@ import FilterSidebar from '@/components/ui/filterSidebar'; import cardsModal from './cards-modal'; import HatchedPetDialog from '../stable/hatchedPetDialog'; -import startQuestModal from '../../groups/startQuestModal'; +import questDetailModal from '../../groups/questDetailModal'; import QuestInfo from '../../shops/quests/questInfo.vue'; import { mapState } from '@/libs/store'; @@ -384,7 +384,7 @@ export default { ItemRows, HatchedPetDialog, CountBadge, - startQuestModal, + questDetailModal, cardsModal, QuestInfo, FilterSidebar, @@ -632,9 +632,9 @@ export default { this.$root.$emit('selectMembersModal::showItem', item); } } else if (groupKey === 'quests') { - this.$root.$emit('bv::show::modal', 'start-quest-modal'); - - this.$root.$emit('selectQuest', item); + this.$root.$emit('bv::show::modal', 'quest-detail-modal', { + key: item.key, + }); } }, diff --git a/website/client/src/components/memberDetails.stories.js b/website/client/src/components/memberDetails.stories.js new file mode 100644 index 0000000000..44fbf624af --- /dev/null +++ b/website/client/src/components/memberDetails.stories.js @@ -0,0 +1,34 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { storiesOf } from '@storybook/vue'; + +import MemberDetails from './memberDetails.vue'; +import MemberDetailsNew from './memberDetailsNew.vue'; +import { userStyles } from '../../config/storybook/mock.data'; + +storiesOf('Member Details', module) + .add('party header (old)', () => ({ + components: { MemberDetails }, + template: ` +
+ +
+ `, + data () { + return { + user: userStyles, + }; + }, + })) + .add('quest participants (new)', () => ({ + components: { MemberDetailsNew }, + template: ` +
+ +
+ `, + data () { + return { + user: userStyles, + }; + }, + })); diff --git a/website/client/src/components/memberDetailsNew.vue b/website/client/src/components/memberDetailsNew.vue new file mode 100644 index 0000000000..0d6548c8b1 --- /dev/null +++ b/website/client/src/components/memberDetailsNew.vue @@ -0,0 +1,330 @@ + + + + + diff --git a/website/client/src/components/members/classBadge.vue b/website/client/src/components/members/classBadge.vue index b6ce43d7d7..2a01e05189 100644 --- a/website/client/src/components/members/classBadge.vue +++ b/website/client/src/components/members/classBadge.vue @@ -1,5 +1,6 @@