diff options
author | John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | 2018-09-21 19:36:46 +0200 |
---|---|---|
committer | John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | 2018-09-25 14:52:43 +0200 |
commit | ba72cdbadf5b44fe99aef97c060ce88cbad6445e (patch) | |
tree | 9fc2da3ff4d7a81351864117fdc7fc6704aea17f /src | |
parent | 8ddc94522a834607521819fc2f5370bd35b0c3be (diff) |
Fixed deletion on details, improved loading performances and comments
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/components/ContactDetails.vue | 67 | ||||
-rw-r--r-- | src/components/ContentList/ContentListItem.vue | 2 | ||||
-rw-r--r-- | src/models/contact.js | 3 | ||||
-rw-r--r-- | src/store/addressbooks.js | 35 | ||||
-rw-r--r-- | src/store/contacts.js | 8 |
5 files changed, 79 insertions, 36 deletions
diff --git a/src/components/ContactDetails.vue b/src/components/ContactDetails.vue index 41540e38..a313923b 100644 --- a/src/components/ContactDetails.vue +++ b/src/components/ContactDetails.vue @@ -78,8 +78,11 @@ </div> </header> + <!-- contact details loading --> + <section v-if="loadingData" class="icon-loading contact-details" /> + <!-- contact details --> - <section class="contact-details"> + <section v-else class="contact-details"> <!-- properties iteration --> <!-- using contact.key in the key and index as key to avoid conflicts between similar data and exact key --> @@ -143,6 +146,14 @@ export default { data() { return { + /** + * Local off-store clone of the selected contact for edition + * because we can't edit contacts data outside the store. + * Every change will be dispatched and updated on the real + * store contact after a debounce. + */ + localContact: undefined, + loadingData: true, openedMenu: false, addressbookModel: { readableName: t('contacts', 'Addressbook'), @@ -226,19 +237,14 @@ export default { addressbooks() { return this.$store.getters.getAddressbooks }, - - // local version of the contact contact() { - let contact = this.$store.getters.getContact(this.uid) - if (contact) { - // create empty contact and copy inner data - let localContact = new Contact( - 'BEGIN:VCARD\nUID:' + contact.uid + '\nEND:VCARD', - contact.addressbook - ) - localContact.updateContact(contact.jCal) - return localContact - } + return this.$store.getters.getContact(this.uid) + } + }, + + beforeMount() { + if (this.uid) { + this.selectContact(this.uid) } }, @@ -268,6 +274,28 @@ export default { }, /** + * Trigger an full fetch and + */ + selectContact(uid) { + // local version of the contact + this.loadingData = true + let contact = this.$store.getters.getContact(uid) + if (contact) { + this.$store.dispatch('fetchFullContact', contact) + .then(() => { + // create empty contact and copy inner data + let localContact = new Contact( + 'BEGIN:VCARD\nUID:' + contact.uid + '\nEND:VCARD', + contact.addressbook + ) + localContact.updateContact(contact.jCal) + this.localContact = localContact + this.loadingData = false + }) + } + }, + + /** * Dispatch contact deletion request */ deleteContact() { @@ -283,13 +311,13 @@ export default { addressbook = this.addressbooks.find( search => search.id === addressbook.id ) - // we need to use the store contact, not the local contact - let contact = this.$store.getters.getContact(this.contact.key) // TODO Make sure we do not overwrite contacts if (addressbook) { this.$store .dispatch('moveContactToAddressbook', { - contact: contact, + // we need to use the store contact, not the local contact + // using this.contact and not this.localContact + contact: this.contact, addressbook }) .then(() => { @@ -297,6 +325,13 @@ export default { }) } } + }, + watch: { + contact: function() { + if (this.uid) { + this.selectContact(this.uid) + } + } } } </script> diff --git a/src/components/ContentList/ContentListItem.vue b/src/components/ContentList/ContentListItem.vue index ee3dfe75..a271e112 100644 --- a/src/components/ContentList/ContentListItem.vue +++ b/src/components/ContentList/ContentListItem.vue @@ -7,7 +7,7 @@ class="app-content-list-item-checkbox checkbox" @keypress.enter.space.prevent.stop="toggleSelect"> <label :for="contact.key" @click.prevent.stop="toggleSelect" @keypress.enter.space.prevent.stop="toggleSelect" /> --> - <div :style="{ 'backgroundColor': colorAvatar }" class="app-content-list-item-icon">{{ contact.displayName | firstLetter }}</div> + <div :style="{ 'backgroundColor': colorAvatar, 'backgroundImage': `url(${contact.url} + ?photo)` }" class="app-content-list-item-icon">{{ contact.displayName | firstLetter }}</div> <div class="app-content-list-item-line-one">{{ contact.displayName }}</div> <div v-if="contact.email" class="app-content-list-item-line-two">{{ contact.email }}</div> <div v-if="contact.addressbook.readOnly" class="icon-delete" tabindex="0" diff --git a/src/models/contact.js b/src/models/contact.js index 63b3b777..e23fffff 100644 --- a/src/models/contact.js +++ b/src/models/contact.js @@ -31,9 +31,10 @@ export default class Contact { * @param {string} vcard the vcard data as string with proper new lines * @param {object} addressbook the addressbook which the contat belongs to * @param {string} [url] the url of the contact + * @param {string} [etag] the current etag of the contact * @memberof Contact */ - constructor(vcard = '', addressbook, url) { + constructor(vcard = '', addressbook, url = '', etag = '') { let jCal = ICAL.parse(vcard) if (jCal[0] !== 'vcard') { throw new Error('Only one contact is allowed in the vcard data') diff --git a/src/store/addressbooks.js b/src/store/addressbooks.js index 81d412e7..bc61b982 100644 --- a/src/store/addressbooks.js +++ b/src/store/addressbooks.js @@ -21,10 +21,10 @@ * */ -import parseVcf from '../services/parseVcf' import Vue from 'vue' - +import parseVcf from '../services/parseVcf' import client from '../services/cdav' +import Contact from '../models/contact' const addressbookModel = { id: '', @@ -201,20 +201,21 @@ const actions = { * @returns {Promise} fetch and commit */ async getAddressbooks(context) { - let addressbooks = await client.addressBookHomes[0].findAllAddressBooks().then(addressbooks => { - return addressbooks.map(addressbook => { - return { - // get last part of url - id: addressbook.url.split('/').slice(-2, -1)[0], - displayName: addressbook.displayname, - enabled: addressbook.enabled !== false, - owner: addressbook.owner, - readOnly: addressbook.readOnly !== false, - url: addressbook.url, - dav: addressbook - } + let addressbooks = await client.addressBookHomes[0].findAllAddressBooks() + .then(addressbooks => { + return addressbooks.map(addressbook => { + return { + // get last part of url + id: addressbook.url.split('/').slice(-2, -1)[0], + displayName: addressbook.displayname, + enabled: addressbook.enabled !== false, + owner: addressbook.owner, + readOnly: addressbook.readOnly !== false, + url: addressbook.url, + dav: addressbook + } + }) }) - }) addressbooks.forEach(addressbook => { context.commit('addAddressbooks', addressbook) @@ -286,9 +287,7 @@ const actions = { // We don't want to lose the url information // so we need to parse one by one const contacts = response.map(item => { - let contact = parseVcf(item.data, addressbook)[0] - contact.url = item.url - contact.etag = item.etag + let contact = new Contact(item.data, addressbook, item.url, item.etag) contact.dav = item return contact }) diff --git a/src/store/contacts.js b/src/store/contacts.js index 99f87327..e937af83 100644 --- a/src/store/contacts.js +++ b/src/store/contacts.js @@ -232,6 +232,14 @@ const actions = { */ updateContact(context, contact) { context.commit('updateContact', contact) + }, + + fetchFullContact(context, contact) { + return contact.dav.fetchCompleteData() + .then(() => { + let newContact = new Contact(contact.dav.data, contact.addressbook, contact.dav.url, contact.dav.etag) + context.commit('updateContact', newContact) + }) } } |