diff --git a/src/resources/js/app.js b/src/resources/js/app.js --- a/src/resources/js/app.js +++ b/src/resources/js/app.js @@ -264,7 +264,7 @@ // TODO: Set locale argument according to the currently used locale return ((price || 0) / 100).toLocaleString('de-DE', { style: 'currency', currency: currency || 'CHF' }) }, - priceLabel(cost, discount) { + priceLabel(cost, discount, currency) { let index = '' if (discount) { @@ -272,7 +272,7 @@ index = '\u00B9' } - return this.price(cost) + '/' + this.$t('wallet.month') + index + return this.price(cost, currency) + '/' + this.$t('wallet.month') + index }, clickRecord(event) { if (!/^(a|button|svg|path)$/i.test(event.target.nodeName)) { diff --git a/src/resources/js/meet/app.js b/src/resources/js/meet/app.js --- a/src/resources/js/meet/app.js +++ b/src/resources/js/meet/app.js @@ -571,7 +571,7 @@ }) // Add an element for the count of unread messages on the chat button - button.append('<span class="badge badge-dark blinker">') + button.append('<span class="badge bg-dark blinker">') .on('click', () => { button.find('.badge').text('') chatCount = 0 diff --git a/src/resources/vue/Dashboard.vue b/src/resources/vue/Dashboard.vue --- a/src/resources/vue/Dashboard.vue +++ b/src/resources/vue/Dashboard.vue @@ -17,11 +17,11 @@ </router-link> <router-link v-if="status.enableWallets" class="card link-wallet" :to="{ name: 'wallet' }"> <svg-icon icon="wallet"></svg-icon><span class="name">{{ $t('dashboard.wallet') }}</span> - <span v-if="balance < 0" class="badge badge-danger">{{ $root.price(balance, currency) }}</span> + <span v-if="balance < 0" class="badge bg-danger">{{ $root.price(balance, currency) }}</span> </router-link> <router-link v-if="$root.hasSKU('meet')" class="card link-chat" :to="{ name: 'rooms' }"> <svg-icon icon="comments"></svg-icon><span class="name">{{ $t('dashboard.chat') }}</span> - <span class="badge badge-primary">{{ $t('dashboard.beta') }}</span> + <span class="badge bg-primary">{{ $t('dashboard.beta') }}</span> </router-link> <a v-if="webmailURL" class="card link-webmail" :href="webmailURL"> <svg-icon icon="envelope"></svg-icon><span class="name">{{ $t('dashboard.webmail') }}</span> diff --git a/src/resources/vue/Meet/Room.vue b/src/resources/vue/Meet/Room.vue --- a/src/resources/vue/Meet/Room.vue +++ b/src/resources/vue/Meet/Room.vue @@ -21,7 +21,7 @@ :title="$t('meet.menu-channel')" aria-haspopup="true" aria-expanded="false" > <svg-icon icon="headphones"></svg-icon> - <span class="badge badge-danger" v-if="session.channel">{{ session.channel.toUpperCase() }}</span> + <span class="badge bg-danger" v-if="session.channel">{{ session.channel.toUpperCase() }}</span> </button> <div class="dropdown-menu"> <a :class="'dropdown-item' + (!session.channel ? ' active' : '')" href="#" data-code="" @click="switchChannel">- {{ $t('form.none') }} -</a> diff --git a/src/resources/vue/Reseller/Dashboard.vue b/src/resources/vue/Reseller/Dashboard.vue --- a/src/resources/vue/Reseller/Dashboard.vue +++ b/src/resources/vue/Reseller/Dashboard.vue @@ -4,7 +4,7 @@ <div id="dashboard-nav" class="mt-3"> <router-link v-if="status.enableWallets" class="card link-wallet" :to="{ name: 'wallet' }"> <svg-icon icon="wallet"></svg-icon><span class="name">{{ $t('dashboard.wallet') }}</span> - <span :class="'badge badge-' + (balance < 0 ? 'danger' : 'success')">{{ $root.price(balance) }}</span> + <span :class="'badge bg-' + (balance < 0 ? 'danger' : 'success')">{{ $root.price(balance) }}</span> </router-link> <router-link class="card link-invitations" :to="{ name: 'invitations' }"> <svg-icon icon="envelope-open-text"></svg-icon><span class="name">{{ $t('dashboard.invitations') }}</span> diff --git a/src/resources/vue/Rooms.vue b/src/resources/vue/Rooms.vue --- a/src/resources/vue/Rooms.vue +++ b/src/resources/vue/Rooms.vue @@ -2,7 +2,7 @@ <div class="container" dusk="rooms-component"> <div id="meet-rooms" class="card"> <div class="card-body"> - <div class="card-title">{{ $t('meet.title') }} <small><sup class="badge badge-primary">{{ $t('dashboard.beta') }}</sup></small></div> + <div class="card-title">{{ $t('meet.title') }} <small><sup class="badge bg-primary">{{ $t('dashboard.beta') }}</sup></small></div> <div class="card-text"> <p>{{ $t('meet.welcome') }}</p> <p>{{ $t('meet.url') }}</p> diff --git a/src/resources/vue/User/Info.vue b/src/resources/vue/User/Info.vue --- a/src/resources/vue/User/Info.vue +++ b/src/resources/vue/User/Info.vue @@ -102,7 +102,7 @@ <label :for="'pkg-input-' + pkg.id">{{ pkg.name }}</label> </td> <td class="price text-nowrap"> - {{ $root.priceLabel(pkg.cost, discount) }} + {{ $root.priceLabel(pkg.cost, discount, currency) }} </td> <td class="buttons"> <button v-if="pkg.description" type="button" class="btn btn-link btn-lg p-0" v-tooltip="pkg.description"> @@ -154,7 +154,7 @@ </div> </td> <td class="price text-nowrap"> - {{ $root.priceLabel(sku.cost, discount) }} + {{ $root.priceLabel(sku.cost, discount, currency) }} </td> <td class="buttons"> <button v-if="sku.description" type="button" class="btn btn-link btn-lg p-0" v-tooltip="sku.description"> @@ -226,6 +226,7 @@ }, data() { return { + currency: '', discount: 0, discount_description: '', user_id: null, @@ -245,9 +246,12 @@ wallet = this.$store.state.authInfo.wallets[0] } - if (wallet && wallet.discount) { - this.discount = wallet.discount - this.discount_description = wallet.discount_description + if (wallet) { + this.currency = wallet.currency + if (wallet.discount) { + this.discount = wallet.discount + this.discount_description = wallet.discount_description + } } this.$root.startLoading() @@ -444,7 +448,7 @@ input.prev().text(value + ' ' + sku.range.unit) // Update the price - record.find('.price').text(this.$root.priceLabel(cost, this.discount)) + record.find('.price').text(this.$root.priceLabel(cost, this.discount, this.currency)) }, findSku(id) { for (let i = 0; i < this.skus.length; i++) { diff --git a/src/tests/Browser/Reseller/WalletTest.php b/src/tests/Browser/Reseller/WalletTest.php --- a/src/tests/Browser/Reseller/WalletTest.php +++ b/src/tests/Browser/Reseller/WalletTest.php @@ -64,7 +64,7 @@ ->submitLogon('reseller@' . \config('app.domain'), \App\Utils::generatePassphrase(), true) ->on(new Dashboard()) ->assertSeeIn('@links .link-wallet .name', 'Wallet') - ->assertSeeIn('@links .link-wallet .badge-success', '1,25 CHF'); + ->assertSeeIn('@links .link-wallet .badge.bg-success', '1,25 CHF'); }); Wallet::where('user_id', $reseller->id)->update(['balance' => -1234]); @@ -73,7 +73,7 @@ $this->browse(function (Browser $browser) { $browser->visit(new Dashboard()) ->assertSeeIn('@links .link-wallet .name', 'Wallet') - ->assertSeeIn('@links .link-wallet .badge-danger', '-12,34 CHF'); + ->assertSeeIn('@links .link-wallet .badge.bg-danger', '-12,34 CHF'); }); } diff --git a/src/tests/Browser/UsersTest.php b/src/tests/Browser/UsersTest.php --- a/src/tests/Browser/UsersTest.php +++ b/src/tests/Browser/UsersTest.php @@ -16,6 +16,7 @@ use Tests\Browser\Pages\Home; use Tests\Browser\Pages\UserInfo; use Tests\Browser\Pages\UserList; +use Tests\Browser\Pages\Wallet as WalletPage; use Tests\TestCaseDusk; use Illuminate\Foundation\Testing\DatabaseMigrations; @@ -50,6 +51,7 @@ $wallet = $john->wallets()->first(); $wallet->discount()->dissociate(); + $wallet->currency = 'CHF'; $wallet->save(); $this->clearBetaEntitlements(); @@ -680,6 +682,68 @@ } /** + * Test non-default currency in the UI + */ + public function testCurrency(): void + { + // Add 10% discount + $john = User::where('email', 'john@kolab.org')->first(); + $wallet = $john->wallet(); + $wallet->balance = -1000; + $wallet->currency = 'EUR'; + $wallet->save(); + + // On Dashboard and the wallet page + $this->browse(function (Browser $browser) { + $browser->visit('/logout') + ->on(new Home()) + ->submitLogon('john@kolab.org', 'simple123', true) + ->on(new Dashboard()) + ->assertSeeIn('@links .link-wallet .badge', '-10,00 €') + ->click('@links .link-wallet') + ->on(new WalletPage()) + ->assertSeeIn('#wallet .card-title', 'Account balance -10,00 €'); + }); + + // SKUs on user edit page + $this->browse(function (Browser $browser) { + $browser->visit(new UserList()) + ->waitFor('@table tr:nth-child(2)') + ->click('@table tr:nth-child(2) a') // joe@kolab.org + ->on(new UserInfo()) + ->with('@general', function (Browser $browser) { + $browser->whenAvailable('@skus', function (Browser $browser) { + $quota_input = new QuotaInput('tbody tr:nth-child(2) .range-input'); + $browser->waitFor('tbody tr') + ->assertElementsCount('tbody tr', 6) + // Mailbox SKU + ->assertSeeIn('tbody tr:nth-child(1) td.price', '5,00 €/month') + // Storage SKU + ->assertSeeIn('tr:nth-child(2) td.price', '0,00 €/month') + ->with($quota_input, function (Browser $browser) { + $browser->setQuotaValue(100); + }) + ->assertSeeIn('tr:nth-child(2) td.price', '23,75 €/month'); + }); + }); + }); + + // Packages on new user page + $this->browse(function (Browser $browser) { + $browser->visit(new UserList()) + ->click('button.create-user') + ->on(new UserInfo()) + ->with('@general', function (Browser $browser) { + $browser->whenAvailable('@packages', function (Browser $browser) { + $browser->assertElementsCount('tbody tr', 2) + ->assertSeeIn('tbody tr:nth-child(1) .price', '9,90 €/month') // Groupware + ->assertSeeIn('tbody tr:nth-child(2) .price', '5,00 €/month'); // Lite + }); + }); + }); + } + + /** * Test beta entitlements * * @depends testList