Skip to content

Commit

Permalink
Merge pull request #880 from nextcloud/displayName-fix
Browse files Browse the repository at this point in the history
Properly format displayName and fields validatation
  • Loading branch information
skjnldsv authored Jan 25, 2019
2 parents 9b3d292 + 1f86484 commit 37434ef
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
54 changes: 41 additions & 13 deletions src/models/contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import uuid from 'uuid'
import ICAL from 'ical.js'

import store from '../store'

export default class Contact {

/**
Expand Down Expand Up @@ -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())
}
}
Expand Down Expand Up @@ -271,25 +273,51 @@ 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() {
if (this.vCard.hasProperty('fn')) {
return this.vCard.getFirstPropertyValue('fn')
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
// ! by checking the property we check for null AND empty string
// ! that means we can then check for empty array and be safe not to have
// ! 'xxxx'.join('') !== ''
if (orderKey && n && n.join('') !== '') {
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(', ')
}
}
if (this.vCard.hasProperty('n')) {
// reverse and join
return this.vCard.getFirstPropertyValue('n')
.filter(function(part) {
return part
})
.join(' ')
// otherwise the FN is enough
if (fn) {
return fn
}
return null
// BUT if no FN property use the N anyway
if (n && n.join('') !== '') {
// 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 && org.join('') !== '') {
// org is supposed to be an array but is also used as plain string
return Array.isArray(org) ? org[0] : org
}
return ''

}

/**
Expand Down
27 changes: 27 additions & 0 deletions src/services/checks/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @copyright Copyright (c) 2019 John Molakvoæ <[email protected]>
*
* @author John Molakvoæ <[email protected]>
*
* @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
]
49 changes: 49 additions & 0 deletions src/services/checks/missingFN.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @copyright Copyright (c) 2019 John Molakvoæ <[email protected]>
*
* @author John Molakvoæ <[email protected]>
*
* @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') // No FN
|| contact.vCard.getFirstPropertyValue('fn') === '' // Empty 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
}
}
2 changes: 1 addition & 1 deletion src/services/parseVcf.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 []
}

Expand Down
47 changes: 47 additions & 0 deletions src/services/validate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* @copyright Copyright (c) 2019 John Molakvoæ <[email protected]>
*
* @author John Molakvoæ <[email protected]>
*
* @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')
}
}
2 changes: 1 addition & 1 deletion src/store/addressbooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/store/contacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down
1 change: 1 addition & 0 deletions src/views/Contacts.vue
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ export default {
})
} catch (error) {
OC.Notification.showTemporary(t('contacts', 'Unable to create the contact.'))
console.error(error)
}
},

Expand Down

0 comments on commit 37434ef

Please sign in to comment.