summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2018-09-21 19:36:46 +0200
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2018-09-25 14:52:43 +0200
commitba72cdbadf5b44fe99aef97c060ce88cbad6445e (patch)
tree9fc2da3ff4d7a81351864117fdc7fc6704aea17f /src
parent8ddc94522a834607521819fc2f5370bd35b0c3be (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.vue67
-rw-r--r--src/components/ContentList/ContentListItem.vue2
-rw-r--r--src/models/contact.js3
-rw-r--r--src/store/addressbooks.js35
-rw-r--r--src/store/contacts.js8
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)
+ })
}
}