summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2020-02-04 16:25:58 +0100
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2020-03-13 12:13:54 +0100
commit02de7d76e48ff602a6c97159984cb9f27b5784e2 (patch)
treed22110d792bb3ba19bf69af0ebcb53646113e362 /src
parent1d41416dec7277d5525386a2e6182262fda7cd91 (diff)
Add ability to clone contact
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/components/Actions/ActionCopyNtoFN.vue2
-rw-r--r--src/components/Actions/ActionToggleYear.vue2
-rw-r--r--src/components/ContactDetails.vue132
-rw-r--r--src/components/ContactDetails/ContactDetailsAddNewProp.vue4
-rw-r--r--src/components/ContactDetails/ContactDetailsAvatar.vue8
-rw-r--r--src/components/Properties/PropertyActions.vue6
-rw-r--r--src/components/Properties/PropertyDateTime.vue6
-rw-r--r--src/components/Properties/PropertyGroups.vue9
-rw-r--r--src/components/Properties/PropertyMultipleText.vue4
-rw-r--r--src/components/Properties/PropertySelect.vue4
-rw-r--r--src/components/Properties/PropertyText.vue4
-rw-r--r--src/components/Settings/SettingsAddressbook.vue13
-rw-r--r--src/components/Settings/SettingsAddressbookShare.vue6
-rw-r--r--src/components/Settings/SettingsImportContacts.vue11
-rw-r--r--src/components/Settings/SettingsSortContacts.vue7
-rw-r--r--src/main.js10
-rw-r--r--src/store/addressbooks.js31
-rw-r--r--src/views/Contacts.vue20
18 files changed, 230 insertions, 49 deletions
diff --git a/src/components/Actions/ActionCopyNtoFN.vue b/src/components/Actions/ActionCopyNtoFN.vue
index c73ff9b4..4f4335b8 100644
--- a/src/components/Actions/ActionCopyNtoFN.vue
+++ b/src/components/Actions/ActionCopyNtoFN.vue
@@ -26,7 +26,7 @@
</ActionButton>
</template>
<script>
-import { ActionButton } from '@nextcloud/vue'
+import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import ActionsMixin from '../../mixins/ActionsMixin'
export default {
diff --git a/src/components/Actions/ActionToggleYear.vue b/src/components/Actions/ActionToggleYear.vue
index d76533a9..9da87b0c 100644
--- a/src/components/Actions/ActionToggleYear.vue
+++ b/src/components/Actions/ActionToggleYear.vue
@@ -28,7 +28,7 @@
</ActionCheckbox>
</template>
<script>
-import { ActionCheckbox } from '@nextcloud/vue'
+import ActionCheckbox from '@nextcloud/vue/dist/Components/ActionCheckbox'
import ActionsMixin from '../../mixins/ActionsMixin'
export default {
diff --git a/src/components/ContactDetails.vue b/src/components/ContactDetails.vue
index e1a433c2..62321e60 100644
--- a/src/components/ContactDetails.vue
+++ b/src/components/ContactDetails.vue
@@ -94,7 +94,7 @@
:class="{'icon-loading-small': loadingUpdate,
[`${warning.icon}`]: warning}"
class="header-icon"
- href="#" />
+ @click="onWarningClick" />
<!-- conflict message -->
<div v-if="conflict"
@@ -117,12 +117,23 @@
@click="updateContact" />
<!-- menu actions -->
- <Actions class="header-menu" menu-align="right">
+ <Actions ref="actions"
+ class="header-menu"
+ menu-align="right"
+ :open.sync="openedMenu">
<ActionLink :href="contact.url"
:download="`${contact.displayName}.vcf`"
icon="icon-download">
{{ t('contacts', 'Download') }}
</ActionLink>
+ <!-- user can clone if there is at least one option available -->
+ <ActionButton v-if="isReadOnly && addressbooksOptions.length > 0"
+ ref="cloneAction"
+ :close-after-click="true"
+ icon="icon-clone"
+ @click="cloneContact">
+ {{ t('contacts', 'Clone contact') }}
+ </ActionButton>
<ActionButton icon="icon-qrcode" @click="showQRcode">
{{ t('contacts', 'Generate QR Code') }}
</ActionButton>
@@ -135,9 +146,34 @@
<!-- qrcode -->
<Modal v-if="qrcode"
id="qrcode-modal"
+ :clear-view-delay="-1"
:title="contact.displayName"
@close="closeQrModal">
- <img :src="`data:image/svg+xml;base64,${qrcode}`" class="qrcode" width="400">
+ <img :src="`data:image/svg+xml;base64,${qrcode}`"
+ :alt="t('contacts', 'Contact vcard as qrcode')"
+ class="qrcode"
+ width="400">
+ </Modal>
+
+ <!-- pick addressbook when cloning contact -->
+ <Modal v-if="showPickAddressbookModal"
+ id="pick-addressbook-modal"
+ :clear-view-delay="-1"
+ :title="t('contacts', 'Pick an address book')"
+ @close="closePickAddressbookModal">
+ <Multiselect ref="pickAddressbook"
+ v-model="pickedAddressbook"
+ :allow-empty="false"
+ :options="addressbooksOptions"
+ :placeholder="t('contacts', 'Select addressbook')"
+ track-by="id"
+ label="name" />
+ <button @click="closePickAddressbookModal">
+ {{ t('contacts', 'Cancel') }}
+ </button>
+ <button class="primary" @click="cloneContact">
+ {{ t('contacts', 'Clone contact') }}
+ </button>
</Modal>
</header>
@@ -193,7 +229,12 @@ import debounce from 'debounce'
import PQueue from 'p-queue'
import qr from 'qr-image'
import { stringify } from 'ical.js'
-import { ActionLink, ActionButton } from '@nextcloud/vue'
+import Actions from '@nextcloud/vue/dist/Components/Actions'
+import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
+import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
+import Modal from '@nextcloud/vue/dist/Components/Modal'
+import { showError } from '@nextcloud/dialogs'
import rfcProps from '../models/rfcProps'
import validate from '../services/validate'
@@ -211,6 +252,7 @@ export default {
name: 'ContactDetails',
components: {
+ Actions,
ActionButton,
ActionLink,
AddNewProp,
@@ -219,6 +261,8 @@ export default {
PropertyGroups,
PropertyRev,
PropertySelect,
+ Modal,
+ Multiselect,
},
props: {
@@ -247,6 +291,8 @@ export default {
loadingUpdate: false,
openedMenu: false,
qrcode: '',
+ showPickAddressbookModal: false,
+ pickedAddressbook: null,
}
},
@@ -377,6 +423,7 @@ export default {
/**
* Store getters filtered and mapped to usable object
+ * This is the list of addressbooks that are available to write
*
* @returns {Array}
*/
@@ -504,11 +551,11 @@ export default {
await this.updateLocalContact(contact)
} catch (error) {
if (error.name === 'ParserError') {
- OC.Notification.showTemporary(t('contacts', 'Syntax error. Cannot open the contact.'))
+ showError(t('contacts', 'Syntax error. Cannot open the contact.'))
} else if (error.status === 404) {
- OC.Notification.showTemporary(t('contacts', `The contact doesn't exists anymore on the server.`))
+ showError(t('contacts', `The contact doesn't exists anymore on the server.`))
} else {
- OC.Notification.showTemporary(t('contacts', `Unable to retrieve the contact from the server, please check your network connection.`))
+ showError(t('contacts', `Unable to retrieve the contact from the server, please check your network connection.`))
}
console.error(error)
// trigger a local deletion from the store only
@@ -556,6 +603,41 @@ export default {
})
} catch (error) {
console.error(error)
+ showError(t('contacts', 'An error occured while trying to move the contact'))
+ } finally {
+ this.loadingUpdate = false
+ }
+ }
+ },
+
+ /**
+ * Copy contact to the specified addressbook
+ *
+ * @param {string} addressbookId the desired addressbook ID
+ */
+ async copyContactToAddressbook(addressbookId) {
+ const addressbook = this.addressbooks.find(search => search.id === addressbookId)
+ this.loadingUpdate = true
+ if (addressbook) {
+ try {
+ const contact = await this.$store.dispatch('copyContactToAddressbook', {
+ // we need to use the store contact, not the local contact
+ // using this.contact and not this.localContact
+ contact: this.contact,
+ addressbook,
+ })
+ // select the contact again
+ this.$router.push({
+ name: 'contact',
+ params: {
+ selectedGroup: this.$route.params.selectedGroup,
+ selectedContact: contact.key,
+ },
+ })
+ } catch (error) {
+ console.error(error)
+ window.temp1 = error
+ showError(t('contacts', 'An error occured while trying to copy the contact'))
} finally {
this.loadingUpdate = false
}
@@ -600,6 +682,42 @@ export default {
this.debounceUpdateContact()
}
},
+
+ /**
+ * Clone the current contact to another addressbook
+ */
+ async cloneContact() {
+ // only one addressbook, let's clone it there
+ if (this.pickedAddressbook && this.addressbooks.find(addressbook => addressbook.id === this.pickedAddressbook.id)) {
+ console.debug('Cloning contact to', this.pickedAddressbook.name)
+ await this.copyContactToAddressbook(this.pickedAddressbook.id)
+ this.closePickAddressbookModal()
+ } else if (this.addressbooksOptions.length === 1) {
+ console.debug('Cloning contact to', this.addressbooksOptions[0].name)
+ await this.copyContactToAddressbook(this.addressbooksOptions[0].id)
+ } else {
+ this.showPickAddressbookModal = true
+ }
+ },
+
+ closePickAddressbookModal() {
+ this.showPickAddressbookModal = false
+ this.pickedAddressbook = null
+ },
+
+ /**
+ * The user clicked the warning icon
+ */
+ onWarningClick() {
+ // if the user clicked the readonly icon, let's focus the clone button
+ if (this.isReadOnly && this.addressbooksOptions.length > 0) {
+ this.openedMenu = true
+ this.$nextTick(() => {
+ // focus the clone button
+ this.$refs.actions.onMouseFocusAction({ target: this.$refs.cloneAction.$el })
+ })
+ }
+ },
},
}
</script>
diff --git a/src/components/ContactDetails/ContactDetailsAddNewProp.vue b/src/components/ContactDetails/ContactDetailsAddNewProp.vue
index c6b3ac64..7dc86f00 100644
--- a/src/components/ContactDetails/ContactDetailsAddNewProp.vue
+++ b/src/components/ContactDetails/ContactDetailsAddNewProp.vue
@@ -29,7 +29,7 @@
<div class="property__label" />
<!-- type selector -->
- <multiselect :options="availableProperties"
+ <Multiselect :options="availableProperties"
:placeholder="t('contacts', 'Choose property type')"
class="property__value"
track-by="id"
@@ -40,6 +40,7 @@
</template>
<script>
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import rfcProps from '../../models/rfcProps'
import Contact from '../../models/contact'
import PropertyTitle from '../Properties/PropertyTitle'
@@ -49,6 +50,7 @@ export default {
name: 'ContactDetailsAddNewProp',
components: {
+ Multiselect,
PropertyTitle,
},
diff --git a/src/components/ContactDetails/ContactDetailsAvatar.vue b/src/components/ContactDetails/ContactDetailsAvatar.vue
index e2a03b9b..7b211c8c 100644
--- a/src/components/ContactDetails/ContactDetailsAvatar.vue
+++ b/src/components/ContactDetails/ContactDetailsAvatar.vue
@@ -46,6 +46,7 @@
<Modal v-if="maximizeAvatar"
ref="modal"
+ :clear-view-delay="-1"
class="contact-header-modal"
size="large"
:title="contact.displayName"
@@ -86,7 +87,10 @@
<script>
import debounce from 'debounce'
-import { ActionLink, ActionButton } from '@nextcloud/vue'
+import Actions from '@nextcloud/vue/dist/Components/Actions'
+import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
+import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
+import Modal from '@nextcloud/vue/dist/Components/Modal'
import { getFilePickerBuilder } from '@nextcloud/dialogs'
import { generateRemoteUrl } from '@nextcloud/router'
@@ -99,8 +103,10 @@ export default {
name: 'ContactDetailsAvatar',
components: {
+ Actions,
ActionLink,
ActionButton,
+ Modal,
},
props: {
diff --git a/src/components/Properties/PropertyActions.vue b/src/components/Properties/PropertyActions.vue
index 8de4723a..f015d65c 100644
--- a/src/components/Properties/PropertyActions.vue
+++ b/src/components/Properties/PropertyActions.vue
@@ -25,7 +25,7 @@
<ActionButton icon="icon-delete" @click="deleteProperty">
{{ t('contacts', 'Delete') }}
</ActionButton>
- <actions :is="action"
+ <Actions :is="action"
v-for="(action, index) in actions"
:key="index"
:component="propertyComponent" />
@@ -33,12 +33,14 @@
</template>
<script>
-import { ActionButton } from '@nextcloud/vue'
+import Actions from '@nextcloud/vue/dist/Components/Actions'
+import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
export default {
name: 'PropertyActions',
components: {
+ Actions,
ActionButton,
},
diff --git a/src/components/Properties/PropertyDateTime.vue b/src/components/Properties/PropertyDateTime.vue
index cd0af107..4402e748 100644
--- a/src/components/Properties/PropertyDateTime.vue
+++ b/src/components/Properties/PropertyDateTime.vue
@@ -30,7 +30,7 @@
<div class="property__row">
<!-- type selector -->
- <multiselect v-if="propModel.options"
+ <Multiselect v-if="propModel.options"
v-model="localType"
:options="options"
:searchable="false"
@@ -84,7 +84,8 @@
<script>
import debounce from 'debounce'
import moment from 'moment'
-import { DatetimePicker } from '@nextcloud/vue'
+import DatetimePicker from '@nextcloud/vue/dist/Components/DatetimePicker'
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import { getLocale } from '@nextcloud/l10n'
import { VCardTime } from 'ical.js'
@@ -96,6 +97,7 @@ export default {
name: 'PropertyDateTime',
components: {
+ Multiselect,
DatetimePicker,
PropertyTitle,
PropertyActions,
diff --git a/src/components/Properties/PropertyGroups.vue b/src/components/Properties/PropertyGroups.vue
index b2ce1547..d5f9e7ff 100644
--- a/src/components/Properties/PropertyGroups.vue
+++ b/src/components/Properties/PropertyGroups.vue
@@ -30,7 +30,7 @@
</div>
<!-- multiselect taggable groups with a limit to 3 groups shown -->
- <multiselect v-model="localValue"
+ <Multiselect v-model="localValue"
:options="groups"
:placeholder="t('contacts', 'Add contact in group')"
:multiple="true"
@@ -51,18 +51,23 @@
<span slot="noResult">
{{ t('settings', 'No results') }}
</span>
- </multiselect>
+ </Multiselect>
</div>
</div>
</template>
<script>
import debounce from 'debounce'
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import Contact from '../../models/contact'
export default {
name: 'PropertyGroups',
+ components: {
+ Multiselect,
+ },
+
props: {
propModel: {
type: Object,
diff --git a/src/components/Properties/PropertyMultipleText.vue b/src/components/Properties/PropertyMultipleText.vue
index 896ff661..af7bb430 100644
--- a/src/components/Properties/PropertyMultipleText.vue
+++ b/src/components/Properties/PropertyMultipleText.vue
@@ -30,7 +30,7 @@
<div class="property__row">
<!-- type selector -->
- <multiselect v-if="propModel.options"
+ <Multiselect v-if="propModel.options"
v-model="localType"
:options="options"
:placeholder="t('contacts', 'Select type')"
@@ -101,6 +101,7 @@
</template>
<script>
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import PropertyMixin from '../../mixins/PropertyMixin'
import PropertyTitle from './PropertyTitle'
import PropertyActions from './PropertyActions'
@@ -109,6 +110,7 @@ export default {
name: 'PropertyMultipleText',
components: {
+ Multiselect,
PropertyTitle,
PropertyActions,
},
diff --git a/src/components/Properties/PropertySelect.vue b/src/components/Properties/PropertySelect.vue
index 1ddd6893..321ec771 100644
--- a/src/components/Properties/PropertySelect.vue
+++ b/src/components/Properties/PropertySelect.vue
@@ -39,7 +39,7 @@
{{ propModel.readableName }}
</div>
- <multiselect v-model="matchedOptions"
+ <Multiselect v-model="matchedOptions"
:options="propModel.options"
:placeholder="t('contacts', 'Select option')"
:disabled="isSingleOption || isReadOnly"
@@ -59,6 +59,7 @@
</template>
<script>
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import PropertyMixin from '../../mixins/PropertyMixin'
import PropertyTitle from './PropertyTitle'
import PropertyActions from './PropertyActions'
@@ -67,6 +68,7 @@ export default {
name: 'PropertySelect',
components: {
+ Multiselect,
PropertyTitle,
PropertyActions,
},
diff --git a/src/components/Properties/PropertyText.vue b/src/components/Properties/PropertyText.vue
index ffc7148c..69a7b3c8 100644
--- a/src/components/Properties/PropertyText.vue
+++ b/src/components/Properties/PropertyText.vue
@@ -30,7 +30,7 @@
<div class="property__row">
<!-- type selector -->
- <multiselect v-if="propModel.options"
+ <Multiselect v-if="propModel.options"
v-model="localType"
:options="options"
:placeholder="t('contacts', 'Select type')"
@@ -92,6 +92,7 @@
</template>
<script>
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import debounce from 'debounce'
import PropertyMixin from '../../mixins/PropertyMixin'
import PropertyTitle from './PropertyTitle'
@@ -101,6 +102,7 @@ export default {
name: 'PropertyText',
components: {
+ Multiselect,
PropertyTitle,
PropertyActions,
},
diff --git a/src/components/Settings/SettingsAddressbook.vue b/src/components/Settings/SettingsAddressbook.vue
index 3d9b2271..0b86134c 100644
--- a/src/components/Settings/SettingsAddressbook.vue
+++ b/src/components/Settings/SettingsAddressbook.vue
@@ -93,18 +93,23 @@
</template>
<script>
-import { ActionLink, ActionButton, ActionInput, ActionCheckbox } from '@nextcloud/vue'
+import Actions from '@nextcloud/vue/dist/Components/Actions'
+import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
+import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
+import ActionInput from '@nextcloud/vue/dist/Components/ActionInput'
+import ActionCheckbox from '@nextcloud/vue/dist/Components/ActionCheckbox'
import ShareAddressBook from './SettingsAddressbookShare'
export default {
name: 'SettingsAddressbook',
components: {
- ShareAddressBook,
- ActionLink,
ActionButton,
- ActionInput,
ActionCheckbox,
+ ActionInput,
+ ActionLink,
+ Actions,
+ ShareAddressBook,
},
props: {
diff --git a/src/components/Settings/SettingsAddressbookShare.vue b/src/components/Settings/SettingsAddressbookShare.vue
index ce43c655..728a4cfd 100644
--- a/src/components/Settings/SettingsAddressbookShare.vue
+++ b/src/components/Settings/SettingsAddressbookShare.vue
@@ -22,7 +22,7 @@
<template>
<div class="addressbook-shares">
- <multiselect
+ <Multiselect
id="users-groups-search"
:options="usersOrGroups"
:searchable="true"
@@ -48,6 +48,7 @@
</template>
<script>
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import client from '../../services/cdav'
import addressBookSharee from './SettingsAddressbookSharee'
@@ -55,9 +56,12 @@ import debounce from 'debounce'
export default {
name: 'SettingsAddressbookShare',
+
components: {
+ Multiselect,
addressBookSharee,
},
+
props: {
addressbook: {
type: Object,
diff --git a/src/components/Settings/SettingsImportContacts.vue b/src/components/Settings/SettingsImportContacts.vue
index 809c2185..db53be5f 100644
--- a/src/components/Settings/SettingsImportContacts.vue
+++ b/src/components/Settings/SettingsImportContacts.vue
@@ -34,7 +34,7 @@
@close="toggleModal">
<section class="import-contact__modal-addressbook">
<h3>{{ t('contacts', 'Import contacts') }}</h3>
- <multiselect
+ <Multiselect
v-if="!isSingleAddressbook"
id="select-addressbook"
v-model="selectedAddressbook"
@@ -47,7 +47,7 @@
<template slot="singleLabel" slot-scope="{ option }">
{{ t('contacts', `Import into the '{addressbookName}' addressbook`, { addressbookName: option.displayName }) }}
</template>
- </multiselect>
+ </Multiselect>
</section>
<section class="import-contact__modal-pick">
<input id="contact-import"
@@ -84,6 +84,8 @@
</template>
<script>
+import Modal from '@nextcloud/vue/dist/Components/Modal'
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import { encodePath } from '@nextcloud/paths'
import { getCurrentUser } from '@nextcloud/auth'
import { generateRemoteUrl } from '@nextcloud/router'
@@ -103,6 +105,11 @@ const picker = getFilePickerBuilder(t('contacts', 'Choose a vCard file to import
export default {
name: 'SettingsImportContacts',
+ components: {
+ Modal,
+ Multiselect,
+ },
+
data() {
return {
cancelRequest: () => {},
diff --git a/src/components/Settings/SettingsSortContacts.vue b/src/components/Settings/SettingsSortContacts.vue
index 7bf0644f..11bf0da3 100644
--- a/src/components/Settings/SettingsSortContacts.vue
+++ b/src/components/Settings/SettingsSortContacts.vue
@@ -22,7 +22,7 @@
<template>
<div class="sort-contacts">
- <multiselect
+ <Multiselect
id="sort-by"
:value="orderKeyOption"
:searchable="false"
@@ -36,10 +36,15 @@
</template>
<script>
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
export default {
name: 'SettingsSortContacts',
+ components: {
+ Multiselect,
+ },
+
computed: {
/* Order Keys */
options() {
diff --git a/src/main.js b/src/main.js
index 47b4353e..58cc554a 100644
--- a/src/main.js
+++ b/src/main.js
@@ -32,7 +32,6 @@ import { generateFilePath } from '@nextcloud/router'
import { getRequestToken } from '@nextcloud/auth'
/** GLOBAL COMPONENTS AND DIRECTIVE */
-import { Actions, DatetimePicker, Multiselect, PopoverMenu, Modal } from '@nextcloud/vue'
import ClickOutside from 'vue-click-outside'
import VTooltip from '@nextcloud/vue/dist/Directives/Tooltip'
import VueClipboard from 'vue-clipboard2'
@@ -48,13 +47,7 @@ __webpack_nonce__ = btoa(getRequestToken())
// eslint-disable-next-line
__webpack_public_path__ = generateFilePath('contacts', '', 'js/')
-// Register global components
-Vue.component('Actions', Actions)
-Vue.component('DatetimePicker', DatetimePicker)
-Vue.component('Modal', Modal)
-Vue.component('Multiselect', Multiselect)
-Vue.component('PopoverMenu', PopoverMenu)
-
+// Register global directives
Vue.directive('ClickOutside', ClickOutside)
Vue.directive('Tooltip', VTooltip)
@@ -71,6 +64,7 @@ Vue.prototype.oc_config = oc_config
Vue.prototype.OC = OC
Vue.prototype.OCA = OCA
+// Force redirect if rewrite enabled but accessed through index.php
if (window.location.pathname.split('/')[1] === 'index.php'
&& oc_config.modRewriteWorking) {
router.push({
diff --git a/src/store/addressbooks.js b/src/store/addressbooks.js
index 5871d791..e7a39ac4 100644
--- a/