Page MenuHomePhorge

D3557.1775180032.diff
No OneTemporary

Authored By
Unknown
Size
52 KB
Referenced Files
None
Subscribers
None

D3557.1775180032.diff

diff --git a/src/phpunit.xml b/src/phpunit.xml
--- a/src/phpunit.xml
+++ b/src/phpunit.xml
@@ -23,24 +23,7 @@
<testsuite name="Browser">
<directory suffix="Test.php">tests/Browser</directory>
- <exclude>tests/Browser/Reseller/DashboardTest.php</exclude>
- <exclude>tests/Browser/Reseller/DistlistTest.php</exclude>
- <exclude>tests/Browser/Reseller/DomainTest.php</exclude>
- <exclude>tests/Browser/Reseller/InvitationsTest.php</exclude>
- <exclude>tests/Browser/Reseller/LogonTest.php</exclude>
- <exclude>tests/Browser/Reseller/PaymentMollieTest.php</exclude>
- <exclude>tests/Browser/Reseller/ResourceTest.php</exclude>
- <exclude>tests/Browser/Reseller/SharedFolderTest.php</exclude>
- <exclude>tests/Browser/Reseller/StatsTest.php</exclude>
- <exclude>tests/Browser/Reseller/UserTest.php</exclude>
- <exclude>tests/Browser/Reseller/WalletTest.php</exclude>
- <exclude>tests/Browser/Reseller/UserFinancesTest.php</exclude>
- <exclude>tests/Browser/LogonTest.php</exclude>
- <exclude>tests/Browser/SignupTest.php</exclude>
<exclude>tests/Browser/PaymentStripeTest.php</exclude>
- <exclude>tests/Browser/Meet/RoomSetupTest.php</exclude>
- <exclude>tests/Browser/Meet/RoomControlsTest.php</exclude>
- <exclude>tests/Browser/Meet/RoomModeratorTest.php</exclude>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
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
@@ -9,7 +9,6 @@
import AppComponent from '../vue/App'
import MenuComponent from '../vue/Widgets/Menu'
import SupportForm from '../vue/Widgets/SupportForm'
-import { Tab } from 'bootstrap'
import { loadLangAsync, i18n } from './locale'
import { clearFormValidation, pick, startLoading, stopLoading } from './utils'
@@ -169,10 +168,6 @@
pick,
startLoading,
stopLoading,
- tab(e) {
- e.preventDefault()
- new Tab(e.target).show()
- },
errorPage(code, msg, hint) {
// Until https://github.com/vuejs/vue-router/issues/977 is implemented
// we can't really use router to display error page as it has two side
@@ -206,6 +201,10 @@
this.logoutUser(false)
}
} else {
+ if (!error.response) {
+ console.error(error)
+ }
+
this.errorPage(status, message)
}
},
diff --git a/src/resources/js/bootstrap.js b/src/resources/js/bootstrap.js
--- a/src/resources/js/bootstrap.js
+++ b/src/resources/js/bootstrap.js
@@ -27,15 +27,17 @@
import VueRouter from 'vue-router'
import Btn from '../vue/Widgets/Btn'
import BtnRouter from '../vue/Widgets/BtnRouter'
+import Tabs from '../vue/Widgets/Tabs'
import Toast from '../vue/Widgets/Toast'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { Tooltip } from 'bootstrap'
window.Vue = Vue
-Vue.component('SvgIcon', FontAwesomeIcon)
Vue.component('Btn', Btn)
Vue.component('BtnRouter', BtnRouter)
+Vue.component('SvgIcon', FontAwesomeIcon)
+Vue.component('Tabs', Tabs)
const vTooltip = (el, binding) => {
let t = []
@@ -62,7 +64,6 @@
})
Vue.use(Toast)
-
Vue.use(VueRouter)
let vueRouterBase = '/'
diff --git a/src/resources/lang/en/ui.php b/src/resources/lang/en/ui.php
--- a/src/resources/lang/en/ui.php
+++ b/src/resources/lang/en/ui.php
@@ -430,7 +430,6 @@
'add-beta' => "Enable beta program",
'address' => "Address",
'aliases' => "Aliases",
- 'aliases-email' => "Email Aliases",
'aliases-none' => "This user has no email aliases.",
'add-bonus' => "Add bonus",
'add-bonus-title' => "Add a bonus to the wallet",
@@ -455,6 +454,7 @@
'distlists' => "Distribution lists",
'domains' => "Domains",
'ext-email' => "External Email",
+ 'email-aliases' => "Email Aliases",
'finances' => "Finances",
'greylisting' => "Greylisting",
'greylisting-text' => "Greylisting is a method of defending users against spam. Any incoming mail from an unrecognized sender "
diff --git a/src/resources/lang/fr/ui.php b/src/resources/lang/fr/ui.php
--- a/src/resources/lang/fr/ui.php
+++ b/src/resources/lang/fr/ui.php
@@ -383,7 +383,6 @@
'add-beta' => "Activer le programme bêta",
'address' => "Adresse",
'aliases' => "Alias",
- 'aliases-email' => "Alias E-mail",
'aliases-none' => "Cet utilisateur n'aucune alias e-mail.",
'add-bonus' => "Ajouter un bonus",
'add-bonus-title' => "Ajouter un bonus au portefeuille",
@@ -406,6 +405,7 @@
'discount-title' => "Rabais de compte",
'distlists' => "Listes de Distribution",
'domains' => "Domaines",
+ 'email-aliases' => "Alias E-mail",
'ext-email' => "E-mail externe",
'finances' => "Finances",
'greylisting' => "Greylisting",
diff --git a/src/resources/vue/Admin/Distlist.vue b/src/resources/vue/Admin/Distlist.vue
--- a/src/resources/vue/Admin/Distlist.vue
+++ b/src/resources/vue/Admin/Distlist.vue
@@ -47,15 +47,9 @@
</div>
</div>
</div>
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-settings" href="#distlist-settings" role="tab" aria-controls="distlist-settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="['form.settings']"></tabs>
<div class="tab-content">
- <div class="tab-pane show active" id="distlist-settings" role="tabpanel" aria-labelledby="tab-settings">
+ <div class="tab-pane show active" id="settings" role="tabpanel" aria-labelledby="tab-settings">
<div class="card-body">
<div class="card-text">
<form class="read-only short">
diff --git a/src/resources/vue/Admin/Domain.vue b/src/resources/vue/Admin/Domain.vue
--- a/src/resources/vue/Admin/Domain.vue
+++ b/src/resources/vue/Admin/Domain.vue
@@ -35,20 +35,9 @@
</div>
</div>
</div>
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-config" href="#domain-config" role="tab" aria-controls="domain-config" aria-selected="true" @click="$root.tab">
- {{ $t('form.config') }}
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-settings" href="#domain-settings" role="tab" aria-controls="domain-settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="['form.config', 'form.settings']"></tabs>
<div class="tab-content">
- <div class="tab-pane show active" id="domain-config" role="tabpanel" aria-labelledby="tab-config">
+ <div class="tab-pane show active" id="config" role="tabpanel" aria-labelledby="tab-config">
<div class="card-body">
<div class="card-text">
<p>{{ $t('domain.dns-verify') }}</p>
@@ -58,7 +47,7 @@
</div>
</div>
</div>
- <div class="tab-pane" id="domain-settings" role="tabpanel" aria-labelledby="tab-settings">
+ <div class="tab-pane" id="settings" role="tabpanel" aria-labelledby="tab-settings">
<div class="card-body">
<div class="card-text">
<form class="read-only short">
diff --git a/src/resources/vue/Admin/Resource.vue b/src/resources/vue/Admin/Resource.vue
--- a/src/resources/vue/Admin/Resource.vue
+++ b/src/resources/vue/Admin/Resource.vue
@@ -31,15 +31,9 @@
</div>
</div>
</div>
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-settings" href="#resource-settings" role="tab" aria-controls="resource-settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="['form.settings']"></tabs>
<div class="tab-content">
- <div class="tab-pane show active" id="resource-settings" role="tabpanel" aria-labelledby="tab-settings">
+ <div class="tab-pane show active" id="settings" role="tabpanel" aria-labelledby="tab-settings">
<div class="card-body">
<div class="card-text">
<form class="read-only short">
diff --git a/src/resources/vue/Admin/SharedFolder.vue b/src/resources/vue/Admin/SharedFolder.vue
--- a/src/resources/vue/Admin/SharedFolder.vue
+++ b/src/resources/vue/Admin/SharedFolder.vue
@@ -37,20 +37,9 @@
</div>
</div>
</div>
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-settings" href="#folder-settings" role="tab" aria-controls="folder-settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-aliases" href="#folder-aliases" role="tab" aria-controls="folder-aliases" aria-selected="false" @click="$root.tab">
- {{ $t('user.aliases-email') }} ({{ folder.aliases.length }})
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="tabs" ref="tabs"></tabs>
<div class="tab-content">
- <div class="tab-pane show active" id="folder-settings" role="tabpanel" aria-labelledby="tab-settings">
+ <div class="tab-pane show active" id="settings" role="tabpanel" aria-labelledby="tab-settings">
<div class="card-body">
<div class="card-text">
<form class="read-only short">
@@ -71,7 +60,7 @@
</div>
</div>
</div>
- <div class="tab-pane" id="folder-aliases" role="tabpanel" aria-labelledby="tab-aliases">
+ <div class="tab-pane" id="aliases" role="tabpanel" aria-labelledby="tab-aliases">
<div class="card-body">
<div class="card-text">
<list-table :list="folder.aliases" :setup="aliasesListSetup" class="mb-0"></list-table>
@@ -100,13 +89,18 @@
],
footLabel: 'shf.aliases-none'
},
- folder: { config: {}, aliases: [] }
+ folder: { config: {}, aliases: [] },
+ tabs: [
+ { label: 'form.settings' },
+ { label: 'user.email-aliases', count: 0 }
+ ]
}
},
created() {
axios.get('/api/v4/shared-folders/' + this.$route.params.folder, { loader: true })
.then(response => {
this.folder = response.data
+ this.tabs[1].count = this.folder.aliases.length
})
.catch(this.$root.errorHandler)
}
diff --git a/src/resources/vue/Admin/User.vue b/src/resources/vue/Admin/User.vue
--- a/src/resources/vue/Admin/User.vue
+++ b/src/resources/vue/Admin/User.vue
@@ -86,55 +86,9 @@
</div>
</div>
</div>
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-finances" href="#user-finances" role="tab" aria-controls="user-finances" aria-selected="true">
- {{ $t('user.finances') }}
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-aliases" href="#user-aliases" role="tab" aria-controls="user-aliases" aria-selected="false">
- {{ $t('user.aliases') }} ({{ user.aliases.length }})
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-subscriptions" href="#user-subscriptions" role="tab" aria-controls="user-subscriptions" aria-selected="false">
- {{ $t('user.subscriptions') }} ({{ skus.length }})
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-domains" href="#user-domains" role="tab" aria-controls="user-domains" aria-selected="false">
- {{ $t('user.domains') }} ({{ domains.length }})
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-users" href="#user-users" role="tab" aria-controls="user-users" aria-selected="false">
- {{ $t('user.users') }} ({{ users.length }})
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-distlists" href="#user-distlists" role="tab" aria-controls="user-distlists" aria-selected="false">
- {{ $t('user.distlists') }} ({{ distlists.length }})
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-resources" href="#user-resources" role="tab" aria-controls="user-resources" aria-selected="false">
- {{ $t('user.resources') }} ({{ resources.length }})
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-shared-folders" href="#user-shared-folders" role="tab" aria-controls="user-shared-folders" aria-selected="false">
- {{ $t('dashboard.shared-folders') }} ({{ folders.length }})
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-settings" href="#user-settings" role="tab" aria-controls="user-settings" aria-selected="false">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="tabs" ref="tabs"></tabs>
<div class="tab-content">
- <div class="tab-pane show active" id="user-finances" role="tabpanel" aria-labelledby="tab-finances">
+ <div class="tab-pane show active" id="finances" role="tabpanel" aria-labelledby="tab-finances">
<div class="card-body">
<h2 class="card-title">
{{ $t('wallet.title') }}
@@ -181,14 +135,14 @@
<transaction-log v-if="wallet.id && !walletReload" class="card-text" :wallet-id="wallet.id" :is-admin="true"></transaction-log>
</div>
</div>
- <div class="tab-pane" id="user-aliases" role="tabpanel" aria-labelledby="tab-aliases">
+ <div class="tab-pane" id="aliases" role="tabpanel" aria-labelledby="tab-aliases">
<div class="card-body">
<div class="card-text">
<list-table :list="user.aliases" :setup="aliasesListSetup" class="mb-0"></list-table>
</div>
</div>
</div>
- <div class="tab-pane" id="user-subscriptions" role="tabpanel" aria-labelledby="tab-subscriptions">
+ <div class="tab-pane" id="subscriptions" role="tabpanel" aria-labelledby="tab-subscriptions">
<div class="card-body">
<div class="card-text">
<list-table :list="skus" :setup="skusListSetup" class="mb-0"></list-table>
@@ -203,42 +157,42 @@
</div>
</div>
</div>
- <div class="tab-pane" id="user-domains" role="tabpanel" aria-labelledby="tab-domains">
+ <div class="tab-pane" id="domains" role="tabpanel" aria-labelledby="tab-domains">
<div class="card-body">
<div class="card-text">
<domain-list :list="domains" class="mb-0"></domain-list>
</div>
</div>
</div>
- <div class="tab-pane" id="user-users" role="tabpanel" aria-labelledby="tab-users">
+ <div class="tab-pane" id="users" role="tabpanel" aria-labelledby="tab-users">
<div class="card-body">
<div class="card-text">
<user-list :list="users" :current="user" class="mb-0"></user-list>
</div>
</div>
</div>
- <div class="tab-pane" id="user-distlists" role="tabpanel" aria-labelledby="tab-distlists">
+ <div class="tab-pane" id="distlists" role="tabpanel" aria-labelledby="tab-distlists">
<div class="card-body">
<div class="card-text">
<distlist-list :list="distlists" class="mb-0"></distlist-list>
</div>
</div>
</div>
- <div class="tab-pane" id="user-resources" role="tabpanel" aria-labelledby="tab-resources">
+ <div class="tab-pane" id="resources" role="tabpanel" aria-labelledby="tab-resources">
<div class="card-body">
<div class="card-text">
<resource-list :list="resources" class="mb-0"></resource-list>
</div>
</div>
</div>
- <div class="tab-pane" id="user-shared-folders" role="tabpanel" aria-labelledby="tab-shared-folders">
+ <div class="tab-pane" id="folders" role="tabpanel" aria-labelledby="tab-folders">
<div class="card-body">
<div class="card-text">
<shared-folder-list :list="folders" :with-email="true" class="mb-0"></shared-folder-list>
</div>
</div>
</div>
- <div class="tab-pane" id="user-settings" role="tabpanel" aria-labelledby="tab-settings">
+ <div class="tab-pane" id="settings" role="tabpanel" aria-labelledby="tab-settings">
<div class="card-body">
<div class="card-text">
<form class="read-only short">
@@ -379,6 +333,17 @@
footLabel: 'user.subscriptions-none',
model: 'sku'
},
+ tabs: [
+ { label: 'user.finances' },
+ { label: 'user.aliases', count: 0 },
+ { label: 'user.subscriptions', count: 0 },
+ { label: 'user.domains', count: 0 },
+ { label: 'user.users', count: 0 },
+ { label: 'user.distlists', count: 0 },
+ { label: 'user.resources', count: 0 },
+ { label: 'dashboard.shared-folders', count: 0 },
+ { label: 'form.settings' }
+ ],
users: [],
user: {
aliases: [],
@@ -395,7 +360,7 @@
.then(response => {
this.user = response.data
- const loader = '#user-finances'
+ const loader = '#finances'
const keys = ['first_name', 'last_name', 'external_email', 'billing_address', 'phone', 'organization']
let country = this.user.settings.country
@@ -410,6 +375,8 @@
this.discount = this.user.wallet.discount
this.discount_description = this.user.wallet.discount_description
+ this.$refs.tabs.updateCounter('aliases', this.user.aliases.length)
+
// TODO: currencies, multi-wallets, accounts
// Get more info about the wallet (e.g. payment provider related)
axios.get('/api/v4/wallets/' + this.user.wallets[0].id, { loader })
@@ -447,6 +414,8 @@
}
}
})
+
+ this.$refs.tabs.updateCounter('subscriptions', this.skus.length)
})
// Fetch users
@@ -454,37 +423,40 @@
axios.get('/api/v4/users?owner=' + user_id)
.then(response => {
this.users = response.data.list;
+ this.$refs.tabs.updateCounter('users', this.users.length)
})
// Fetch domains
axios.get('/api/v4/domains?owner=' + user_id)
.then(response => {
this.domains = response.data.list
+ this.$refs.tabs.updateCounter('domains', this.domains.length)
})
// Fetch distribution lists
axios.get('/api/v4/groups?owner=' + user_id)
.then(response => {
this.distlists = response.data.list
+ this.$refs.tabs.updateCounter('distlists', this.distlists.length)
})
// Fetch resources lists
axios.get('/api/v4/resources?owner=' + user_id)
.then(response => {
this.resources = response.data.list
+ this.$refs.tabs.updateCounter('resources', this.resources.length)
})
// Fetch shared folders lists
axios.get('/api/v4/shared-folders?owner=' + user_id)
.then(response => {
this.folders = response.data.list
+ this.$refs.tabs.updateCounter('folders', this.folders.length)
})
})
.catch(this.$root.errorHandler)
},
mounted() {
- $(this.$el).find('ul.nav-tabs a').on('click', this.$root.tab)
-
this.$refs.discountDialog.events({
shown: () => {
// Note: Vue v-model is strict, convert null to a string
@@ -506,6 +478,8 @@
cost: sku.cost,
price: this.$root.priceLabel(sku.cost, this.discount)
})
+
+ this.$refs.tabs.updateCounter('subscriptions', this.skus.length)
}
})
},
@@ -561,6 +535,7 @@
this.$toast.success(response.data.message)
this.skus = this.skus.filter(sku => sku.id != this.sku2FA)
this.has2FA = false
+ this.$refs.tabs.updateCounter('subscriptions', this.skus.length)
}
})
},
diff --git a/src/resources/vue/CompanionApp.vue b/src/resources/vue/CompanionApp.vue
--- a/src/resources/vue/CompanionApp.vue
+++ b/src/resources/vue/CompanionApp.vue
@@ -13,22 +13,9 @@
</div>
</div>
</div>
-
- <ul class="nav nav-tabs mt-2" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-qrcode" href="#companion-qrcode" role="tab" aria-controls="companion-qrcode" aria-selected="true" @click="$root.tab">
- {{ $t('companion.pair-new') }}
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-list" href="#companion-list" role="tab" aria-controls="companion-list" aria-selected="false" @click="$root.tab">
- {{ $t('companion.paired') }}
- </a>
- </li>
- </ul>
-
+ <tabs class="mt-3" :tabs="['companion.pair-new','companion.paired']"></tabs>
<div class="tab-content">
- <div class="tab-pane active" id="companion-qrcode" role="tabpanel" aria-labelledby="tab-qrcode">
+ <div class="tab-pane active" id="new" role="tabpanel" aria-labelledby="tab-new">
<div class="card-body">
<div class="card-text">
<p>
@@ -40,13 +27,12 @@
</div>
</div>
</div>
- <div class="tab-pane" id="companion-list" role="tabpanel" aria-labelledby="tab-list">
+ <div class="tab-pane" id="paired" role="tabpanel" aria-labelledby="tab-paired">
<div class="card-body">
<companionapp-list class="card-text"></companionapp-list>
</div>
</div>
</div>
-
</div>
</template>
diff --git a/src/resources/vue/Distlist/Info.vue b/src/resources/vue/Distlist/Info.vue
--- a/src/resources/vue/Distlist/Info.vue
+++ b/src/resources/vue/Distlist/Info.vue
@@ -8,20 +8,9 @@
{{ $tc('distlist.list-title', 1) }}
<btn class="btn-outline-danger button-delete float-end" @click="deleteList()" icon="trash-can">{{ $t('distlist.delete') }}</btn>
</div>
- <div class="card-title" v-if="list_id === 'new'">{{ $t('distlist.new') }}</div>
+ <div class="card-title" v-else>{{ $t('distlist.new') }}</div>
<div class="card-text">
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-general" href="#general" role="tab" aria-controls="general" aria-selected="true" @click="$root.tab">
- {{ $t('form.general') }}
- </a>
- </li>
- <li v-if="list_id !== 'new'" class="nav-item">
- <a class="nav-link" id="tab-settings" href="#settings" role="tab" aria-controls="settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="list_id === 'new' ? ['form.general'] : ['form.general','form.settings']"></tabs>
<div class="tab-content">
<div class="tab-pane show active" id="general" role="tabpanel" aria-labelledby="tab-general">
<form @submit.prevent="submit" class="card-body">
diff --git a/src/resources/vue/Domain/Info.vue b/src/resources/vue/Domain/Info.vue
--- a/src/resources/vue/Domain/Info.vue
+++ b/src/resources/vue/Domain/Info.vue
@@ -9,18 +9,7 @@
<btn class="btn-outline-danger button-delete float-end" @click="$refs.deleteDialog.show()" icon="trash-can">{{ $t('domain.delete') }}</btn>
</div>
<div class="card-text">
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-general" href="#general" role="tab" aria-controls="general" aria-selected="true" @click="$root.tab">
- {{ $t('form.general') }}
- </a>
- </li>
- <li class="nav-item" v-if="domain.id">
- <a class="nav-link" id="tab-settings" href="#settings" role="tab" aria-controls="settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="domain_id === 'new' ? ['form.general'] : ['form.general','form.settings']"></tabs>
<div class="tab-content">
<div class="tab-pane show active" id="general" role="tabpanel" aria-labelledby="tab-general">
<form @submit.prevent="submit" class="card-body">
diff --git a/src/resources/vue/File/Info.vue b/src/resources/vue/File/Info.vue
--- a/src/resources/vue/File/Info.vue
+++ b/src/resources/vue/File/Info.vue
@@ -7,18 +7,7 @@
<btn v-if="file.canDelete" class="btn-outline-danger button-delete float-end" @click="fileDelete" icon="trash-can">{{ $t('file.delete') }}</btn>
</div>
<div class="card-text">
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-general" href="#general" role="tab" aria-controls="general" aria-selected="true" @click="$root.tab">
- {{ $t('form.general') }}
- </a>
- </li>
- <li class="nav-item" v-if="file.isOwner">
- <a class="nav-link" id="tab-sharing" href="#sharing" role="tab" aria-controls="sharing" aria-selected="false" @click="$root.tab">
- {{ $t('file.sharing') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="file.isOwner ? ['form.general','file.sharing'] : ['form.general']"></tabs>
<div class="tab-content">
<form class="tab-pane show active card-body read-only short" id="general" role="tabpanel" aria-labelledby="tab-general">
<div class="row plaintext">
diff --git a/src/resources/vue/Resource/Info.vue b/src/resources/vue/Resource/Info.vue
--- a/src/resources/vue/Resource/Info.vue
+++ b/src/resources/vue/Resource/Info.vue
@@ -10,18 +10,7 @@
</div>
<div class="card-title" v-if="resource_id === 'new'">{{ $t('resource.new') }}</div>
<div class="card-text">
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-general" href="#general" role="tab" aria-controls="general" aria-selected="true" @click="$root.tab">
- {{ $t('form.general') }}
- </a>
- </li>
- <li v-if="resource_id !== 'new'" class="nav-item">
- <a class="nav-link" id="tab-settings" href="#settings" role="tab" aria-controls="settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="resource_id === 'new' ? ['form.general'] : ['form.general','form.settings']"></tabs>
<div class="tab-content">
<div class="tab-pane show active" id="general" role="tabpanel" aria-labelledby="tab-general">
<form @submit.prevent="submit" class="card-body">
diff --git a/src/resources/vue/SharedFolder/Info.vue b/src/resources/vue/SharedFolder/Info.vue
--- a/src/resources/vue/SharedFolder/Info.vue
+++ b/src/resources/vue/SharedFolder/Info.vue
@@ -10,18 +10,7 @@
</div>
<div class="card-title" v-if="folder_id === 'new'">{{ $t('shf.new') }}</div>
<div class="card-text">
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-general" href="#general" role="tab" aria-controls="general" aria-selected="true" @click="$root.tab">
- {{ $t('form.general') }}
- </a>
- </li>
- <li v-if="folder_id !== 'new'" class="nav-item">
- <a class="nav-link" id="tab-settings" href="#settings" role="tab" aria-controls="settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="folder_id === 'new' ? ['form.general'] : ['form.general', 'form.settings']"></tabs>
<div class="tab-content">
<div class="tab-pane show active" id="general" role="tabpanel" aria-labelledby="tab-general">
<form @submit.prevent="submit" class="card-body">
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
@@ -11,18 +11,7 @@
</div>
<div class="card-title" v-if="user_id === 'new'">{{ $t('user.new') }}</div>
<div class="card-text">
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-general" href="#general" role="tab" aria-controls="general" aria-selected="true" @click="$root.tab">
- {{ $t('form.general') }}
- </a>
- </li>
- <li v-if="user_id !== 'new'" class="nav-item">
- <a class="nav-link" id="tab-settings" href="#settings" role="tab" aria-controls="settings" aria-selected="false" @click="$root.tab">
- {{ $t('form.settings') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" :tabs="user_id === 'new' ? ['form.general'] : ['form.general','form.settings']"></tabs>
<div class="tab-content">
<div class="tab-pane show active" id="general" role="tabpanel" aria-labelledby="tab-general">
<form @submit.prevent="submit" class="card-body">
@@ -57,7 +46,7 @@
</div>
</div>
<div class="row mb-3">
- <label for="aliases-input" class="col-sm-4 col-form-label">{{ $t('user.aliases-email') }}</label>
+ <label for="aliases-input" class="col-sm-4 col-form-label">{{ $t('user.email-aliases') }}</label>
<div class="col-sm-8">
<list-input id="aliases" :list="user.aliases"></list-input>
</div>
diff --git a/src/resources/vue/Wallet.vue b/src/resources/vue/Wallet.vue
--- a/src/resources/vue/Wallet.vue
+++ b/src/resources/vue/Wallet.vue
@@ -41,25 +41,10 @@
</div>
</div>
- <ul class="nav nav-tabs mt-3" role="tablist">
- <li class="nav-item">
- <a class="nav-link active" id="tab-receipts" href="#wallet-receipts" role="tab" aria-controls="wallet-receipts" aria-selected="true">
- {{ $t('wallet.receipts') }}
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link" id="tab-history" href="#wallet-history" role="tab" aria-controls="wallet-history" aria-selected="false">
- {{ $t('wallet.history') }}
- </a>
- </li>
- <li v-if="showPendingPayments" class="nav-item">
- <a class="nav-link" id="tab-payments" href="#wallet-payments" role="tab" aria-controls="wallet-payments" aria-selected="false">
- {{ $t('wallet.pending-payments') }}
- </a>
- </li>
- </ul>
+ <tabs class="mt-3" ref="tabs" :tabs="tabs"></tabs>
+
<div class="tab-content">
- <div class="tab-pane active" id="wallet-receipts" role="tabpanel" aria-labelledby="tab-receipts">
+ <div class="tab-pane active" id="receipts" role="tabpanel" aria-labelledby="tab-receipts">
<div class="card-body">
<div class="card-text">
<p v-if="receipts.length">
@@ -77,12 +62,12 @@
</div>
</div>
</div>
- <div class="tab-pane" id="wallet-history" role="tabpanel" aria-labelledby="tab-history">
+ <div class="tab-pane" id="history" role="tabpanel" aria-labelledby="tab-history">
<div class="card-body">
<transaction-log v-if="walletId && loadTransactions" class="card-text" :wallet-id="walletId"></transaction-log>
</div>
</div>
- <div class="tab-pane" id="wallet-payments" role="tabpanel" aria-labelledby="tab-payments">
+ <div class="tab-pane" id="payments" role="tabpanel" aria-labelledby="tab-payments">
<div class="card-body">
<payment-log v-if="walletId && loadPayments" class="card-text" :wallet-id="walletId"></payment-log>
</div>
@@ -213,6 +198,13 @@
}
return [ button ]
+ },
+ tabs() {
+ let tabs = [ 'wallet.receipts', 'wallet.history' ]
+ if (this.showPendingPayments) {
+ tabs.push('wallet.pending-payments')
+ }
+ return tabs
}
},
mounted() {
@@ -224,7 +216,7 @@
.then(response => {
this.wallet = response.data
- axios.get('/api/v4/wallets/' + this.walletId + '/receipts', { loader: '#wallet-receipts' })
+ axios.get('/api/v4/wallets/' + this.walletId + '/receipts', { loader: '#receipts' })
.then(response => {
this.receipts = response.data.list
})
@@ -241,17 +233,9 @@
.then(response => {
this.showPendingPayments = response.data.hasPending
})
- },
- updated() {
- $(this.$el).find('ul.nav-tabs a').on('click', e => {
- this.$root.tab(e)
-
- if ($(e.target).is('#tab-history')) {
- this.loadTransactions = true
- } else if ($(e.target).is('#tab-payments')) {
- this.loadPayments = true
- }
- })
+
+ this.$refs.tabs.clickHandler('history', () => { this.loadTransactions = true })
+ this.$refs.tabs.clickHandler('payments', () => { this.loadPayments = true })
},
methods: {
loadMandate() {
diff --git a/src/resources/vue/Widgets/Tabs.vue b/src/resources/vue/Widgets/Tabs.vue
new file mode 100644
--- /dev/null
+++ b/src/resources/vue/Widgets/Tabs.vue
@@ -0,0 +1,65 @@
+<template>
+ <ul class="nav nav-tabs" role="tablist">
+ <li v-for="(tab, index) in tabs" :key="index" class="nav-item">
+ <a role="tab" :aria-controls="tabKey(tab)" :aria-selected="!index" @click="tabClick"
+ :class="'nav-link' + (!index ? ' active' : '')"
+ :id="'tab-' + tabKey(tab)"
+ :href="'#' + tabKey(tab)"
+ >
+ {{ $t(tabLabel(tab)) + (typeof tab != 'string' && 'count' in tab ? ` (${tab.count})` : '') }}
+ </a>
+ </li>
+ </ul>
+</template>
+
+<script>
+ import { Tab } from 'bootstrap'
+
+ export default {
+ props: {
+ tabs: { type: Array, default: () => [] }
+ },
+ data() {
+ return {
+ clickHandlers: {}
+ }
+ },
+ methods: {
+ tabClick(event) {
+ event.preventDefault()
+
+ new Tab(event.target).show()
+
+ const key = event.target.id.replace('tab-', '')
+
+ if (key in this.clickHandlers) {
+ this.clickHandlers[key](event)
+ }
+ },
+ tabKey(tab) {
+ return this.tabLabel(tab).split(/[.-]/).slice(-1)
+ },
+ tabIndex(key) {
+ return this.tabs.findIndex(tab => this.tabKey(tab) == key)
+ },
+ tabLabel(tab) {
+ return typeof tab == 'string' ? tab : tab.label
+ },
+ updateCounter(key, count) {
+ const index = this.tabIndex(key)
+ let tab = this.tabs[index]
+
+ if (typeof tab == 'string') {
+ tab = { label: tab, count }
+ } else {
+ tab.count = count
+ }
+
+ this.$set(this.tabs, index, tab)
+ },
+ clickHandler(key, callback) {
+ this.clickHandlers[key] = callback
+ }
+ }
+ }
+</script>
diff --git a/src/tests/Browser/Admin/SharedFolderTest.php b/src/tests/Browser/Admin/SharedFolderTest.php
--- a/src/tests/Browser/Admin/SharedFolderTest.php
+++ b/src/tests/Browser/Admin/SharedFolderTest.php
@@ -70,9 +70,9 @@
->on(new Dashboard())
->visit($user_page)
->on($user_page)
- ->click('@nav #tab-shared-folders')
+ ->click('@nav #tab-folders')
->pause(1000)
- ->click('@user-shared-folders table tbody tr:first-child td:first-child a')
+ ->click('@user-folders table tbody tr:first-child td:first-child a')
->on($folder_page)
->assertSeeIn('@folder-info .card-title', $folder->email)
->with('@folder-info form', function (Browser $browser) use ($folder) {
diff --git a/src/tests/Browser/Admin/UserTest.php b/src/tests/Browser/Admin/UserTest.php
--- a/src/tests/Browser/Admin/UserTest.php
+++ b/src/tests/Browser/Admin/UserTest.php
@@ -178,9 +178,9 @@
});
// Assert Shared folders tab
- $browser->assertSeeIn('@nav #tab-shared-folders', 'Shared folders (0)')
- ->click('@nav #tab-shared-folders')
- ->with('@user-shared-folders', function (Browser $browser) {
+ $browser->assertSeeIn('@nav #tab-folders', 'Shared folders (0)')
+ ->click('@nav #tab-folders')
+ ->with('@user-folders', function (Browser $browser) {
$browser->assertElementsCount('table tbody tr', 0)
->assertSeeIn('table tfoot tr td', 'There are no shared folders in this account.');
});
@@ -327,9 +327,9 @@
});
// Assert Shared folders tab
- $browser->assertSeeIn('@nav #tab-shared-folders', 'Shared folders (2)')
- ->click('@nav #tab-shared-folders')
- ->with('@user-shared-folders', function (Browser $browser) {
+ $browser->assertSeeIn('@nav #tab-folders', 'Shared folders (2)')
+ ->click('@nav #tab-folders')
+ ->with('@user-folders', function (Browser $browser) {
$browser->assertElementsCount('table tbody tr', 2)
->assertSeeIn('table tbody tr:nth-child(1) td:first-child', 'Calendar')
->assertSeeIn('table tbody tr:nth-child(1) td:nth-child(2)', 'Calendar')
@@ -449,9 +449,9 @@
});
// We don't expect John's folders here
- $browser->assertSeeIn('@nav #tab-shared-folders', 'Shared folders (0)')
- ->click('@nav #tab-shared-folders')
- ->with('@user-shared-folders', function (Browser $browser) {
+ $browser->assertSeeIn('@nav #tab-folders', 'Shared folders (0)')
+ ->click('@nav #tab-folders')
+ ->with('@user-folders', function (Browser $browser) {
$browser->assertElementsCount('table tbody tr', 0)
->assertSeeIn('table tfoot tr td', 'There are no shared folders in this account.');
});
diff --git a/src/tests/Browser/Pages/Admin/Distlist.php b/src/tests/Browser/Pages/Admin/Distlist.php
--- a/src/tests/Browser/Pages/Admin/Distlist.php
+++ b/src/tests/Browser/Pages/Admin/Distlist.php
@@ -51,7 +51,7 @@
return [
'@app' => '#app',
'@distlist-info' => '#distlist-info',
- '@distlist-settings' => '#distlist-settings',
+ '@distlist-settings' => '#settings',
];
}
}
diff --git a/src/tests/Browser/Pages/Admin/Domain.php b/src/tests/Browser/Pages/Admin/Domain.php
--- a/src/tests/Browser/Pages/Admin/Domain.php
+++ b/src/tests/Browser/Pages/Admin/Domain.php
@@ -52,8 +52,8 @@
'@app' => '#app',
'@domain-info' => '#domain-info',
'@nav' => 'ul.nav-tabs',
- '@domain-config' => '#domain-config',
- '@domain-settings' => '#domain-settings',
+ '@domain-config' => '#config',
+ '@domain-settings' => '#settings',
];
}
}
diff --git a/src/tests/Browser/Pages/Admin/Resource.php b/src/tests/Browser/Pages/Admin/Resource.php
--- a/src/tests/Browser/Pages/Admin/Resource.php
+++ b/src/tests/Browser/Pages/Admin/Resource.php
@@ -51,7 +51,7 @@
return [
'@app' => '#app',
'@resource-info' => '#resource-info',
- '@resource-settings' => '#resource-settings',
+ '@resource-settings' => '#settings',
];
}
}
diff --git a/src/tests/Browser/Pages/Admin/SharedFolder.php b/src/tests/Browser/Pages/Admin/SharedFolder.php
--- a/src/tests/Browser/Pages/Admin/SharedFolder.php
+++ b/src/tests/Browser/Pages/Admin/SharedFolder.php
@@ -51,8 +51,8 @@
return [
'@app' => '#app',
'@folder-info' => '#folder-info',
- '@folder-settings' => '#folder-settings',
- '@folder-aliases' => '#folder-aliases',
+ '@folder-settings' => '#settings',
+ '@folder-aliases' => '#aliases',
];
}
}
diff --git a/src/tests/Browser/Pages/Admin/User.php b/src/tests/Browser/Pages/Admin/User.php
--- a/src/tests/Browser/Pages/Admin/User.php
+++ b/src/tests/Browser/Pages/Admin/User.php
@@ -53,15 +53,15 @@
'@app' => '#app',
'@user-info' => '#user-info',
'@nav' => 'ul.nav-tabs',
- '@user-finances' => '#user-finances',
- '@user-aliases' => '#user-aliases',
- '@user-subscriptions' => '#user-subscriptions',
- '@user-distlists' => '#user-distlists',
- '@user-domains' => '#user-domains',
- '@user-resources' => '#user-resources',
- '@user-shared-folders' => '#user-shared-folders',
- '@user-users' => '#user-users',
- '@user-settings' => '#user-settings',
+ '@user-finances' => '#finances',
+ '@user-aliases' => '#aliases',
+ '@user-subscriptions' => '#subscriptions',
+ '@user-distlists' => '#distlists',
+ '@user-domains' => '#domains',
+ '@user-resources' => '#resources',
+ '@user-folders' => '#folders',
+ '@user-users' => '#users',
+ '@user-settings' => '#settings',
];
}
}
diff --git a/src/tests/Browser/Pages/Wallet.php b/src/tests/Browser/Pages/Wallet.php
--- a/src/tests/Browser/Pages/Wallet.php
+++ b/src/tests/Browser/Pages/Wallet.php
@@ -42,8 +42,9 @@
'@main' => '#wallet',
'@payment-dialog' => '#payment-dialog',
'@nav' => 'ul.nav-tabs',
- '@history-tab' => '#wallet-history',
- '@receipts-tab' => '#wallet-receipts',
+ '@history-tab' => '#history',
+ '@receipts-tab' => '#receipts',
+ '@payments-tab' => '#payments',
];
}
}
diff --git a/src/tests/Browser/Reseller/PaymentMollieTest.php b/src/tests/Browser/Reseller/PaymentMollieTest.php
--- a/src/tests/Browser/Reseller/PaymentMollieTest.php
+++ b/src/tests/Browser/Reseller/PaymentMollieTest.php
@@ -61,10 +61,10 @@
->click('@main button')
->with(new Dialog('@payment-dialog'), function (Browser $browser) {
$browser->assertSeeIn('@title', 'Top up your wallet')
- ->waitFor('#payment-method-selection #creditcard')
- ->waitFor('#payment-method-selection #paypal')
- ->waitFor('#payment-method-selection #banktransfer')
- ->click('#creditcard');
+ ->waitFor('#payment-method-selection .link-creditcard svg')
+ ->waitFor('#payment-method-selection .link-paypal svg')
+ ->waitFor('#payment-method-selection .link-banktransfer svg')
+ ->click('#payment-method-selection .link-creditcard');
})
->with(new Dialog('@payment-dialog'), function (Browser $browser) {
$browser->assertSeeIn('@title', 'Top up your wallet')
diff --git a/src/tests/Browser/Reseller/SharedFolderTest.php b/src/tests/Browser/Reseller/SharedFolderTest.php
--- a/src/tests/Browser/Reseller/SharedFolderTest.php
+++ b/src/tests/Browser/Reseller/SharedFolderTest.php
@@ -70,9 +70,9 @@
->on(new Dashboard())
->visit($user_page)
->on($user_page)
- ->click('@nav #tab-shared-folders')
+ ->click('@nav #tab-folders')
->pause(1000)
- ->click('@user-shared-folders table tbody tr:first-child td:first-child a')
+ ->click('@user-folders table tbody tr:first-child td:first-child a')
->on($folder_page)
->assertSeeIn('@folder-info .card-title', $folder->email)
->with('@folder-info form', function (Browser $browser) use ($folder) {
diff --git a/src/tests/Browser/Reseller/UserTest.php b/src/tests/Browser/Reseller/UserTest.php
--- a/src/tests/Browser/Reseller/UserTest.php
+++ b/src/tests/Browser/Reseller/UserTest.php
@@ -175,9 +175,9 @@
});
// Assert Shared folders tab
- $browser->assertSeeIn('@nav #tab-shared-folders', 'Shared folders (0)')
- ->click('@nav #tab-shared-folders')
- ->with('@user-shared-folders', function (Browser $browser) {
+ $browser->assertSeeIn('@nav #tab-folders', 'Shared folders (0)')
+ ->click('@nav #tab-folders')
+ ->with('@user-folders', function (Browser $browser) {
$browser->assertElementsCount('table tbody tr', 0)
->assertSeeIn('table tfoot tr td', 'There are no shared folders in this account.');
});
@@ -323,9 +323,9 @@
});
// Assert Shared folders tab
- $browser->assertSeeIn('@nav #tab-shared-folders', 'Shared folders (2)')
- ->click('@nav #tab-shared-folders')
- ->with('@user-shared-folders', function (Browser $browser) {
+ $browser->assertSeeIn('@nav #tab-folders', 'Shared folders (2)')
+ ->click('@nav #tab-folders')
+ ->with('@user-folders', function (Browser $browser) {
$browser->assertElementsCount('table tbody tr', 2)
->assertSeeIn('table tbody tr:nth-child(1) td:first-child', 'Calendar')
->assertSeeIn('table tbody tr:nth-child(1) td:nth-child(2)', 'Calendar')
@@ -422,9 +422,9 @@
});
// Assert Shared folders tab
- $browser->assertSeeIn('@nav #tab-shared-folders', 'Shared folders (0)')
- ->click('@nav #tab-shared-folders')
- ->with('@user-shared-folders', function (Browser $browser) {
+ $browser->assertSeeIn('@nav #tab-folders', 'Shared folders (0)')
+ ->click('@nav #tab-folders')
+ ->with('@user-folders', function (Browser $browser) {
$browser->assertElementsCount('table tbody tr', 0)
->assertSeeIn('table tfoot tr td', 'There are no shared folders in this account.');
});

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 3, 1:33 AM (3 d, 3 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18818775
Default Alt Text
D3557.1775180032.diff (52 KB)

Event Timeline