From db9975002af9388557f19ff854618148afdfdc3b Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 25 Sep 2023 15:34:12 +0200 Subject: [PATCH 1/6] fix(settings-plans-billing): do not poll the active plan, just refetch it when it changes (#2476) * fix(settings-plans-billing): do not poll the active plan, just refetch it when it changes * fix: do not show note about free plan if not on free plan * refactor: remove branch --------- Co-authored-by: Arsenije Savic --- src/components/dao/settings-plans-billing.vue | 82 +++++++++++++------ src/layouts/DhoSelector.vue | 29 +++---- src/utils/format-plan.js | 10 +++ 3 files changed, 80 insertions(+), 41 deletions(-) create mode 100644 src/utils/format-plan.js diff --git a/src/components/dao/settings-plans-billing.vue b/src/components/dao/settings-plans-billing.vue index e9c674a4c..bba8c9c12 100644 --- a/src/components/dao/settings-plans-billing.vue +++ b/src/components/dao/settings-plans-billing.vue @@ -2,6 +2,7 @@ import { mapGetters } from 'vuex' import gql from 'graphql-tag' import { ORIGIN, PLAN_TYPE, PAYMENT_INTERVAL } from '~/const' +import formatPlan from '~/utils/format-plan' const STATES = Object.freeze({ WAITING: 'WAITING', @@ -22,6 +23,22 @@ const PLANS_QUERY = ` } ` +const ACTIVE_PLAN_QUERY = ` + activePlan(daoUrl: $daoUrl) { + subscriptionId + subscriptionItemId + subscriptionStatus + currency + currentPeriodEnd + currentPeriodStart + coreMembersCount + communityMembersCount + price + id: planId + name: planName + } + ` + export default { name: 'settings-plans-billing', components: { @@ -32,7 +49,7 @@ export default { props: { form: { type: Object, - default: () => {} + default: () => { } }, isAdmin: { @@ -43,14 +60,20 @@ export default { apollo: { _plans: { - query: gql`query PLANS { ${PLANS_QUERY} }`, + query: gql`query PLANS{ ${PLANS_QUERY} }`, update: data => data.getStripePrices, fetchPolicy: 'no-cache' + }, + activePlan: { + variables() { return { daoUrl: this.$route.params.dhoname } }, + query: gql`query activePlan($daoUrl: String!) { ${ACTIVE_PLAN_QUERY} }`, + update: data => formatPlan(data.activePlan), + fetchPolicy: 'no-cache' } }, - data () { + data() { return { STATES, state: STATES.WAITING, @@ -64,7 +87,7 @@ export default { }, methods: { - async _createCheckoutSession (id) { + async _createCheckoutSession(id) { this.state = STATES.CREATING_SESSION const res = await this.$apollo.mutate({ @@ -108,7 +131,7 @@ export default { } }, - async _updateSubscription (id) { + async _updateSubscription(id) { this.state = STATES.CREATING_SESSION const res = await this.$apollo.mutate({ @@ -139,16 +162,17 @@ export default { if (res) { this.state = STATES.WAITING + this.$apollo.queries.activePlan.refetch() } }, - onPlanDialogClose () { + onPlanDialogClose() { this.state = STATES.WAITING this.planType = PLAN_TYPE.SAAS this.paymentInterval = PAYMENT_INTERVAL.YEAR }, - switchPlanType () { + switchPlanType() { if (this.planType === PLAN_TYPE.SAAS) { this.planType = PLAN_TYPE.EAAS this.paymentInterval = null @@ -158,16 +182,20 @@ export default { } }, - formatMoney (amount) { return amount ? new Intl.NumberFormat().format(parseInt(amount), { style: 'currency' }) : 0 } + formatMoney(amount) { return amount ? new Intl.NumberFormat().format(parseInt(amount), { style: 'currency' }) : 0 } }, computed: { ...mapGetters('dao', ['daoSettings', 'selectedDao', 'selectedDaoPlan']), - isFreePlan () { return !this.selectedDaoPlan.id }, - isPlanModalOpen () { return [STATES.UPDATING_PLAIN, STATES.CREATING_SESSION].includes(this.state) }, + isFreePlan() { return !this.selectedDaoPlan?.id }, + isPlanModalOpen() { return [STATES.UPDATING_PLAIN, STATES.CREATING_SESSION].includes(this.state) }, - plans () { + currentPlan() { + return this.activePlan?.id ? this.activePlan : this.selectedDaoPlan + }, + + plans() { return this._plans .map(_ => ({ ..._, @@ -236,7 +264,7 @@ export default { div .text-xl.text-weight-600.text-primary {{ $t(`plans.${plan.name}`) }} p.q-pa-none.q-ma-none.text-3xl.text-primary.text-bold ${{ formatMoney(plan.amountUSD) }} - div(v-if="selectedDaoPlan.id === plan.id") + div(v-if="currentPlan?.id === plan.id") q-chip(dense color="positive" text-color="white") span.text-uppercase.text-xxs.text-bold.q-px-xxs {{ $t(`statuses.active`) }} .hr.q-mt-md.q-mb-xs @@ -254,7 +282,7 @@ export default { nav.q-mt-xl.full-width.row.justify-end q-btn.q-px-xl.rounded-border.text-bold.q-ml-xs( - :disable="selectedDaoPlan.id === plan.id" + :disable="currentPlan?.id === plan.id" :label="$t('configuration.settings-plans-billing.plan.modal.cta')" @click="isFreePlan ? _createCheckoutSession(plan.id) : _updateSubscription(plan.id)" color="secondary" @@ -267,40 +295,40 @@ export default { .row .col-12.col-md-6(:class="{ 'q-pr-sm': $q.screen.gt.md, 'q-mt-md': $q.screen.lt.md }") widget(:title="$t('configuration.settings-plans-billing.plan.title')" titleImage='/svg/paperplane.svg' bar).q-pa-none - p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose.q-mt-sm {{ $t('configuration.settings-plans-billing.plan.description.free') }} + p(v-if="isFreePlan").q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose.q-mt-sm {{ $t('configuration.settings-plans-billing.plan.description.free') }} widget.q-mt-xl(bar shadow) header.row.justify-between div - .text-xl.text-weight-600.text-primary {{ $t(`plans.${selectedDaoPlan.name}`) }} - p.q-pa-none.q-ma-none.text-3xl.text-primary.text-bold ${{ formatMoney(selectedDaoPlan.amountUSD) }} + .text-xl.text-weight-600.text-primary {{ $t(`plans.${currentPlan.name}`) }} + p.q-pa-none.q-ma-none.text-3xl.text-primary.text-bold ${{ formatMoney(currentPlan.amountUSD) }} //- TODO: Return after beta //- span.q-ml-xxs.text-sm.text-weight-500 / {{ $('periods.month') }} div q-chip(dense color="positive" text-color="white") - span.text-uppercase.text-xxs.text-bold.q-px-xxs {{ $t(`statuses.${selectedDaoPlan.status}`) }} + span.text-uppercase.text-xxs.text-bold.q-px-xxs {{ $t(`statuses.${currentPlan.status}`) }} .hr.q-mt-md.q-mb-xs footer div.row.justify-between p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose Core Members - p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose {{ selectedDaoPlan.currentCoreMembersCount }} / {{ selectedDaoPlan.coreMembersCount }} + p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose {{ selectedDaoPlan.currentCoreMembersCount }} / {{ currentPlan.coreMembersCount }} //- TODO: Return after beta //- div.row.justify-between.q-mt-xs //- p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose Community Members //- p.q-pa-none.q-ma-none.text-sm.text-h-gray.leading-loose {{ selectedDaoPlan.communityMembersCount }} nav.q-mt-xl.full-width.row.justify-end - q-btn.q-px-xl.rounded-border.text-bold.q-ml-xs( - :disable="!isAdmin" - :label="$t('configuration.settings-plans-billing.plan.cta')" - @click="state = STATES.UPDATING_PLAIN" - color="secondary" - no-caps - rounded - unelevated - ) + q-btn.q-px-xl.rounded-border.text-bold.q-ml-xs( + :disable="!isAdmin" + :label="$t('configuration.settings-plans-billing.plan.cta')" + @click="state = STATES.UPDATING_PLAIN" + color="secondary" + no-caps + rounded + unelevated + ) .col-12.col-md-6(:class="{ 'q-pr-sm': $q.screen.gt.md, 'q-mt-md': $q.screen.lt.md }") widget(:title="$t('configuration.settings-plans-billing.history.title')" titleImage='/svg/briefcase.svg' bar).q-pa-none diff --git a/src/layouts/DhoSelector.vue b/src/layouts/DhoSelector.vue index c0f3983c1..66ef02e00 100644 --- a/src/layouts/DhoSelector.vue +++ b/src/layouts/DhoSelector.vue @@ -308,10 +308,10 @@ export default { dao: { query: gql`query activeDao($daoUrl: String!, $regexp: String!) { ${DAO_ACTIVE_QUERY} }`, update: data => data.queryDao, - skip () { return !this.dhoname || !this.daoRegexp }, - variables () { return { regexp: this.daoRegexp, daoUrl: this.dhoname } }, + skip() { return !this.dhoname || !this.daoRegexp }, + variables() { return { regexp: this.daoRegexp, daoUrl: this.dhoname } }, - result (res) { + result(res) { const data = res?.data if (!data?.queryDao?.length) { @@ -330,8 +330,8 @@ export default { this.$store.dispatch('accounts/checkMembership') }, - fetchPolicy: 'no-cache', - pollInterval: 1000 // TODO: Swap with subscribe once dgraph is ready + fetchPolicy: 'no-cache' + // pollInterval: 1000 // TODO: Swap with subscribe once dgraph is ready // subscribeToMore: { // document: gql`subscription activeDao($regexp: String!) { ${DAO_ACTIVE_QUERY} }`, // skip () { return !this.dhoname || !this.daoRegexp }, @@ -354,7 +354,7 @@ export default { dho: { query: require('~/query/main-dho.gql'), update: data => data.queryDho, - result (res) { + result(res) { this.$store.commit('dao/setDho', res.data.queryDho) }, fetchPolicy: 'no-cache' @@ -362,16 +362,16 @@ export default { }, - data () { + data() { return { daoQueryNumberOfRetires: 0 } }, computed: { - daoRegexp () { return '/^' + this.dhoname + '$/i' }, + daoRegexp() { return '/^' + this.dhoname + '$/i' }, - dho () { + dho() { if (this.dao && this.dao.length) { return { name: this.dao[0]?.details_daoName_n || '', @@ -389,10 +389,11 @@ export default { } }, - useCreateLayout () { return this.$q.screen.lt.md && this.$route.meta && this.$route.meta.layout && this.$route.meta.layout.mobile === 'create' }, - useLoginLayout () { return this.$route.name === 'login' }, - useMobileProposalLayout () { return this.$q.screen.lt.md && this.$route.meta && this.$route.meta.layout === 'proposal' }, - useMultiDHOLayout () { return this.$route.name !== 'login' } + useCreateLayout() { return this.$q.screen.lt.md && this.$route.meta && this.$route.meta.layout && this.$route.meta.layout.mobile === 'create' }, + useLoginLayout() { return this.$route.name === 'login' }, + useMobileProposalLayout() { return this.$q.screen.lt.md && this.$route.meta && this.$route.meta.layout === 'proposal' }, + useMultiDHOLayout() { return this.$route.name !== 'login' }, + refetch() { return this.$apollo.queries.dao.refetch } } } @@ -401,7 +402,7 @@ export default { .dho-selector create-layout(v-if="useCreateLayout") login-layout(v-if="useLoginLayout") - multi-dho-layout(v-if="useMultiDHOLayout" :dho="dho" :daoName="dhoname" :dhoTitle="dho?.title") + multi-dho-layout(v-if="useMultiDHOLayout" :dho="dho" :daoName="dhoname" :dhoTitle="dho?.title" :refetch="refetch") proposal-layout(v-if="useMobileProposalLayout && $q.platform.is.desktop") diff --git a/src/utils/format-plan.js b/src/utils/format-plan.js new file mode 100644 index 000000000..32202063c --- /dev/null +++ b/src/utils/format-plan.js @@ -0,0 +1,10 @@ +import { PLAN, PLAN_STATUS } from '~/const' + +export default (plan) => ({ + ...plan, + name: (plan?.name || PLAN.FOUNDER).toLowerCase(), + status: plan?.status || PLAN_STATUS.ACTIVE, + amountUSD: plan?.price / 100 / 12, + coreMembersCount: plan?.coreMembersCount || 5, + communityMembersCount: plan?.communityMembersCount || 0 +}) From 58bc002dd5dddd9483eec09abdc498c2a853f3b9 Mon Sep 17 00:00:00 2001 From: Evgeni B Date: Mon, 25 Sep 2023 16:35:16 +0300 Subject: [PATCH 2/6] fix: mobile UI bugs (#2474) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(mobile): hide left navigation on mobile * fix(step-details): mobile ui bugs --------- Co-authored-by: Arsenije Savić --- src/layouts/MultiDhoLayout.vue | 5 +++-- src/pages/proposals/create/StepDetails.vue | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/layouts/MultiDhoLayout.vue b/src/layouts/MultiDhoLayout.vue index 1754d6c5f..f61182081 100644 --- a/src/layouts/MultiDhoLayout.vue +++ b/src/layouts/MultiDhoLayout.vue @@ -557,8 +557,9 @@ export default { profile-sidebar-guest(v-if="!account && ($q.screen.gt.lg || !$q.screen.gt.sm) && !loadingAccount" :dhoTitle="dhoTitle" :daoName="daoName" @close="right = false" :registrationEnabled="daoSettings.registrationEnabled") q-footer.bg-white(v-if="$q.screen.lt.lg && $route.name !== ROUTE_NAMES.PROPOSAL_DETAIL && $route.name !== ROUTE_NAMES.CREATE_YOUR_DAO" :style="{ height: '74px' }") bottom-navigation - q-drawer(v-else v-model="left" side="left" :width="80" persistent="persistent" :show-if-above="true") - left-navigation(:dho="dho" :dhos="dhos") + q-drawer(v-else-if="$q.screen.gt.md" v-model="left" side="left" :width="80" persistent="persistent" :show-if-above="true") + left-navigation(:dho="dho" :dhos="getDaos($apolloData.data.member)") + diff --git a/src/components/login/register-user-with-captcha-view.vue b/src/components/login/register-user-with-captcha-view.vue index a080afc78..3deb65715 100644 --- a/src/components/login/register-user-with-captcha-view.vue +++ b/src/components/login/register-user-with-captcha-view.vue @@ -6,7 +6,7 @@ import ipfsy from '~/utils/ipfsy' import { Notify } from 'quasar' import slugify from '~/utils/slugify' -const HELP_LINK = 'https://help.hypha.earth/hc/2431449449' +const HELP_LINK = 'https://hypha.earth/get-started/create-hypha-account/' export default { name: 'register-user-with-captcha-view', @@ -15,7 +15,8 @@ export default { Captcha: () => import('~/components/form/captcha.vue'), InputFileIpfs: () => import('~/components/ipfs/input-file-ipfs.vue'), LoadingSpinner: () => import('~/components/common/loading-spinner.vue'), - QrcodeVue + QrcodeVue, + ProfilePicture: () => import('~/components/profiles/profile-picture.vue') }, props: { step: String, @@ -49,6 +50,10 @@ export default { loading: { name: 'loading', index: 5 + }, + account: { + name: 'account', + index: 6 } } return { @@ -113,6 +118,7 @@ export default { }, computed: { ...mapGetters('accounts', ['account', 'isAuthenticated']), + ...mapGetters('dao', ['daoSettings', 'selectedDao']), isImageSelected: { cache: false, get () { return this.$refs.ipfsInput?.imageURI } @@ -149,7 +155,10 @@ export default { } catch (e) { } } else { - await this.loginWallet({ idx, returnUrl: this.isOnboarding ? 'create' : this.$route.query.returnUrl || 'home' }) + await this.loginWallet({ idx }) + if (this.account) { + this.$emit('stepChanged', this.steps.account.name) + } } }, async setCaptchaResponse(data) { @@ -221,74 +230,77 @@ export default { } else if (navigator.userAgent.toLowerCase().indexOf('android') > -1) { window.location.href = process.env.DOWNLOAD_WALLET_LINK_ANDROID } + }, + enterDao() { + this.$router.push({ path: `/${this.selectedDao.name}/home` }) } } } diff --git a/src/components/login/welcome-view.vue b/src/components/login/welcome-view.vue index 522a72613..4d2ee7f4c 100644 --- a/src/components/login/welcome-view.vue +++ b/src/components/login/welcome-view.vue @@ -17,20 +17,20 @@ export default { } diff --git a/src/locales/en.json b/src/locales/en.json index 5690e1d16..d0f8ead7b 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -785,9 +785,9 @@ "loginTo":"Login to your {daoName} Account", "your":" your", "account":"account", - "loginTo1":"Login to\n ", + "loginTo1":"Log in to\n ", "yourAccount":"your account", - "youCanEither":"You can log in with Hypha wallet or Seeds Light wallet (available for iOS and Android). You can also log in with Anchor wallet, a secure, open source tool (available for Windows and Mac desktops and Android and iOS mobiles).", + "youCanEither":"You can log in using Hypha Wallet or Partner Wallets (available for iOS and Android). Alternatively, you can log in with Anchor Wallet, a secure, open source tool (available for Windows, Mac, Android and iOS).", "downloadHere":"Download here", "orAnchor":") Or Anchor, a secure and Open Source tool that is available for download as a ", "desktopAppFor":"Desktop App for Windows and Mac ", @@ -797,7 +797,7 @@ "nbspios":" iOS", "forMore":". For more help with setting up Anchor,", "seeTheseSlidesnbsp":"see these slides. ", - "pleaseLoginWith":"Please login with one of the wallets, your private key or continue as guest. For improved security, we recommend to download and install the Anchor wallet.", + "pleaseLoginWith":"You can log in using Hypha Wallet or Partner Wallets (available for iOS and Android). Alternatively, you can log in with Anchor Wallet, a secure, open source tool (available for Windows, Mac, Android and iOS).", "account1":"Account", "account2":"Account", "privateKey":"Private key", @@ -839,46 +839,51 @@ "createDao":"Create DAO" }, "register-user-with-captcha-view":{ - "createNew":"Create New Hypha Account\n ", + "enter": "Enter DAO", + "youCanNowUserYour": "You can now use your Hypha account on {dao}", + "accountConnected": "Account connected", + "welcomeUser": "Welcome {username}!", + "createNew":"Create New", "hyphaAccount":"Hypha Account", - "pleaseVerifyYou":"Please verify you are not a BOT", - "proceedWith":"Proceed with Hypha Wallet\n ", + "pleaseVerifyYou":"Please, verify you are not a BOT", + "proceedWith":"Proceed with\n Hypha Wallet\n ", "setupHyphaWallet":"Set-up Hypha Wallet", - "scanTheQr":"Click the 'Download Wallet' button on this page,", - "itContainsThe":" this will redirect you to the Hypha Wallet download page.", + "scanTheQr": "Click on “Download Wallet” below to install the Hypha Wallet on your phone and create your account. Once the account is ready, you are set for the last next step.", + "itContainsThe":"Scan the QR code to install the Hypha Wallet on your phone and create your account. Once the account is ready, you are set for the last next step.", "onceTheAccount":" Once the account is ready,", "youAreSet":" you are set for the last next step.", "copyInviteLink":"Copy invite link", - "loginWith":"Log-in with Hypha Wallet\n ", + "loginWith":"Log-in with\n Hypha Wallet\n ", "hyphaWallet1":"Hypha Wallet", "signYourFirstTransaction":"Sign your first transaction", - "didYouCreate":"Did you create your Hypha Account inside the Hypha Wallet? Great! Now click the button below and generate your first log-in transaction request, sign-it and you are good to go!", - "login":"{1} Login {2}", + "didYouCreate":"Did you create your Hypha Account inside the Hypha Wallet? Great! Now click on the button below and sign the transaction into your Hypha Wallet to log into your DAO.", + "login":"Log in with {1}", + "loginMobile": "Log in", "getApp":"Get app", "areYouAMember":"Are you a member?", "loginHere":"Login here", "createYourDao":"Create Your DAO", - "goAheadAndAddYour":"Go ahead and add your DAO's name and upload a logo. You can also also list your DAO's purpose and the impact it envisions making.", + "goAheadAndAddYour":"Start by uploading your logo and entering your DAO’s name. After that, go ahead and create a short and meaningful purpose statement for your DAO.", "publishYourDao":"Publish your DAO", "needHelp":"Need help?", - "downloadWallet": "Download Wallet" + "downloadWallet": "Download Hypha Wallet app" }, "welcome-view":{ - "youNeedAn":"You need an Hypha Account to interact with Hypha Ecosystem and create a DAO.", - "isonboarding":"If you already have a Hypha account, click the log in button, sign the transaction with your Wallet and start creating your DAO. If not, you can click 'Create Hypha account' or 'Continue as guest.'", + "youNeedAn":"Log in with your Hypha account", + "isonboarding":"If you already have a Hypha account configured in your wallet, click on the “Log in” button. Otherwise, choose “Create Hypha account” or simply “Continue as a Guest”.", "ifThisIs":"If this is your first time here,", "clickCreateNew":" click Create new Hypha account and follow the steps. ", "ifYouAlready":"If you already have an Hypha Account and Anchor wallet configured", "clickThe":", click the log-in button, validate the transaction with Anchor Wallet and enter the DAO.", - "theDhoDecentralized":"The DHO (Decentralized Human Organization) is a framework to build your organization from the ground up in an organic and participative way and together with others.", - "createNewHyphaAccount":"Create new Hypha account", + "theDhoDecentralized": "If you already have a Hypha account configured in your wallet, click on the “Log in” button. Otherwise, choose “Create Hypha account” or simply “Continue as a Guest”.", + "createNewHyphaAccount":"Create Hypha account", "registrationIsTemporarilyDisabled":"Registration is temporarily disabled", "login":"Log in", - "continueAsAGuest":"Continue as guest", + "continueAsAGuest":"Continue as Guest", "useAnExisting":"Use an existing\n ", "blockhainAccount":"blockhain account", - "launchYourFirst":"Launch your first DAO", - "youNeedAHyphaAccount":"You need a Hypha Account to interact with the Hypha network.", + "launchYourFirst":"Create Your DAO", + "youNeedAHyphaAccount":"You need a Hypha account to create a DAO.", "ifYouAlreadyHaveAHyphaAccount":"If you already have a Hypha Account, click the log in button, sign the transaction with your Wallet and start creating your DAO." } }, diff --git a/src/pages/onboarding/NLogin.vue b/src/pages/onboarding/NLogin.vue index 8f5176daf..e94d1175e 100644 --- a/src/pages/onboarding/NLogin.vue +++ b/src/pages/onboarding/NLogin.vue @@ -147,7 +147,7 @@ export default { .relative-position.full-height.full-width.custom-scroll-area(v-if="$q.screen.lt.md || $q.screen.md") .welcome-bg-mobile.full-height.full-width(:class="animationBGMobile") .welcome-fg.full-height.full-width - img.hyphaLogo(src="~assets/logos/hypha-logo-full.svg") + img.hyphaLogo(src="~assets/logos/hypha-horizontal-light.png") q-card.card-container.bottom-card(:class="animationCardMobile") q-scroll-area.full-width.full-height(:thumb-style="{ 'opacity': '0'}" :content-style="{ 'height': '100%' }" ref="scrollArea") transition(v-if="step === steps.welcome" enter-active-class="animated fadeIn" leave-active-class="animated fadeOut") @@ -196,17 +196,17 @@ export default { .left-card padding 50px 80px .bottom-card + border-radius: 25px 25px 0 0 position: absolute top: 120px left: 0 right: 0 bottom: 0 - padding: 30px 20px 30px @media (orientation: landscape) and (min-width: 1024px) height: auto !important @media (max-width: 375px) height: 100% !important - max-height: calc(90vh - 130px) + max-height: 88% @media (max-width: 375px) top: auto .bottom-card-step-two @@ -231,7 +231,7 @@ export default { background-position-x: 70% .hyphaLogo width: 150px - margin: 44px 0 0 42px + margin: 20px 0 0 20px z-index: 10 position: relative .custom-scroll-area From e8e878da5033138e9e2b6e2a1246c5b7becb7511 Mon Sep 17 00:00:00 2001 From: Arsenije Savic Date: Mon, 25 Sep 2023 08:04:45 -0600 Subject: [PATCH 4/6] refactor: clean up layouts --- src/App.vue | 24 +- .../login/register-user-with-captcha-view.vue | 1 - src/layouts/DhoSelector.vue | 410 ----------- src/layouts/Layout.vue | 25 + src/layouts/MultiDhoLayout.vue | 689 +++++++++++++----- src/pages/dho/Configuration.vue | 1 - src/router/routes.js | 31 +- src/store/accounts/mutations.js | 18 + src/store/profiles/actions.js | 12 +- 9 files changed, 597 insertions(+), 614 deletions(-) delete mode 100644 src/layouts/DhoSelector.vue create mode 100644 src/layouts/Layout.vue diff --git a/src/App.vue b/src/App.vue index 6704d123f..f326be441 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,11 +5,30 @@ import { mapActions, mapGetters, mapMutations } from 'vuex' export default { name: 'App', + apollo: { + dho: { + query: require('~/query/main-dho.gql'), + update: data => data.queryDho, + result (res) { this.$store.commit('dao/setDho', res.data.queryDho) }, + fetchPolicy: 'no-cache' + } + }, + computed: { + ...mapGetters('accounts', ['account']), ...mapGetters('layout', ['alert']) }, watch: { + account: { + async handler (value) { + if (value) { + await this.getPublicProfile(this.account) + } + }, + immediate: true + }, + alert: function (value) { Notify.create({ type: value.level, @@ -39,8 +58,10 @@ export default { ...mapActions('accounts', ['autoLogin']), ...mapActions('dao', ['initConfigs']), ...mapActions('layout', ['loadAlert']), - ...mapMutations('layout', ['dismissAlert']) + ...mapMutations('layout', ['dismissAlert']), + ...mapActions('profiles', ['getPublicProfile']) } + } @@ -50,5 +71,4 @@ export default { diff --git a/src/components/login/register-user-with-captcha-view.vue b/src/components/login/register-user-with-captcha-view.vue index 3deb65715..df66716fd 100644 --- a/src/components/login/register-user-with-captcha-view.vue +++ b/src/components/login/register-user-with-captcha-view.vue @@ -202,7 +202,6 @@ export default { query.subscribe(({ data, loading }) => { const value = data.queryDao if (value.length > 0) { - this.$store.dispatch('accounts/checkMembership') this.$router.push({ path: `/${daoUrl}/` }) } }) diff --git a/src/layouts/DhoSelector.vue b/src/layouts/DhoSelector.vue deleted file mode 100644 index 66ef02e00..000000000 --- a/src/layouts/DhoSelector.vue +++ /dev/null @@ -1,410 +0,0 @@ - - - - diff --git a/src/layouts/Layout.vue b/src/layouts/Layout.vue new file mode 100644 index 000000000..cf156482d --- /dev/null +++ b/src/layouts/Layout.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/src/layouts/MultiDhoLayout.vue b/src/layouts/MultiDhoLayout.vue index f61182081..90d5eeded 100644 --- a/src/layouts/MultiDhoLayout.vue +++ b/src/layouts/MultiDhoLayout.vue @@ -6,6 +6,308 @@ import { timeago } from '~/utils/TimeUtils' import { parsedNotification } from '~/utils/notifications-utils' import { ROUTE_NAMES } from '~/const' +const MAX_NUM_OF_RETIRES = 10 + +const DAO_ACTIVE_QUERY = ` + activePlan(daoUrl: $daoUrl) { + subscriptionId + subscriptionItemId + subscriptionStatus + currency + currentPeriodEnd + currentPeriodStart + coreMembersCount + communityMembersCount + price + id: planId + name: planName + } + + queryDao @cascade(fields: ["settings"]) { + docId + details_daoName_n + + details_daoType_s + # details_isWaitingEcosystem_i + createdDate + + upcomingelct { + docId + } + + admin(filter: { details_member_n: { eq: $username } }) { + docId + } + enroller(filter: { details_member_n: { eq: $username } }) { + docId + } + applicant(filter: { details_member_n: { eq: $username } }) { + docId + } + member(filter: { details_member_n: { eq: $username } }) { + docId + } + + announcements: alert { + id: docId + title: details_level_s + message: details_content_s + enabled: details_enabled_i + } + + planmanager { + bill { + id: docId + startDate: details_startDate_t + endDate: details_endDate_t + expirationDate: details_expirationDate_t + periodCount: details_periodCount_i + name: details_planName_s + price: details_planPrice_a + isInfinite: details_isInfinite_i + discountPercX10000: details_discountPercX10000_i + + pricingplan { + maxMemberCount: details_maxMemberCount_i + } + } + currentbill { + id: docId + startDate: details_startDate_t + endDate: details_endDate_t + expirationDate: details_expirationDate_t + periodCount: details_periodCount_i + name: details_planName_s + price: details_planPrice_a + isInfinite: details_isInfinite_i + discountPercX10000: details_discountPercX10000_i + + pricingplan { + maxMemberCount: details_maxMemberCount_i + } + } + lastbill { + id: docId + startDate: details_startDate_t + endDate: details_endDate_t + expirationDate: details_expirationDate_t + periodCount: details_periodCount_i + name: details_planName_s + price: details_planPrice_a + isInfinite: details_isInfinite_i + discountPercX10000: details_discountPercX10000_i + + pricingplan { + maxMemberCount: details_maxMemberCount_i + } + } + } + + multisigs: openmultisig { + approvedby { + docId + details_member_n + } + + id: docId + + # ecosystem_name_s + # ecosystem_logo_s + # ecosystem_domain_s + # ecosystem_purpose_s + + # settings_onboarderAccount_n + + # settings_claimEnabled_i + settings_daoUrl_s + # settings_daoName_n + settings_daoTitle_s + # settings_daoDescription_s + # settings_governanceTokenContract_n + # settings_pegToken_a + # settings_pegTokenContract_n + # settings_rewardToken_a + # settings_rewardTokenContract_n + # settings_rewardToPegRatio_a + # settings_treasuryContract_n + # settings_voiceToken_a + + settings_socialChat_s + settings_documentationButtonText_s + + settings_proposalsCreationEnabled_i + settings_membersApplicationEnabled_i + settings_removableBannersEnabled_i + settings_multisigEnabled_i + + settings_votingDurationSec_i + # settings_periodDurationSec_i + settings_votingAlignmentX100_i + settings_votingQuorumX100_i + # settings_voiceTokenDecayPeriod_i + + settings_communityVotingEnabled_i + settings_communityVotingMethod_s + settings_upvoteStartDateTime_s + settings_upvoteDuration_i + settings_upvoteRounds_s + settings_upvoteCheifDelegateCount_i + settings_upvoteCheifDelegateDuration_i + settings_upvoteHeadDelegateRound_i + settings_upvoteHeadDelegateDuration_i + settings_communityVotingDurationSec_i + settings_communityVotingAlignmentPercent_i + settings_communityVotingQuorumPercent_i + + # settings_usesSeeds_i + # settings_isHypha_i + + settings_logo_s + settings_extendedLogo_s + settings_primaryColor_s + settings_secondaryColor_s + settings_textColor_s + settings_pattern_s + settings_patternColor_s + settings_patternOpacity_i + settings_patternBase64_s + + settings_splashBackgroundImage_s + + settings_dashboardBackgroundImage_s + settings_dashboardTitle_s + settings_dashboardParagraph_s + + settings_proposalsBackgroundImage_s + settings_proposalsTitle_s + settings_proposalsParagraph_s + + settings_membersBackgroundImage_s + settings_membersTitle_s + settings_membersParagraph_s + + settings_organisationBackgroundImage_s + settings_organisationTitle_s + settings_organisationParagraph_s + + settings_exploreBackgroundImage_s + settings_exploreTitle_s + settings_exploreParagraph_s + + settings_documentationURL_s + } + + settings(filter: { settings_daoUrl_s: { regexp: $regexp } }) { + ecosystem_name_s + ecosystem_logo_s + ecosystem_domain_s + ecosystem_purpose_s + + settings_onboarderAccount_n + + settings_claimEnabled_i + settings_daoUrl_s + settings_daoName_n + settings_daoTitle_s + settings_daoDescription_s + settings_governanceTokenContract_n + + settings_pegTokenName_s + settings_pegToken_a + settings_pegTokenContract_n + settings_treasuryTokenMultiplier_i + settings_treasuryContract_n + + settings_rewardTokenName_s + settings_rewardToken_a + settings_rewardTokenContract_n + settings_rewardToPegRatio_a + settings_rewardTokenMaxSupply_a + settings_utilityTokenMultiplier_i + + settings_voiceToken_a + settings_voiceTokenDecayPeriod_i + settings_voiceTokenDecayPerPeriodX10M_i + settings_voiceTokenMultiplier_i + + settings_socialChat_s + settings_documentationButtonText_s + + settings_proposalsCreationEnabled_i + settings_membersApplicationEnabled_i + settings_removableBannersEnabled_i + settings_multisigEnabled_i + + settings_votingDurationSec_i + settings_periodDurationSec_i + settings_votingAlignmentX100_i + settings_votingQuorumX100_i + settings_voiceTokenDecayPeriod_i + + settings_communityVotingEnabled_i + settings_communityVotingMethod_s + settings_upvoteStartDateTime_s + settings_upvoteDuration_i + settings_upvoteRounds_s + settings_upvoteCheifDelegateCount_i + settings_upvoteCheifDelegateDuration_i + settings_upvoteHeadDelegateRound_i + settings_upvoteHeadDelegateDuration_i + settings_communityVotingDurationSec_i + settings_communityVotingAlignmentPercent_i + settings_communityVotingQuorumPercent_i + + settings_usesSeeds_i + settings_isHypha_i + + settings_logo_s + settings_extendedLogo_s + settings_primaryColor_s + settings_secondaryColor_s + settings_textColor_s + settings_pattern_s + settings_patternColor_s + settings_patternOpacity_i + settings_patternBase64_s + + settings_splashBackgroundImage_s + + settings_dashboardBackgroundImage_s + settings_dashboardTitle_s + settings_dashboardParagraph_s + + settings_proposalsBackgroundImage_s + settings_proposalsTitle_s + settings_proposalsParagraph_s + + settings_membersBackgroundImage_s + settings_membersTitle_s + settings_membersParagraph_s + + settings_organisationBackgroundImage_s + settings_organisationTitle_s + settings_organisationParagraph_s + + settings_exploreBackgroundImage_s + settings_exploreTitle_s + settings_exploreParagraph_s + + settings_documentationURL_s + } + + levels: salaryband { + id: docId + name: details_name_s + annualAmount: details_annualUsdSalary_a + minDeferred: details_minDeferredX100_i + } + + memberAggregate { + count + } + } +` + // const NOTIFICATIONS_QUERY = ` // queryNotification(order: { desc: time }) { // event { @@ -25,6 +327,11 @@ import { ROUTE_NAMES } from '~/const' // } // ` +const STATE = Object.freeze({ + LOADING: 'LOADING', + READY: 'READY' +}) + export default { name: 'multi-dho-layout', components: { @@ -45,12 +352,55 @@ export default { }, props: { - dho: Object, - daoName: String, - dhoTitle: String + dhoname: String }, apollo: { + dao: { + query: gql`query activeDao($daoUrl: String!, $regexp: String!, $username: String) { ${DAO_ACTIVE_QUERY} }`, + update: data => { + const dao = data.queryDao[0] + return { + ...dao, + name: dao?.details_daoName_n || '', + title: dao?.settings[0]?.settings_daoTitle_s || '', + icon: dao?.settings[0]?.settings_logo_s || '', + isHypha: dao?.settings[0]?.settings_isHypha_i || '' + } + }, + skip () { return !this.dhoname || !this.account }, + variables () { + return { + regexp: '/^' + this.dhoname + '$/i', + daoUrl: this.dhoname, + username: this.account + } + }, + + async result (res) { + const data = res?.data + + if (!data?.queryDao?.length) { + this.daoQueryNumberOfRetires++ + if (this.daoQueryNumberOfRetires > MAX_NUM_OF_RETIRES) { + this.$router.push({ path: '/not-found' }) + } else { + this.$apollo.queries.dao.refetch() + } + return + } + + this.$store.commit('accounts/setMember', data?.queryDao[0]) + this.$store.dispatch('ballots/getSupply') + this.$store.commit('dao/switchDao', data) + this.$store.dispatch('dao/setTheme') + this.state = STATE.READY + }, + loadingKey: 'loading', + fetchPolicy: 'no-cache' + // pollInterval: 300 // TODO: Swap with subscribe once dgraph is ready + }, + dhos: { query: require('../query/profile/profile-dhos.gql'), update: data => data?.getMember?.memberof.map(dao => ({ @@ -91,6 +441,10 @@ export default { data () { return { + daoQueryNumberOfRetires: 0, + STATE, + state: STATE.LOADING, + ROUTE_NAMES, timeago, parsedNotification, @@ -153,17 +507,13 @@ export default { watch: { - dho (v) { + dao (v) { if (v.icon) { this.updateTitle() this.updateFavicon() } }, - '$apolloData.data.member': { - handler () { - }, - immediate: true - }, + $route: { handler () { this.$refs.scrollArea.setScrollPosition('vertical', 0) @@ -201,12 +551,11 @@ export default { }, account: { async handler () { - await this.$nextTick() + // await this.$nextTick() if (this.account) { this.getProfile() - this.$store.dispatch('accounts/checkMembership') this.$store.dispatch('accounts/getHyphaOwners') - await this.$nextTick() + // await this.$nextTick() // await this.$apollo.queries.member.setVariables({ // username: this.account // }) @@ -264,14 +613,14 @@ export default { link.rel = 'icon' document.getElementsByTagName('head')[0].appendChild(link) } - const file = await BrowserIpfs.retrieve(this.dho.icon) + const file = await BrowserIpfs.retrieve(this.dao.icon) const faviconUrl = URL.createObjectURL(file.payload) link.href = faviconUrl // link.href = 'https://stackoverflow.com/favicon.ico' }, async updateTitle () { const title = this.$route.meta.title - document.title = `${title} - ${this.dho.title}` + document.title = `${title} - ${this.dao.title}` // let title = document.querySelector('title') // link.href = faviconUrl // link.href = 'https://stackoverflow.com/favicon.ico' @@ -400,6 +749,14 @@ export default { this.$router.push({ path: `/${this.selectedDao?.name}/proposals/${proposal}` }) } } + }, + + // created () { + // this.state = STATE.LOADING + // }, + updated () { + console.log(JSON.stringify(this.$apollo.queries.dao.loading)) + console.log(JSON.stringify(this.account)) } } @@ -407,158 +764,158 @@ export default {