diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 653a39f01..e6f49c031 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -61,6 +61,8 @@ jobs: LOGIN_CONTRACT: ${{ vars.LOGIN_CONTRACT }} JOIN_CONTRACT: ${{ vars.JOIN_CONTRACT }} JOIN_URI: 'https://join.hypha.earth/' + DOWNLOAD_WALLET_LINK_IOS: ${{vars.DOWNLOAD_WALLET_LINK_IOS}} || http://itunes.apple.com/lb/app/id1659926348 + DOWNLOAD_WALLET_LINK_ANDROID: ${{vars.DOWNLOAD_WALLET_LINK_ANDROID}} || http://play.google.com/store/apps/details?id=earth.hypha.wallet.hypha_wallet - name: S3 sync diff --git a/.github/workflows/deploy-eos-dev.yml b/.github/workflows/deploy-eos-dev.yml index ec39fc326..22cdb8290 100644 --- a/.github/workflows/deploy-eos-dev.yml +++ b/.github/workflows/deploy-eos-dev.yml @@ -77,6 +77,9 @@ jobs: JOIN_CONTRACT: ${{ vars.JOIN_CONTRACT }} JOIN_URI: 'https://join.hypha.earth/' + DOWNLOAD_WALLET_LINK_IOS: ${{vars.DOWNLOAD_WALLET_LINK_IOS}} || http://itunes.apple.com/lb/app/id1659926348 + DOWNLOAD_WALLET_LINK_ANDROID: ${{vars.DOWNLOAD_WALLET_LINK_ANDROID}} || http://play.google.com/store/apps/details?id=earth.hypha.wallet.hypha_wallet + - name: Deploy to S3 bucket run: aws s3 sync ./dist/spa s3://${{ vars.AWS_S3_BUCKET}} --delete - name: Invalidate CloudFront diff --git a/.github/workflows/deploy-eos-prod.yml b/.github/workflows/deploy-eos-prod.yml index 2c8ee5a86..14b64432e 100644 --- a/.github/workflows/deploy-eos-prod.yml +++ b/.github/workflows/deploy-eos-prod.yml @@ -77,6 +77,9 @@ jobs: JOIN_CONTRACT: ${{ vars.JOIN_CONTRACT }} JOIN_URI: 'https://join.hypha.earth/' + DOWNLOAD_WALLET_LINK_IOS: ${{vars.DOWNLOAD_WALLET_LINK_IOS}} || http://itunes.apple.com/lb/app/id1659926348 + DOWNLOAD_WALLET_LINK_ANDROID: ${{vars.DOWNLOAD_WALLET_LINK_ANDROID}} || http://play.google.com/store/apps/details?id=earth.hypha.wallet.hypha_wallet + - name: Deploy to S3 bucket run: aws s3 sync ./dist/spa s3://${{ vars.AWS_S3_BUCKET}} --delete - name: Invalidate CloudFront diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 6e1188605..9dffb792a 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -67,6 +67,9 @@ jobs: JOIN_CONTRACT: ${{ vars.JOIN_CONTRACT }} JOIN_URI: 'https://join.hypha.earth/' + DOWNLOAD_WALLET_LINK_IOS: ${{vars.DOWNLOAD_WALLET_LINK_IOS}} || http://itunes.apple.com/lb/app/id1659926348 + DOWNLOAD_WALLET_LINK_ANDROID: ${{vars.DOWNLOAD_WALLET_LINK_ANDROID}} || http://play.google.com/store/apps/details?id=earth.hypha.wallet.hypha_wallet + - name: S3 sync uses: jakejarvis/s3-sync-action@master with: diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index fef1be5f2..a860dfb32 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -67,6 +67,9 @@ jobs: JOIN_CONTRACT: ${{ vars.JOIN_CONTRACT }} JOIN_URI: 'https://join.hypha.earth/' + DOWNLOAD_WALLET_LINK_IOS: ${{vars.DOWNLOAD_WALLET_LINK_IOS}} || http://itunes.apple.com/lb/app/id1659926348 + DOWNLOAD_WALLET_LINK_ANDROID: ${{vars.DOWNLOAD_WALLET_LINK_ANDROID}} || http://play.google.com/store/apps/details?id=earth.hypha.wallet.hypha_wallet + - name: S3 sync uses: jakejarvis/s3-sync-action@master with: diff --git a/.github/workflows/deploy.branch.yml b/.github/workflows/deploy.branch.yml index ba392fcf8..26c40a40b 100644 --- a/.github/workflows/deploy.branch.yml +++ b/.github/workflows/deploy.branch.yml @@ -66,6 +66,9 @@ env: CAPTCHA_NETWORK: ${{ vars.CAPTCHA_NETWORK }} LOGIN_CONTRACT: ${{ vars.LOGIN_CONTRACT }} + DOWNLOAD_WALLET_LINK_IOS: ${{vars.DOWNLOAD_WALLET_LINK_IOS}} || http://itunes.apple.com/lb/app/id1659926348 + DOWNLOAD_WALLET_LINK_ANDROID: ${{vars.DOWNLOAD_WALLET_LINK_ANDROID}} || http://play.google.com/store/apps/details?id=earth.hypha.wallet.hypha_wallet + jobs: build_and_deploy: name: 'Build and Deploy App' diff --git a/quasar.conf.js b/quasar.conf.js index 9ae07f330..1e7ec8170 100644 --- a/quasar.conf.js +++ b/quasar.conf.js @@ -109,7 +109,9 @@ module.exports = function (ctx) { CAPTCHA_NETWORK: process.env.CAPTCHA_NETWORK || 'telosTestnet', LOGIN_CONTRACT: process.env.LOGIN_CONTRACT, JOIN_CONTRACT: process.env.JOIN_CONTRACT, - JOIN_URI: process.env.JOIN_URI + JOIN_URI: process.env.JOIN_URI, + DOWNLOAD_WALLET_LINK_IOS: process.env.DOWNLOAD_WALLET_LINK_IOS, + DOWNLOAD_WALLET_LINK_ANDROID: process.env.DOWNLOAD_WALLET_LINK_ANDROID }, scopeHoisting: true, diff --git a/src/components/common/payout-amounts.vue b/src/components/common/payout-amounts.vue index 005fdcdbf..26c9dd02b 100644 --- a/src/components/common/payout-amounts.vue +++ b/src/components/common/payout-amounts.vue @@ -2,6 +2,7 @@ import { defineComponent } from 'vue' import { PropType } from 'vue/types/v3-component-props' import TokenValue from './token-value.vue' +import { TOKEN_TYPES } from '~/const' type TokenProps = Omit< InstanceType['$props'], @@ -31,6 +32,31 @@ export default defineComponent({ type: String, default: undefined } + }, + + methods: { + settingsHasToken(token) { + if (token !== 'VOICE') { + if (this.$store.state.dao.settings.pegToken && this.$store.state.dao.settings.rewardToken) { + return token === this.$store.state.dao.settings.pegToken || token === this.$store.state.dao.settings.rewardToken + } else { + return false + } + } else { + return true + } + }, + + settingsMultiplier(label) { + switch (label) { + case TOKEN_TYPES.CASH_TOKEN: + return this.$store.state.dao.settings.settings_treasuryTokenMultiplier_i + case TOKEN_TYPES.VOICE_TOKEN: + return this.$store.state.dao.settings.settings_voiceTokenMultiplier_i + case TOKEN_TYPES.UTILITY_TOKEN: + return this.$store.state.dao.settings.settings_utilityTokenMultiplier_i + } + } } }) @@ -39,5 +65,5 @@ export default defineComponent({ .full-width(:class="{row: $q.platform.is.desktop}") template(v-for="token in tokens") .col(v-if="token.value" :class="{'col-12': stacked, 'q-mb-md': $q.platform.is.mobile}") - token-value(:daoLogo="daoLogo" :multiplier="multiplier" v-bind="token") + token-value(v-if="settingsHasToken(token.symbol)" :daoLogo="daoLogo" :multiplier="settingsMultiplier(token.label)" v-bind="token") diff --git a/src/components/dao/settings-plans-billing.vue b/src/components/dao/settings-plans-billing.vue new file mode 100644 index 000000000..6bce49d66 --- /dev/null +++ b/src/components/dao/settings-plans-billing.vue @@ -0,0 +1,246 @@ + + + + + diff --git a/src/components/dao/settings-tokens.vue b/src/components/dao/settings-tokens.vue index de004e64d..8ad4631e6 100644 --- a/src/components/dao/settings-tokens.vue +++ b/src/components/dao/settings-tokens.vue @@ -2,6 +2,7 @@ import { mapActions, mapGetters } from 'vuex' import { validation } from '~/mixins/validation' import currency from 'src/data/currency.json' +import map from '~/utils/map' const mapCurrency = (currency) => (_) => ({ label: `${currency[_]?.symbol} - ${currency[_]?.name}`, @@ -9,6 +10,9 @@ const mapCurrency = (currency) => (_) => ({ ...currency[_] }) +const MIN_DECAY = 0 +const MAX_DECAY = 10000000 + export default { name: 'settings-token', mixins: [validation], @@ -32,7 +36,6 @@ export default { data () { return { - tokens: { // Treasury token (aka peg_token = treasuryDigits treasurySymbol) treasuryName: null, @@ -51,7 +54,6 @@ export default { utilityDigits: 2, // 1.0, 1.00, 1.000 utilityTokenMultiplier: 1, utilityAmount: null, // i.e 100000 or -1 for infinite supply - // utilityValue: '1', // The equivalent value of 1 token in USD // Voice token (aka voice_token = voiceDigits voiceSymbol) voiceName: 'Voice Token', @@ -81,7 +83,11 @@ export default { try { const isValid = await this.validate(this.tokens) if (isValid) { - await this.createTokens({ ...this.tokens }) + await this.createTokens({ + ...this.tokens, + + voiceDecayPercent: map(this.tokens.voiceDecayPercent, 0, 100, MIN_DECAY, MAX_DECAY) + }) } } catch (e) { const message = e.message || e.cause.message @@ -95,34 +101,29 @@ export default { const [treasuryDigits, treasurySymbol] = this.daoSettings.settings_pegToken_a.split(' ') const [utilityDigits, utilitySymbol] = this.daoSettings.settings_rewardToken_a.split(' ') const [voiceDigits, voiceSymbol] = this.daoSettings.settings_voiceToken_a.split(' ') + const [utilityAmount] = this.daoSettings?.settings_rewardTokenMaxSupply_a?.split(' ') this.tokens = { // ...this.tokens, treasuryName: this.daoSettings.settings_pegTokenName_s || treasurySymbol, treasurySymbol, treasuryDigits: treasuryDigits.split('.')[1].length, // 1.0, 1.00, 1.000 - treasuryTokenMultiplier: this.daoSettings.settings_treasuryTokenMultiplier_i, - // treasuryCurrency: { - // label: `${currency.USD?.symbol} - ${currency.USD?.name}`, - // value: currency.USD.code, - // ...currency.USD - // }, + treasuryTokenMultiplier: this.daoSettings.treasuryTokenMultiplier, // // Utility token utilityName: this.daoSettings.settings_rewardTokenName_s || utilitySymbol, utilitySymbol, utilityDigits: utilityDigits.split('.')[1].length, // 1.0, 1.00, 1.000, // 1.0, 1.00, 1.000 - utilityTokenMultiplier: this.daoSettings.settings_utilityTokenMultiplier_i, - utilityAmount: this.daoSettings.settings_rewardTokenMaxSupply_a, // i.e 100000 or -1 for infinite supply - // // utilityValue: '1', // The equivalent value of 1 token in USD + utilityTokenMultiplier: this.daoSettings.utilityTokenMultiplier, + utilityAmount: parseInt(utilityAmount) === -1 ? '∞' : utilityAmount, // i.e 100000 or -1 for infinite supply // // Voice token voiceName: voiceSymbol, voiceSymbol, voiceDigits: voiceDigits.split('.')[1].length, - voiceTokenMultiplier: this.daoSettings.settings_voiceTokenMultiplier_i, + voiceTokenMultiplier: this.daoSettings.voiceTokenMultiplier, voiceDecayPeriod: this.daoSettings.settings_voiceTokenDecayPeriod_i, - voiceDecayPercent: this.daoSettings.settings_voiceTokenDecayPerPeriodX10M_i + voiceDecayPercent: map(this.daoSettings.settings_voiceTokenDecayPerPeriodX10M_i, MIN_DECAY, MAX_DECAY, 0, 100) } } @@ -145,18 +146,18 @@ export default { } }, immediate: true - }, - - 'tokens.treasuryCurrency': { - handler: function (value) { - if (value) { - this.tokens.treasuryName = value?.name - this.tokens.treasurySymbol = value?.code - } - }, - immediate: true } + // 'tokens.treasuryCurrency': { + // handler: function (value) { + // if (value) { + // this.tokens.treasuryName = value?.name + // this.tokens.treasurySymbol = value?.code + // } + // }, + // immediate: true + // } + } } @@ -180,11 +181,16 @@ export default { .col-12.col-md-6 label.h-label {{ $t('configuration.settings-tokens.tresury.form.name.label') }} q-input.q-my-xs( + :debounce="200" + :disable="selectedDao.hasCustomToken || !isAdmin" + :filled="selectedDao.hasCustomToken || !isAdmin" + :placeholder="$t('configuration.settings-tokens.utility.form.name.placeholder')" :rules="[rules.required]" + color="accent" dense - disable - filled lazy-rules + outlined + ref="treasuryName" rounded v-model='tokens.treasuryName' ) @@ -193,19 +199,26 @@ export default { .col-12.col-md-6 label.h-label {{ $t('configuration.settings-tokens.tresury.form.symbol.label') }} q-input.q-my-xs( - :rules="[rules.required]" + :debounce="200" + :disable="selectedDao.hasCustomToken || !isAdmin" + :filled="selectedDao.hasCustomToken || !isAdmin" + :placeholder="$t('configuration.settings-tokens.utility.form.symbol.placeholder')" + :rules="[rules.required, rules.isTokenAvailable]" dense - disable - filled lazy-rules + mask="AAAAAAAA" + maxlength="7" + outlined + ref="treasurySymbol" rounded - v-model='tokens.treasurySymbol' + v-model="tokens.treasurySymbol" ) q-tooltip(:content-style="{ 'font-size': '1em' }" anchor="top middle" self="bottom middle" v-if="!selectedDao.hasCustomToken") {{ $t('common.onlyDaoAdmins') }} .col-12(:class="{ 'invisible': selectedDao.hasCustomToken }") label.h-label {{ $t('configuration.settings-tokens.tresury.form.currency.label') }} q-select.q-my-xs( + :disable="!isAdmin" :options="currencies" :rules="[rules.required]" :style='{"min-height":"60px"}' @@ -224,8 +237,10 @@ export default { q-input.q-my-xs( :debounce="200" :disable="!selectedDao.hasCustomToken" + :max="100" + :min="0" :placeholder="$t('configuration.settings-tokens.tresury.form.value.placeholder')" - :rules="[rules.required]" + :rules="[rules.required, rules.greaterThanOrEqual(0), rules.lessOrEqualThan(100)]" bg-color="white" color="accent" dense @@ -241,7 +256,7 @@ export default { .col-12 label.h-label {{ $t('configuration.settings-tokens.tresury.form.digits.label') }} input-slider( - :disable="selectedDao.hasCustomToken" + :disable="selectedDao.hasCustomToken || !isAdmin" :max="3" :maxLabel="$t('configuration.settings-tokens.tresury.form.digits.morePrecise')" :min="1" @@ -262,8 +277,8 @@ export default { label.h-label {{ $t('configuration.settings-tokens.utility.form.name.label') }} q-input.q-my-xs( :debounce="200" - :disable="selectedDao.hasCustomToken" - :filled="selectedDao.hasCustomToken" + :disable="selectedDao.hasCustomToken || !isAdmin" + :filled="selectedDao.hasCustomToken || !isAdmin" :placeholder="$t('configuration.settings-tokens.utility.form.name.placeholder')" :rules="[rules.required]" color="accent" @@ -280,8 +295,8 @@ export default { label.h-label {{ $t('configuration.settings-tokens.utility.form.symbol.label') }} q-input.q-my-xs( :debounce="200" - :disable="selectedDao.hasCustomToken" - :filled="selectedDao.hasCustomToken" + :disable="selectedDao.hasCustomToken || !isAdmin" + :filled="selectedDao.hasCustomToken || !isAdmin" :placeholder="$t('configuration.settings-tokens.utility.form.symbol.placeholder')" :rules="[rules.required, rules.isTokenAvailable]" dense @@ -299,8 +314,8 @@ export default { label.h-label {{ $t('configuration.settings-tokens.utility.form.value.label') }} q-input.q-my-xs( :debounce="200" - :disable="selectedDao.hasCustomToken" - :filled="selectedDao.hasCustomToken" + :disable="selectedDao.hasCustomToken || !isAdmin" + :filled="selectedDao.hasCustomToken || !isAdmin" :placeholder="$t('configuration.settings-tokens.utility.form.value.placeholder')" :rules="[rules.requiredIf(tokens.utilityAmount > 0)]" color="accent" @@ -317,9 +332,11 @@ export default { label.h-label {{ $t('configuration.settings-tokens.utility.form.multiplier.label') }} q-input.q-my-xs( :debounce="200" - :disable="selectedDao.hasCustomToken" - :filled="selectedDao.hasCustomToken" - :rules="[rules.required]" + :disable="selectedDao.hasCustomToken || !isAdmin" + :filled="selectedDao.hasCustomToken || !isAdmin" + :max="100" + :min="0" + :rules="[rules.required, rules.greaterThanOrEqual(0), rules.lessOrEqualThan(100)]" color="accent" dense lazy-rules @@ -334,7 +351,7 @@ export default { .col-12 label.h-label {{ $t('configuration.settings-tokens.utility.form.digits.label') }} input-slider( - :disable="selectedDao.hasCustomToken" + :disable="selectedDao.hasCustomToken || !isAdmin" :max="3" :maxLabel="$t('configuration.settings-tokens.tresury.form.digits.morePrecise')" :min="1" @@ -384,17 +401,19 @@ export default { .row.q-col-gutter-md .col-12.col-md-8(:class="{'q-mt-sm': !$q.screen.gt.md}") label.h-label {{ $t('configuration.settings-tokens.voice.form.decayPeriod.label') }} - custom-period-input.q-my-xs(:disable="selectedDao.hasCustomToken" v-model='tokens.voiceDecayPeriod') + custom-period-input.q-my-xs(:disable="selectedDao.hasCustomToken || !isAdmin" v-model='tokens.voiceDecayPeriod') q-tooltip(:content-style="{ 'font-size': '1em' }" anchor="top middle" self="bottom middle" v-if="!selectedDao.hasCustomToken") {{ $t('common.onlyDaoAdmins') }} .col-12.col-md-4(:class="{'q-mt-sm': !$q.screen.gt.md}") label.h-label {{ $t('configuration.settings-tokens.voice.form.decayPercent.label') }} q-input.q-my-xs( :debounce="200" - :disable="selectedDao.hasCustomToken" - :filled="selectedDao.hasCustomToken" + :disable="selectedDao.hasCustomToken || !isAdmin" + :filled="selectedDao.hasCustomToken || !isAdmin" + :max="100" + :min="0" :placeholder="$t('configuration.settings-tokens.voice.form.decayPercent.placeholder')" - :rules="[rules.required]" + :rules="[rules.required, rules.greaterThanOrEqual(0), rules.lessOrEqualThan(100)]" color="accent" dense lazy-rules @@ -411,9 +430,11 @@ export default { label.h-label {{ $t('configuration.settings-tokens.voice.form.multiplier.label') }} q-input.q-my-xs( :debounce="200" - :disable="selectedDao.hasCustomToken" - :filled="selectedDao.hasCustomToken" - :rules="[rules.required]" + :disable="selectedDao.hasCustomToken || !isAdmin" + :filled="selectedDao.hasCustomToken || !isAdmin" + :max="100" + :min="0" + :rules="[rules.required, rules.greaterThanOrEqual(0), rules.lessOrEqualThan(100)]" color="accent" dense lazy-rules @@ -428,7 +449,7 @@ export default { .col-12 label.h-label {{ $t('configuration.settings-tokens.voice.form.digits.label') }} input-slider( - :disable="selectedDao.hasCustomToken" + :disable="selectedDao.hasCustomToken || !isAdmin" :max="3" :maxLabel="$t('configuration.settings-tokens.tresury.form.digits.morePrecise')" :min="1" diff --git a/src/components/dao/widget-circles.vue b/src/components/dao/widget-circles.vue index a79f6679d..bbaa4b15b 100644 --- a/src/components/dao/widget-circles.vue +++ b/src/components/dao/widget-circles.vue @@ -270,6 +270,7 @@ widget(:title="$t('configuration.settings-structure.circles.title')" titleImage= label.h-label {{ $t('configuration.settings-structure.circles.form.name.label') }} q-input.q-my-xs( :debounce="200" + :disable="!isAdmin" :placeholder="$t('configuration.settings-structure.circles.form.name.placeholder')" bg-color="white" color="accent" @@ -285,6 +286,7 @@ widget(:title="$t('configuration.settings-structure.circles.title')" titleImage= label.h-label {{ $t('configuration.settings-structure.circles.form.description.label') }} q-input.q-my-xs( :debounce="200" + :disable="!isAdmin" :input-style="{ 'resize': 'none' }" :placeholder="$t('configuration.settings-structure.circles.form.description.placeholder')" bg-color="white" @@ -302,6 +304,7 @@ widget(:title="$t('configuration.settings-structure.circles.title')" titleImage= nav.full-width.q-my-xl.row.justify-end q-btn.col-auto.q-px-xl.rounded-border.text-bold.q-mr-xs( + :disable="!isAdmin" :label="$t('configuration.settings-structure.circles.form.cancel')" @click="state = STATES.WAITING" color="white" @@ -311,6 +314,7 @@ widget(:title="$t('configuration.settings-structure.circles.title')" titleImage= unelevated ) q-btn.col-auto.q-px-xl.rounded-border.text-bold.q-ml-xs( + :disable="!isAdmin" :label="$t('configuration.settings-structure.circles.form.submit')" @click="_createCircle({...circle})" color="secondary" diff --git a/src/components/filters/filter-widget-mobile.vue b/src/components/filters/filter-widget-mobile.vue index c48c62293..4393abf9c 100644 --- a/src/components/filters/filter-widget-mobile.vue +++ b/src/components/filters/filter-widget-mobile.vue @@ -19,8 +19,7 @@ export default { transition(name="slide") .container .top-buttons.q-ma-md - q-btn(color="internal-bg" text-color="primary" rounded unelevated size="sm" padding="12px" icon="fas fa-times" @click="$emit('close')") - filter-widget.full-height(v-bind="{ ...$props, ...$attrs, ...$slots }" v-on="$listeners" :showViewSelector="false" @close-window="$emit('close')") + filter-widget.full-height(v-bind="{ ...$props, ...$attrs, ...$slots }" v-on="$listeners" mobile :showViewSelector="false" @close-window="$emit('close')") .bottom-buttons @@ -47,6 +46,7 @@ transition(name="slide") display: flex align-items: center justify-content: flex-end + margin-bottom: 80px .bottom-buttons display: flex align-items: center diff --git a/src/components/filters/filter-widget.vue b/src/components/filters/filter-widget.vue index 0d71896f3..cc025f9f4 100644 --- a/src/components/filters/filter-widget.vue +++ b/src/components/filters/filter-widget.vue @@ -19,6 +19,7 @@ export default { }, props: { + mobile: Boolean, optionArray: Array, circleArray: Array, filters: Array, @@ -126,6 +127,7 @@ export default {