mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
New asynchronous way to synchronize from addressbook.
This commit is contained in:
@@ -1,97 +1,120 @@
|
||||
<template>
|
||||
<v-card class="mt-6">
|
||||
<v-data-table :headers="headers" :items="contacts">
|
||||
<template #top>
|
||||
<v-toolbar color="white" flat>
|
||||
<v-text-field
|
||||
v-model="search"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
:placeholder="$gettext('Search')"
|
||||
variant="outlined"
|
||||
single-line
|
||||
flat
|
||||
hide-details
|
||||
density="compact"
|
||||
class="flex-grow-0 w-33 mr-4"
|
||||
></v-text-field>
|
||||
<v-btn color="primary" variant="outlined" @click="showForm = true">
|
||||
{{ $gettext('Add') }}
|
||||
</v-btn>
|
||||
<template v-if="preferences.enable_carddav_sync">
|
||||
<v-btn
|
||||
icon="mdi-information-outline"
|
||||
:title="$gettext('Display address book information')"
|
||||
class="ml-2"
|
||||
@click="showAddressBookInfo = true"
|
||||
/>
|
||||
<v-btn
|
||||
v-if="!addressBook.last_sync"
|
||||
icon="mdi-sync"
|
||||
color="success"
|
||||
:title="$gettext('Synchronize contacts with address book')"
|
||||
@click="syncToAddressBook"
|
||||
/>
|
||||
</template>
|
||||
<v-chip
|
||||
v-if="$route.params.category"
|
||||
class="my-2 mx-4"
|
||||
label
|
||||
size="small"
|
||||
color="green"
|
||||
prepend-icon="mdi-label"
|
||||
@click="editCategory"
|
||||
>
|
||||
{{ $route.params.category }}
|
||||
</v-chip>
|
||||
<v-spacer></v-spacer>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<template #[`item.display_name`]="{ item }">
|
||||
<template v-if="item.display_name">
|
||||
{{ item.display_name }}
|
||||
</template>
|
||||
<template v-else> {{ item.first_name }} {{ item.last_name }} </template>
|
||||
</template>
|
||||
<template #[`item.emails`]="{ item }">
|
||||
{{ displayEmails(item.emails) }}
|
||||
</template>
|
||||
<template #[`item.phone_numbers`]="{ item }">
|
||||
{{ displayPhoneNumbers(item.phone_numbers) }}
|
||||
</template>
|
||||
<template #[`item.actions`]="{ item }">
|
||||
<div class="text-right">
|
||||
<v-menu offset-y>
|
||||
<template #activator="{ props }">
|
||||
<v-btn icon="mdi-dots-horizontal" variant="text" v-bind="props">
|
||||
<div>
|
||||
<v-card class="mt-6">
|
||||
<v-data-table :headers="headers" :items="contacts">
|
||||
<template #top>
|
||||
<v-toolbar color="white" flat>
|
||||
<v-text-field
|
||||
v-model="search"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
:placeholder="$gettext('Search')"
|
||||
variant="outlined"
|
||||
single-line
|
||||
flat
|
||||
hide-details
|
||||
density="compact"
|
||||
class="flex-grow-0 w-33 mr-4"
|
||||
></v-text-field>
|
||||
<v-btn color="primary" variant="outlined" @click="showForm = true">
|
||||
{{ $gettext('Add') }}
|
||||
</v-btn>
|
||||
<template v-if="preferences.enable_carddav_sync">
|
||||
<v-btn class="ml-2" variant="tonal" icon size="small">
|
||||
<v-icon icon="mdi-cog" />
|
||||
<v-menu activator="parent">
|
||||
<v-list density="compact">
|
||||
<v-list-item
|
||||
v-if="!addressBook.last_sync"
|
||||
color="success"
|
||||
:title="
|
||||
$gettext('Synchronize contacts with address book')
|
||||
"
|
||||
prepend-icon="mdi-sync"
|
||||
@click="syncToAddressBook"
|
||||
/>
|
||||
<v-list-item
|
||||
:title="$gettext('Synchronize')"
|
||||
prepend-icon="mdi-sync"
|
||||
:disabled="addressBook.syncing"
|
||||
@click="syncFromAddressBook(true)"
|
||||
/>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
icon="mdi-information-outline"
|
||||
:title="$gettext('Display address book information')"
|
||||
@click="showAddressBookInfo = true"
|
||||
/>
|
||||
</template>
|
||||
<MenuItems :items="contactActions" :obj="item" />
|
||||
</v-menu>
|
||||
</div>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</v-card>
|
||||
<v-dialog v-model="showForm" persistent max-width="800px">
|
||||
<ContactForm
|
||||
:contact="selectedContact"
|
||||
@close="closeForm"
|
||||
@added="fetchContacts"
|
||||
@updated="fetchContacts"
|
||||
/>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="showCategoriesForm" persistent max-width="800px">
|
||||
<ContactCategoriesForm
|
||||
:contact="selectedContact"
|
||||
@updated="fetchContacts"
|
||||
@close="closeCategoriesForm"
|
||||
/>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="showAddressBookInfo" persistent max-width="800px">
|
||||
<AddressBookInfo
|
||||
:address-book-url="addressBook.url"
|
||||
@close="showAddressBookInfo = false"
|
||||
/>
|
||||
</v-dialog>
|
||||
<v-chip
|
||||
v-if="$route.params.category"
|
||||
class="my-2 mx-4"
|
||||
label
|
||||
size="small"
|
||||
color="green"
|
||||
prepend-icon="mdi-label"
|
||||
@click="editCategory"
|
||||
>
|
||||
{{ $route.params.category }}
|
||||
</v-chip>
|
||||
<v-spacer></v-spacer>
|
||||
<v-progress-circular
|
||||
v-if="addressBook.syncing"
|
||||
color="primary"
|
||||
indeterminate
|
||||
></v-progress-circular>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<template #[`item.display_name`]="{ item }">
|
||||
<template v-if="item.display_name">
|
||||
{{ item.display_name }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.first_name }} {{ item.last_name }}
|
||||
</template>
|
||||
</template>
|
||||
<template #[`item.emails`]="{ item }">
|
||||
{{ displayEmails(item.emails) }}
|
||||
</template>
|
||||
<template #[`item.phone_numbers`]="{ item }">
|
||||
{{ displayPhoneNumbers(item.phone_numbers) }}
|
||||
</template>
|
||||
<template #[`item.actions`]="{ item }">
|
||||
<div class="text-right">
|
||||
<v-menu offset-y>
|
||||
<template #activator="{ props }">
|
||||
<v-btn icon="mdi-dots-horizontal" variant="text" v-bind="props">
|
||||
</v-btn>
|
||||
</template>
|
||||
<MenuItems :items="contactActions" :obj="item" />
|
||||
</v-menu>
|
||||
</div>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</v-card>
|
||||
<v-dialog v-model="showForm" persistent max-width="800px">
|
||||
<ContactForm
|
||||
:contact="selectedContact"
|
||||
@close="closeForm"
|
||||
@added="fetchContacts"
|
||||
@updated="fetchContacts"
|
||||
/>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="showCategoriesForm" persistent max-width="800px">
|
||||
<ContactCategoriesForm
|
||||
:contact="selectedContact"
|
||||
@updated="fetchContacts"
|
||||
@close="closeCategoriesForm"
|
||||
/>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="showAddressBookInfo" persistent max-width="800px">
|
||||
<AddressBookInfo
|
||||
:address-book-url="addressBook.url"
|
||||
@close="showAddressBookInfo = false"
|
||||
/>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -191,8 +214,18 @@ function deleteContact(contact) {
|
||||
})
|
||||
}
|
||||
|
||||
async function fetchAddressBook() {
|
||||
const resp = await contactsApi.getDefaultAddressBook()
|
||||
addressBook.value = resp.data
|
||||
}
|
||||
|
||||
async function fetchPreferences() {
|
||||
const resp = await parametersApi.getUserApplication('contacts')
|
||||
preferences.value = resp.data.params
|
||||
}
|
||||
|
||||
function fetchContacts() {
|
||||
contactsApi.getContacts(route.params).then((resp) => {
|
||||
return contactsApi.getContacts(route.params).then((resp) => {
|
||||
contacts.value = resp.data
|
||||
})
|
||||
}
|
||||
@@ -203,20 +236,43 @@ function syncToAddressBook() {
|
||||
})
|
||||
}
|
||||
|
||||
contactsApi.getDefaultAddressBook().then((resp) => {
|
||||
addressBook.value = resp.data
|
||||
})
|
||||
parametersApi.getUserApplication('contacts').then((resp) => {
|
||||
preferences.value = resp.data.params
|
||||
})
|
||||
fetchContacts()
|
||||
async function monitorAddressBook() {
|
||||
await fetchAddressBook()
|
||||
await fetchContacts()
|
||||
if (!addressBook.value.syncing) {
|
||||
clearInterval(intervalId)
|
||||
intervalId = null
|
||||
startAutomaticSync()
|
||||
}
|
||||
}
|
||||
|
||||
async function syncFromAddressBook(withNotification) {
|
||||
if (intervalId) {
|
||||
// Stop automatic sync for now.
|
||||
clearInterval(intervalId)
|
||||
}
|
||||
await contactsApi.synchronizeFromAddressBook()
|
||||
if (withNotification) {
|
||||
displayNotification({ msg: $gettext('Synchronization started') })
|
||||
}
|
||||
addressBook.value.syncing = true
|
||||
intervalId = setInterval(monitorAddressBook, 5000)
|
||||
}
|
||||
|
||||
function startAutomaticSync() {
|
||||
intervalId = setInterval(
|
||||
syncFromAddressBook,
|
||||
preferences.value.sync_frequency * 1000
|
||||
)
|
||||
}
|
||||
|
||||
await fetchAddressBook()
|
||||
await fetchPreferences()
|
||||
await fetchContacts()
|
||||
|
||||
watch(preferences, (value) => {
|
||||
if (value) {
|
||||
intervalId = setInterval(
|
||||
contactsApi.synchronizeFromAddressBook,
|
||||
value.sync_frequency * 1000
|
||||
)
|
||||
startAutomaticSync()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
<template>
|
||||
<div class="text-h5 ml-4">
|
||||
{{ $gettext('Contacts') }}
|
||||
<div>
|
||||
<div class="text-h5 ml-4">
|
||||
{{ $gettext('Contacts') }}
|
||||
</div>
|
||||
<ContactList @edit-category="openCategoryForm" />
|
||||
<v-dialog v-model="showCategoryForm" persistent max-width="800px">
|
||||
<CategoryForm
|
||||
:category="contactsStore.currentCategory"
|
||||
@close="closeForm"
|
||||
@added="fetchCategories"
|
||||
@updated="fetchCategories"
|
||||
/>
|
||||
</v-dialog>
|
||||
</div>
|
||||
<ContactList @edit-category="openCategoryForm" />
|
||||
<v-dialog v-model="showCategoryForm" persistent max-width="800px">
|
||||
<CategoryForm
|
||||
:category="contactsStore.currentCategory"
|
||||
@close="closeForm"
|
||||
@added="fetchCategories"
|
||||
@updated="fetchCategories"
|
||||
/>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
Reference in New Issue
Block a user