summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2019-01-25 09:48:19 +0100
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2019-01-25 09:48:19 +0100
commitd982fcf753353236cbaa65a8715cbb4097d2e49f (patch)
treed56e3433ec5badd5a013335ca10290314f314306
parent9b3d2929add7c1ab045b9bcf1d286fe55b7248f2 (diff)
Properly format displayName and validate fields
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
-rw-r--r--.eslintrc.js2
-rw-r--r--src/models/contact.js50
-rw-r--r--src/services/checks/index.js27
-rw-r--r--src/services/checks/missingFN.js48
-rw-r--r--src/services/parseVcf.js2
-rw-r--r--src/services/validate.js47
-rw-r--r--src/store/addressbooks.js2
-rw-r--r--src/store/contacts.js4
-rw-r--r--src/views/Contacts.vue1
9 files changed, 168 insertions, 15 deletions
diff --git a/.eslintrc.js b/.eslintrc.js
index 738e0a83..6e1d2a98 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -53,7 +53,7 @@ module.exports = {
'no-tabs': 0,
'vue/html-indent': ['error', 'tab'],
// only debug console
- 'no-console': ['error', { allow: ['error', 'warn', 'debug'] }],
+ 'no-console': ['error', { allow: ['error', 'warn', 'info', 'debug'] }],
// classes blocks
'padded-blocks': ['error', { classes: 'always' }],
// always have the operator in front
diff --git a/src/models/contact.js b/src/models/contact.js
index 2f877d2e..1240d3d2 100644
--- a/src/models/contact.js
+++ b/src/models/contact.js
@@ -23,6 +23,8 @@
import uuid from 'uuid'
import ICAL from 'ical.js'
+import store from '../store'
+
export default class Contact {
/**
@@ -52,7 +54,7 @@ export default class Contact {
// if no uid set, create one
if (!this.vCard.hasProperty('uid')) {
- console.debug('This contact did not have a proper uid. Setting a new one for ', this)
+ console.info('This contact did not have a proper uid. Setting a new one for ', this)
this.vCard.addPropertyWithValue('uid', uuid())
}
}
@@ -271,25 +273,49 @@ export default class Contact {
}
/**
- * Return the display name
+ * Formatted display name based on the order key
*
* @readonly
* @memberof Contact
- * @returns {string} the displayName
*/
get displayName() {
+ const orderKey = store.getters.getOrderKey
+ const n = this.vCard.getFirstPropertyValue('n')
+ const fn = this.vCard.getFirstPropertyValue('fn')
+ const org = this.vCard.getFirstPropertyValue('org')
+
+ // if ordered by last or first name we need the N property
+ if (orderKey && n) {
+ switch (orderKey) {
+ case 'firstName':
+ // Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.
+ // -> John Stevenson
+ return n.slice(0, 2).reverse().join(' ')
+
+ case 'lastName':
+ // Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.
+ // -> Stevenson, John
+ return n.slice(0, 2).join(', ')
+ }
+ }
+ // otherwise the FN is enough
if (this.vCard.hasProperty('fn')) {
- return this.vCard.getFirstPropertyValue('fn')
+ return fn
}
- if (this.vCard.hasProperty('n')) {
- // reverse and join
- return this.vCard.getFirstPropertyValue('n')
- .filter(function(part) {
- return part
- })
- .join(' ')
+ // BUT if no FN property use the N anyway
+ if (n) {
+ // Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.
+ // -> John Stevenson
+ return n.slice(0, 2).reverse().join(' ')
+ }
+ // LAST chance, use the org ir that's the only thing we have
+ if (org) {
+ // Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.
+ // -> John Stevenson
+ return org
}
- return null
+ return ''
+
}
/**
diff --git a/src/services/checks/index.js b/src/services/checks/index.js
new file mode 100644
index 00000000..4a72ce09
--- /dev/null
+++ b/src/services/checks/index.js
@@ -0,0 +1,27 @@
+/**
+ * @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import missingFN from './missingFN'
+
+export default [
+ missingFN
+]
diff --git a/src/services/checks/missingFN.js b/src/services/checks/missingFN.js
new file mode 100644
index 00000000..3c7ea9e6
--- /dev/null
+++ b/src/services/checks/missingFN.js
@@ -0,0 +1,48 @@
+/**
+ * @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * the FN field is mandatory. If there is none we need to
+ * create it based on the available data
+ */
+export default {
+ name: 'missing FN',
+ run: contact => {
+ return !contact.vCard.hasProperty('fn')
+ },
+ fix: contact => {
+ if (contact.vCard.hasProperty('n')) {
+ // Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.
+ // -> John Stevenson
+ const n = contact.vCard.getFirstPropertyValue('n')
+ contact.fullName = n.slice(0, 2).reverse().join(' ')
+ return true
+ } else if (contact.vCard.hasProperty('org')) {
+ const org = contact.vCard.getFirstPropertyValue('org')
+ // ABC, Inc.;North American Division;Marketing
+ // -> ABC, Inc.
+ contact.fullName = org[0]
+ return true
+ }
+ return false
+ }
+}
diff --git a/src/services/parseVcf.js b/src/services/parseVcf.js
index ea733eaa..184c8e76 100644
--- a/src/services/parseVcf.js
+++ b/src/services/parseVcf.js
@@ -28,7 +28,7 @@ export default function parseVcf(data = '', addressbook) {
let vCards = data.match(regexp)
if (!vCards) {
- console.debug('Error during the parsing of the following vcf file: ', data)
+ console.error('Error during the parsing of the following vcf file: ', data)
return []
}
diff --git a/src/services/validate.js b/src/services/validate.js
new file mode 100644
index 00000000..986dd0a2
--- /dev/null
+++ b/src/services/validate.js
@@ -0,0 +1,47 @@
+/**
+ * @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import Contact from '../models/contact'
+import checks from './checks/'
+
+export default function(contact) {
+ if (contact instanceof Contact) {
+
+ // Going through every checks
+ checks.forEach(check => {
+ if (check.run(contact)) {
+
+ // A fix is needed, running ⏳
+ if (!check.fix(contact)) {
+ // FAILURE 🙅
+ console.warn('The following contact needed a correction that failed', check.name, contact)
+ } else {
+ // SUCCESS 💪
+ console.info('The following contact has been repaired', check.name, contact)
+ }
+ }
+ })
+
+ } else {
+ throw new Error('Invalid contact provided')
+ }
+}
diff --git a/src/store/addressbooks.js b/src/store/addressbooks.js
index 3a35b0d1..768b6a0f 100644
--- a/src/store/addressbooks.js
+++ b/src/store/addressbooks.js
@@ -150,7 +150,7 @@ const mutations = {
// convert list into an array and remove duplicate
addressbook.contacts = contacts.reduce((list, contact) => {
if (list[contact.uid]) {
- console.debug('Duplicate contact overrided', list[contact.uid], contact)
+ console.info('Duplicate contact overrided', list[contact.uid], contact)
}
Vue.set(list, contact.uid, contact)
return list
diff --git a/src/store/contacts.js b/src/store/contacts.js
index da47e067..5258d861 100644
--- a/src/store/contacts.js
+++ b/src/store/contacts.js
@@ -23,6 +23,7 @@
import Vue from 'vue'
import ICAL from 'ical.js'
import Contact from '../models/contact'
+import validate from '../services/validate'
const state = {
// Using objects for performance
@@ -78,6 +79,9 @@ const mutations = {
addContact(state, contact) {
if (contact instanceof Contact) {
+ // Checking contact validity 🙈
+ validate(contact)
+
let sortedContact = {
key: contact.key,
value: contact[state.orderKey]
diff --git a/src/views/Contacts.vue b/src/views/Contacts.vue
index c7c80a42..894389fd 100644
--- a/src/views/Contacts.vue
+++ b/src/views/Contacts.vue
@@ -291,6 +291,7 @@ export default {
})
} catch (error) {
OC.Notification.showTemporary(t('contacts', 'Unable to create the contact.'))
+ console.error(error)
}
},