diff --git a/frontend/src/components/admin/domains/DomainList.vue b/frontend/src/components/admin/domains/DomainList.vue
index 8054267bc..959bd4c34 100644
--- a/frontend/src/components/admin/domains/DomainList.vue
+++ b/frontend/src/components/admin/domains/DomainList.vue
@@ -348,11 +348,20 @@ defineExpose({
})
-
diff --git a/frontend/src/components/admin/identities/IdentityList.vue b/frontend/src/components/admin/identities/IdentityList.vue
index 3e2f91ebe..d0f358a3b 100644
--- a/frontend/src/components/admin/identities/IdentityList.vue
+++ b/frontend/src/components/admin/identities/IdentityList.vue
@@ -29,6 +29,12 @@
class="flex-grow-0 w-33 mr-4"
>
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
- {{ item.identity }}
-
-
-
-
- {{ item.identity }}
-
-
+
+
+ {{ item.username }}
+
+
+
+
+ {{ item.address }}
+
+
+
+
-
-
- {{ tag.label }}
+
+ {{ displayRecipients(item) }}
+
+
+ {{ $date(item.date_joined) }}
+
+
+ {{ $date(item.creation) }}
+
+
+ {{ $date(item.last_modification) }}
+
+
+ {{ $date(item.last_login) }}
+
+
+
+ {{ item.role }}
@@ -137,6 +153,13 @@
hide-details
/>
+
+
+
@@ -145,44 +168,39 @@ import { ref, onMounted, computed } from 'vue'
import { useGettext } from 'vue3-gettext'
import MenuItems from '@/components/tools/MenuItems.vue'
import ConfirmDialog from '@/components/tools/ConfirmDialog.vue'
+import ChooseColumnsForm from '@/components/tools/ChooseColumnsForm.vue'
import { useRouter } from 'vue-router'
import { useBusStore } from '@/stores'
import accountsApi from '@/api/accounts'
import aliasesApi from '@/api/aliases'
import debounce from 'debounce'
-// import identitiesApi from '@/api/identities'
-const { $gettext, $pgettext } = useGettext()
+const { $gettext } = useGettext()
const router = useRouter()
const { displayNotification } = useBusStore()
const availableAliasesColumns = {
- address: { title: $gettext('Address'), key: 'address', value: 'address' },
- enabled: { title: $gettext('Enabled'), key: 'enabled', value: 'enabled' },
+ address: { title: $gettext('Address'), key: 'address' },
+ enabled: { title: $gettext('Enabled'), key: 'enabled' },
recipients: {
title: $gettext('Recipients'),
key: 'recipients',
- value: 'recipients',
},
expire_at: {
title: $gettext('Expire at'),
key: 'expire_at',
- value: 'expire_at',
},
description: {
title: $gettext('Description'),
key: 'description',
- value: 'description',
},
creation: {
title: $gettext('Creation date'),
key: 'creation',
- value: 'creation',
},
last_modification: {
title: $gettext('Last modification'),
key: 'last_modification',
- value: 'last_modification',
},
}
@@ -193,54 +211,45 @@ const defaultAliasColumns = [
]
const availableAccountsColumns = {
- username: { title: $gettext('Name'), key: 'username', value: 'username' },
+ username: { title: $gettext('Name'), key: 'username' },
first_name: {
title: $gettext('First name'),
key: 'first_name',
- value: 'first_name',
},
last_name: {
title: $gettext('Last Name'),
key: 'last_name',
- value: 'last_name',
},
- is_active: { title: $gettext('Enabled'), key: 'enabled', value: 'is_active' },
- role: { title: $gettext('Role'), key: 'role', value: 'role' },
- language: { title: $gettext('Language'), key: 'language', value: 'language' },
+ is_active: { title: $gettext('Enabled'), key: 'is_active' },
+ role: { title: $gettext('Role'), key: 'role' },
+ language: { title: $gettext('Language'), key: 'language' },
phone_number: {
title: $gettext('Phone number'),
key: 'phone_number',
- value: 'phone_number',
},
secondary_email: {
title: $gettext('Secondary email'),
key: 'secondary_email',
- value: 'secondary_email',
},
tfa_enabled: {
title: $gettext('TFA enabled'),
key: 'tfa_enabled',
- value: 'tfa_enabled',
},
totp_enabled: {
title: $gettext('TOTP enabled'),
key: 'totp_enabled',
- value: 'totp_enabled',
},
webauth_enabled: {
title: $gettext('WebAutn enabled'),
key: 'webauth_enabled',
- value: 'webauth_enabled',
},
date_joined: {
- title: $gettext('Created date'),
+ title: $gettext('Creation date'),
key: 'date_joined',
- value: 'date_joined',
},
last_login: {
title: $gettext('Last login'),
key: 'last_login',
- value: 'last_login',
},
}
@@ -263,6 +272,7 @@ const currentPage = ref(1)
const itemsPerPageR = ref(10)
const sortByR = ref([])
const columns = ref(defaultAccountsColumns)
+const showColumnsForm = ref(false)
const headers = computed(() => {
const result = columns.value
@@ -292,7 +302,7 @@ async function updateType(value) {
} else {
columns.value = defaultAliasColumns
}
- fetchIdentities()
+ await fetchIdentities()
}
async function updatedOptions({ page, itemsPerPage, sortBy }) {
@@ -329,9 +339,16 @@ async function fetchIdentities() {
}
}
+function updateDisplayedColumns(selection) {
+ columns.value = currentAvailableColumns.value.filter((col) =>
+ selection.includes(col.key)
+ )
+ showColumnsForm.value = false
+}
+
function getMenuItems(item) {
const result = []
- if (identityType === 'account') {
+ if (identityType.value === 'account') {
item.possible_actions.forEach((element) => {
result.push({
label: element.label,
@@ -355,7 +372,7 @@ function getMenuItems(item) {
onClick: deleteAccount,
color: 'red',
})
- } else if (identityType === 'alias') {
+ } else if (identityType.value === 'alias') {
result.push({
label: $gettext('Edit'),
icon: 'mdi-circle-edit-outline',
@@ -439,6 +456,13 @@ async function deleteAlias(alias) {
}
}
+function displayRecipients(alias) {
+ if (!alias.recipients) {
+ return ''
+ }
+ return alias.recipients.join(', ')
+}
+
onMounted(() => {
fetchIdentities()
})
@@ -449,3 +473,14 @@ defineExpose({
fetchIdentities = debounce(fetchIdentities, 500)
+
+
diff --git a/frontend/src/components/tools/ChooseColumnsForm.vue b/frontend/src/components/tools/ChooseColumnsForm.vue
new file mode 100644
index 000000000..5dfc206cf
--- /dev/null
+++ b/frontend/src/components/tools/ChooseColumnsForm.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+ {{ $gettext('Apply') }}
+
+
+
+
+
+
diff --git a/modoboa/admin/api/v2/serializers.py b/modoboa/admin/api/v2/serializers.py
index 50fb3f38a..b955685e0 100644
--- a/modoboa/admin/api/v2/serializers.py
+++ b/modoboa/admin/api/v2/serializers.py
@@ -402,9 +402,13 @@ class AccountSerializer(v1_serializers.AccountSerializer):
aliases = serializers.ListField(
child=lib_fields.DRFEmailFieldUTF8(), source="mailbox.alias_addresses"
)
+ possible_actions = serializers.SerializerMethodField()
class Meta(v1_serializers.AccountSerializer.Meta):
- fields = v1_serializers.AccountSerializer.Meta.fields + ("aliases",)
+ fields = v1_serializers.AccountSerializer.Meta.fields + (
+ "aliases",
+ "possible_actions",
+ )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -412,6 +416,19 @@ class AccountSerializer(v1_serializers.AccountSerializer):
return
self.fields["resources"] = serializers.SerializerMethodField()
+ def get_possible_actions(self, identity) -> list[IdPossibleActionsSerializer]:
+ actions = admin_signals.extra_account_identities_actions.send(
+ self.__class__, account=identity
+ )
+ cleaned_actions = []
+ for action in actions:
+ try:
+ serialized_data = IdPossibleActionsSerializer(action[1]).data
+ cleaned_actions.append(serialized_data)
+ except (ValidationError, AttributeError):
+ continue
+ return cleaned_actions
+
def get_resources(self, account) -> list[AccountResourceSerializer]:
if account.role == "SimpleUsers":
return []