diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/ImportScreen.vue | 33 | ||||
-rw-r--r-- | src/services/parseVcf.js | 6 | ||||
-rw-r--r-- | src/store/addressbooks.js | 43 | ||||
-rw-r--r-- | src/store/importState.js | 5 |
4 files changed, 73 insertions, 14 deletions
diff --git a/src/components/ImportScreen.vue b/src/components/ImportScreen.vue index bb903442..b58182fa 100644 --- a/src/components/ImportScreen.vue +++ b/src/components/ImportScreen.vue @@ -23,19 +23,46 @@ <template> <div class="emptycontent import-screen"> <p class="icon-upload" /> - <h3 class="import-screen__header">{{ t('contacts', 'Importing into') }} {{ importState.addressbook }}</h3> - <progress :max="importState.total" :value="importState.accepted" class="import-screen__progress" /> - <p class="import-screen__tracker">{{ Math.floor(importState.accepted/(importState.total + 1)) * 100 }} %</p> + <h3 class="import-screen__header">{{ t('contacts', 'Importing {total} contacts into', { total }) }} {{ addressbook }}</h3> + <progress :max="total" :value="progress" class="import-screen__progress" /> + <p class="import-screen__tracker"> + <span>{{ percentage }} %</span> + <span v-tooltip.auto="t('contacts', 'Open your browser console for more details')">{{ denied }} {{ t('contacts', 'failed') }}</span> + </p> </div> </template> <script> +import Vue from 'vue' +import VTooltip from 'v-tooltip' + +Vue.use(VTooltip) export default { name: 'ImportScreen', computed: { importState() { return this.$store.getters.getImportState + }, + addressbook() { + return this.importState.addressbook + }, + total() { + return this.importState.total + }, + accepted() { + return this.importState.accepted + }, + denied() { + return this.importState.denied + }, + progress() { + return this.accepted + this.denied + }, + percentage() { + return this.total <= 0 + ? 0 + : Math.floor(this.progress / this.total * 100) } } } diff --git a/src/services/parseVcf.js b/src/services/parseVcf.js index 65d5f95c..11b1fc49 100644 --- a/src/services/parseVcf.js +++ b/src/services/parseVcf.js @@ -26,14 +26,13 @@ import Store from '../store/index' export default function parseVcf(data = '', addressbook) { let regexp = /BEGIN:VCARD[\s\S]*?END:VCARD/mgi let vCards = data.match(regexp) - let importState = Store.getters.getImportState if (!vCards) { console.debug('Error during the parsing of the following vcf file: ', data) return [] } - importState.total = vCards.length + Store.dispatch('setTotal', vCards.length) // Not using map because we want to only push valid contacts // map force to return at least undefined @@ -41,11 +40,10 @@ export default function parseVcf(data = '', addressbook) { try { // console.log(vCards.indexOf(vCard)) let contact = new Contact(vCard, addressbook) - importState.accepted++ contacts.push(contact) } catch (e) { // Parse error! Do not stop here... - importState.denied++ + Store.dispatch('incrementDenied') console.error(e) } return contacts diff --git a/src/store/addressbooks.js b/src/store/addressbooks.js index 74a47bef..185a6465 100644 --- a/src/store/addressbooks.js +++ b/src/store/addressbooks.js @@ -22,9 +22,11 @@ */ import Vue from 'vue' +import ICAL from 'ical.js' import parseVcf from '../services/parseVcf' import client from '../services/cdav' import Contact from '../models/contact' +import pLimit from 'p-limit' const addressbookModel = { id: '', @@ -327,15 +329,42 @@ const actions = { * @param {Object} context the store mutations * @param {Object} importDetails = { vcf, addressbook } */ - importContactsIntoAddressbook(context, { vcf, addressbook }) { - let contacts = parseVcf(vcf, addressbook) + async importContactsIntoAddressbook(context, { vcf, addressbook }) { + const contacts = parseVcf(vcf, addressbook) context.commit('changeStage', 'importing') - contacts.forEach(contact => { - context.commit('addContact', contact) - context.commit('addContactToAddressbook', contact) - context.commit('appendGroupsFromContacts', [contact]) + + // max simultaneous requests + const limit = pLimit(3) + const requests = [] + + // create the array of requests to send + contacts.map(async contact => { + // Get vcard string + try { + let vData = ICAL.stringify(contact.vCard.jCal) + // push contact to server and use limit + requests.push(limit(() => contact.addressbook.dav.createVCard(vData) + .then((response) => { + // success, update store + context.commit('addContact', contact) + context.commit('addContactToAddressbook', contact) + context.commit('appendGroupsFromContacts', [contact]) + context.commit('incrementAccepted') + }) + .catch((error) => { + // error + context.commit('incrementDenied') + console.error(error) + }) + )) + } catch (e) { + context.commit('incrementDenied') + } + }) + + Promise.all(requests).then(() => { + // context.commit('changeStage', 'default') }) - context.commit('changeStage', 'default') }, /** diff --git a/src/store/importState.js b/src/store/importState.js index 024b0ac0..313c8d6d 100644 --- a/src/store/importState.js +++ b/src/store/importState.js @@ -77,6 +77,11 @@ const mutations = { */ changeStage(state, stage) { state.importState.stage = stage + if (stage === 'default') { + state.accepted = 0 + state.denied = 0 + state.total = 0 + } } } |