Bump eslint-config-nextcloud from 0.0.6 to 0.1.0

Bumps [eslint-config-nextcloud](https://github.com/nextcloud/eslint-config-nextcloud) from 0.0.6 to 0.1.0.
- [Release notes](https://github.com/nextcloud/eslint-config-nextcloud/releases)
- [Commits](https://github.com/nextcloud/eslint-config-nextcloud/compare/v0.0.6...v0.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
This commit is contained in:
dependabot-preview[bot] 2019-12-08 10:22:10 +00:00 committed by John Molakvoæ (skjnldsv)
parent 544cc04f16
commit 213a1fc421
No known key found for this signature in database
GPG Key ID: 60C25B8C072916CF
50 changed files with 428 additions and 435 deletions

View File

@ -15,7 +15,7 @@ all: dev-setup lint build-js-production test test-php
dev-setup: clean clean-dev npm-init dev-setup: clean clean-dev npm-init
npm-init: npm-init:
npm install npm ci
npm-update: npm-update:
npm update npm update

6
package-lock.json generated
View File

@ -4650,9 +4650,9 @@
} }
}, },
"eslint-config-nextcloud": { "eslint-config-nextcloud": {
"version": "0.0.6", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/eslint-config-nextcloud/-/eslint-config-nextcloud-0.0.6.tgz", "resolved": "https://registry.npmjs.org/eslint-config-nextcloud/-/eslint-config-nextcloud-0.1.0.tgz",
"integrity": "sha512-ktCzXVA8GrqZVljutkBKOq2hgKvzKyLhNCAB5bCjdmMo7DIky2ZYeMtDmiEUZCPoXbSJY0kyvnZPbcN4VYzyCg==", "integrity": "sha512-qaxA/OZzfa4G4JQt0UGNs8uJcKsln7UM71R2vdiSpcgKW5hJ6tqtPP7RExS+4osBOl7ntiXihg9bj7PUwqsNaA==",
"dev": true "dev": true
}, },
"eslint-config-standard": { "eslint-config-standard": {

View File

@ -75,7 +75,7 @@
"chai": "^4.2.0", "chai": "^4.2.0",
"css-loader": "^3.2.1", "css-loader": "^3.2.1",
"eslint": "^5.16.0", "eslint": "^5.16.0",
"eslint-config-nextcloud": "0.0.6", "eslint-config-nextcloud": "0.1.0",
"eslint-config-standard": "^12.0.0", "eslint-config-standard": "^12.0.0",
"eslint-import-resolver-webpack": "^0.11.1", "eslint-import-resolver-webpack": "^0.11.1",
"eslint-loader": "^3.0.3", "eslint-loader": "^3.0.3",

View File

@ -26,6 +26,6 @@
<script> <script>
export default { export default {
name: 'ContactsRoot' name: 'ContactsRoot',
} }
</script> </script>

View File

@ -32,7 +32,7 @@ import ActionsMixin from '../../mixins/ActionsMixin'
export default { export default {
name: 'ActionCopyNtoFN', name: 'ActionCopyNtoFN',
components: { components: {
ActionButton ActionButton,
}, },
mixins: [ActionsMixin], mixins: [ActionsMixin],
methods: { methods: {
@ -45,7 +45,7 @@ export default {
this.component.contact.fullName = n.slice(0, 2).reverse().join(' ') this.component.contact.fullName = n.slice(0, 2).reverse().join(' ')
this.component.updateContact() this.component.updateContact()
} }
} },
} },
} }
</script> </script>

View File

@ -34,12 +34,12 @@ import ActionsMixin from '../../mixins/ActionsMixin'
export default { export default {
name: 'ActionToggleYear', name: 'ActionToggleYear',
components: { components: {
ActionCheckbox ActionCheckbox,
}, },
mixins: [ActionsMixin], mixins: [ActionsMixin],
data() { data() {
return { return {
omitYear: false omitYear: false,
} }
}, },
@ -74,7 +74,7 @@ export default {
const dateObject = this.component.localValue.toJSON() const dateObject = this.component.localValue.toJSON()
this.component.updateValue(dateObject, true) this.component.updateValue(dateObject, true)
this.omitYear = !this.omitYear this.omitYear = !this.omitYear
} },
} },
} }
</script> </script>

View File

@ -218,18 +218,18 @@ export default {
ContactProperty, ContactProperty,
PropertyGroups, PropertyGroups,
PropertyRev, PropertyRev,
PropertySelect PropertySelect,
}, },
props: { props: {
loading: { loading: {
type: Boolean, type: Boolean,
default: true default: true,
}, },
contactKey: { contactKey: {
type: String, type: String,
default: undefined default: undefined,
} },
}, },
data() { data() {
@ -246,7 +246,7 @@ export default {
loadingData: true, loadingData: true,
loadingUpdate: false, loadingUpdate: false,
openedMenu: false, openedMenu: false,
qrcode: '' qrcode: '',
} }
}, },
@ -267,12 +267,12 @@ export default {
if (!this.contact.dav) { if (!this.contact.dav) {
return { return {
icon: 'icon-error-white header-icon--pulse', icon: 'icon-error-white header-icon--pulse',
msg: t('contacts', 'This contact is not yet synced. Edit it to save it to the server.') msg: t('contacts', 'This contact is not yet synced. Edit it to save it to the server.'),
} }
} else if (this.isReadOnly) { } else if (this.isReadOnly) {
return { return {
icon: 'icon-eye-white', icon: 'icon-eye-white',
msg: t('contacts', 'This contact is in read-only mode. You do not have permission to edit this contact.') msg: t('contacts', 'This contact is in read-only mode. You do not have permission to edit this contact.'),
} }
} }
return false return false
@ -297,7 +297,7 @@ export default {
*/ */
colorAvatar() { colorAvatar() {
try { try {
let color = this.contact.uid.toRgb() const color = this.contact.uid.toRgb()
return `rgb(${color.r}, ${color.g}, ${color.b})` return `rgb(${color.r}, ${color.g}, ${color.b})`
} catch (e) { } catch (e) {
return 'grey' return 'grey'
@ -328,7 +328,7 @@ export default {
return { return {
readableName: t('contacts', 'Addressbook'), readableName: t('contacts', 'Addressbook'),
icon: 'icon-address-book', icon: 'icon-address-book',
options: this.addressbooksOptions options: this.addressbooksOptions,
} }
}, },
@ -344,7 +344,7 @@ export default {
}, },
set: function(addressbookId) { set: function(addressbookId) {
this.moveContactToAddressbook(addressbookId) this.moveContactToAddressbook(addressbookId)
} },
}, },
/** /**
@ -355,7 +355,7 @@ export default {
groupsModel() { groupsModel() {
return { return {
readableName: t('contacts', 'Groups'), readableName: t('contacts', 'Groups'),
icon: 'icon-contacts' icon: 'icon-contacts',
} }
}, },
@ -372,7 +372,7 @@ export default {
set: function(data) { set: function(data) {
this.contact.groups = data this.contact.groups = data
this.debounceUpdateContact() this.debounceUpdateContact()
} },
}, },
/** /**
@ -386,7 +386,7 @@ export default {
.map(addressbook => { .map(addressbook => {
return { return {
id: addressbook.id, id: addressbook.id,
name: addressbook.displayName name: addressbook.displayName,
} }
}) })
}, },
@ -397,7 +397,7 @@ export default {
}, },
contact() { contact() {
return this.$store.getters.getContact(this.contactKey) return this.$store.getters.getContact(this.contactKey)
} },
}, },
watch: { watch: {
@ -405,7 +405,7 @@ export default {
if (this.contactKey) { if (this.contactKey) {
this.selectContact(this.contactKey) this.selectContact(this.contactKey)
} }
} },
}, },
beforeMount() { beforeMount() {
@ -454,11 +454,11 @@ export default {
* Generate a qrcode for the contact * Generate a qrcode for the contact
*/ */
showQRcode() { showQRcode() {
let jCal = this.contact.jCal.slice(0) const jCal = this.contact.jCal.slice(0)
// do not encode photo // do not encode photo
jCal[1] = jCal[1].filter(props => props[0] !== 'photo') jCal[1] = jCal[1].filter(props => props[0] !== 'photo')
let data = stringify(jCal) const data = stringify(jCal)
if (data.length > 0) { if (data.length > 0) {
this.qrcode = btoa(qr.imageSync(data, { type: 'svg' })) this.qrcode = btoa(qr.imageSync(data, { type: 'svg' }))
} }
@ -483,7 +483,7 @@ export default {
async selectContact(key) { async selectContact(key) {
// local version of the contact // local version of the contact
this.loadingData = true this.loadingData = true
let contact = this.$store.getters.getContact(key) const contact = this.$store.getters.getContact(key)
if (contact) { if (contact) {
// if contact exists AND if exists on server // if contact exists AND if exists on server
@ -524,7 +524,7 @@ export default {
* @param {string} addressbookId the desired addressbook ID * @param {string} addressbookId the desired addressbook ID
*/ */
async moveContactToAddressbook(addressbookId) { async moveContactToAddressbook(addressbookId) {
let addressbook = this.addressbooks.find(search => search.id === addressbookId) const addressbook = this.addressbooks.find(search => search.id === addressbookId)
this.loadingUpdate = true this.loadingUpdate = true
if (addressbook) { if (addressbook) {
try { try {
@ -532,15 +532,15 @@ export default {
// we need to use the store contact, not the local contact // we need to use the store contact, not the local contact
// using this.contact and not this.localContact // using this.contact and not this.localContact
contact: this.contact, contact: this.contact,
addressbook addressbook,
}) })
// select the contact again // select the contact again
this.$router.push({ this.$router.push({
name: 'contact', name: 'contact',
params: { params: {
selectedGroup: this.$route.params.selectedGroup, selectedGroup: this.$route.params.selectedGroup,
selectedContact: contact.key selectedContact: contact.key,
} },
}) })
} catch (error) { } catch (error) {
console.error(error) console.error(error)
@ -572,7 +572,7 @@ export default {
*/ */
updateLocalContact(contact) { updateLocalContact(contact) {
// create empty contact and copy inner data // create empty contact and copy inner data
let localContact = Object.assign( const localContact = Object.assign(
Object.create(Object.getPrototypeOf(contact)), Object.create(Object.getPrototypeOf(contact)),
contact contact
) )
@ -588,7 +588,7 @@ export default {
e.preventDefault() e.preventDefault()
this.debounceUpdateContact() this.debounceUpdateContact()
} }
} },
} },
} }
</script> </script>

View File

@ -49,14 +49,14 @@ export default {
name: 'ContactDetailsAddNewProp', name: 'ContactDetailsAddNewProp',
components: { components: {
PropertyTitle PropertyTitle,
}, },
props: { props: {
contact: { contact: {
type: Contact, type: Contact,
default: null default: null,
} },
}, },
computed: { computed: {
@ -92,10 +92,10 @@ export default {
.map(key => { .map(key => {
return { return {
id: key, id: key,
name: this.properties[key].readableName name: this.properties[key].readableName,
} }
}).sort((a, b) => a.name.localeCompare(b.name)) }).sort((a, b) => a.name.localeCompare(b.name))
} },
}, },
methods: { methods: {
@ -108,17 +108,17 @@ export default {
addProp({ id }) { addProp({ id }) {
if (this.properties[id] && this.properties[id].defaultjCal if (this.properties[id] && this.properties[id].defaultjCal
&& this.properties[id].defaultjCal[this.contact.version]) { && this.properties[id].defaultjCal[this.contact.version]) {
let defaultjCal = this.properties[id].defaultjCal[this.contact.version] const defaultjCal = this.properties[id].defaultjCal[this.contact.version]
let property = new ICAL.Property([id, ...defaultjCal]) const property = new ICAL.Property([id, ...defaultjCal])
this.contact.vCard.addProperty(property) this.contact.vCard.addProperty(property)
} else { } else {
let defaultData = this.properties[id].defaultValue const defaultData = this.properties[id].defaultValue
let property = this.contact.vCard.addPropertyWithValue(id, defaultData ? defaultData.value : '') const property = this.contact.vCard.addPropertyWithValue(id, defaultData ? defaultData.value : '')
if (defaultData && defaultData.type) { if (defaultData && defaultData.type) {
property.setParameter('type', defaultData.type) property.setParameter('type', defaultData.type)
} }
} }
} },
} },
} }
</script> </script>

View File

@ -98,14 +98,14 @@ export default {
components: { components: {
ActionLink, ActionLink,
ActionButton ActionButton,
}, },
props: { props: {
contact: { contact: {
type: Object, type: Object,
required: true required: true,
} },
}, },
data() { data() {
@ -115,7 +115,7 @@ export default {
loading: false, loading: false,
root: generateRemoteUrl(`dav/files/${OC.getCurrentUser().uid}`), root: generateRemoteUrl(`dav/files/${OC.getCurrentUser().uid}`),
width: 0, width: 0,
height: 0 height: 0,
} }
}, },
computed: { computed: {
@ -124,7 +124,7 @@ export default {
return this.contact.addressbook.readOnly return this.contact.addressbook.readOnly
} }
return false return false
} },
}, },
mounted() { mounted() {
// update image size on window resize // update image size on window resize
@ -142,10 +142,10 @@ export default {
if (event.target.files && !this.loading) { if (event.target.files && !this.loading) {
this.closeMenu() this.closeMenu()
let file = event.target.files[0] const file = event.target.files[0]
if (file && file.size && file.size <= 1 * 1024 * 1024) { if (file && file.size && file.size <= 1 * 1024 * 1024) {
let reader = new FileReader() const reader = new FileReader()
let self = this const self = this
reader.onload = function(e) { reader.onload = function(e) {
// only getting the raw binary base64 // only getting the raw binary base64
@ -228,7 +228,7 @@ export default {
'image/gif', 'image/gif',
'image/x-xbitmap', 'image/x-xbitmap',
'image/bmp', 'image/bmp',
'image/svg+xml' 'image/svg+xml',
]) ])
.build() .build()
@ -238,7 +238,7 @@ export default {
try { try {
const { get } = await axios() const { get } = await axios()
const response = await get(`${this.root}${file}`, { const response = await get(`${this.root}${file}`, {
responseType: 'arraybuffer' responseType: 'arraybuffer',
}) })
const type = response.headers['content-type'] const type = response.headers['content-type']
const data = Buffer.from(response.data, 'binary').toString('base64') const data = Buffer.from(response.data, 'binary').toString('base64')
@ -317,9 +317,9 @@ export default {
} }
} }
} }
} },
} },
} }
</script> </script>

View File

@ -57,25 +57,25 @@ export default {
props: { props: {
property: { property: {
type: Property, type: Property,
default: true default: true,
}, },
sortedProperties: { sortedProperties: {
type: Array, type: Array,
default() { default() {
return [] return []
} },
}, },
index: { index: {
type: Number, type: Number,
default: 0 default: 0,
}, },
contact: { contact: {
type: Contact, type: Contact,
default: null default: null,
}, },
localContact: { localContact: {
type: Contact, type: Contact,
default: null default: null,
}, },
/** /**
* This is needed so that we can update * This is needed so that we can update
@ -83,8 +83,8 @@ export default {
*/ */
updateContact: { updateContact: {
type: Function, type: Function,
default: () => {} default: () => {},
} },
}, },
computed: { computed: {
@ -222,12 +222,12 @@ export default {
if (this.propLabel) { if (this.propLabel) {
return { return {
id: this.propLabel.name, id: this.propLabel.name,
name: this.propLabel.getFirstValue() name: this.propLabel.getFirstValue(),
} }
} }
if (this.propModel && this.propModel.options && this.type) { if (this.propModel && this.propModel.options && this.type) {
let selectedType = this.type const selectedType = this.type
// vcard 3.0 save pref alongside TYPE // vcard 3.0 save pref alongside TYPE
.filter(type => type !== 'pref') .filter(type => type !== 'pref')
// we only use uppercase strings // we only use uppercase strings
@ -236,17 +236,17 @@ export default {
// Compare array and score them by how many matches they have to the selected type // Compare array and score them by how many matches they have to the selected type
// sorting directly is cleaner but slower // sorting directly is cleaner but slower
// https://jsperf.com/array-map-and-intersection-perf // https://jsperf.com/array-map-and-intersection-perf
let matchingTypes = this.propModel.options const matchingTypes = this.propModel.options
.map(type => { .map(type => {
return { return {
type, type,
// "WORK,HOME" => ['WORK', 'HOME'] // "WORK,HOME" => ['WORK', 'HOME']
score: type.id.split(',').filter(value => selectedType.indexOf(value) !== -1).length score: type.id.split(',').filter(value => selectedType.indexOf(value) !== -1).length,
} }
}) })
// Sort by score, filtering out the null score and selecting the first match // Sort by score, filtering out the null score and selecting the first match
let matchingType = matchingTypes const matchingType = matchingTypes
.sort((a, b) => b.score - a.score) .sort((a, b) => b.score - a.score)
.filter(type => type.score > 0)[0] .filter(type => type.score > 0)[0]
@ -256,13 +256,13 @@ export default {
} }
if (this.type) { if (this.type) {
// vcard 3.0 save pref alongside TYPE // vcard 3.0 save pref alongside TYPE
let selectedType = this.type const selectedType = this.type
.filter(type => type !== 'pref') .filter(type => type !== 'pref')
.join(',') .join(',')
if (selectedType.trim() !== '') { if (selectedType.trim() !== '') {
return { return {
id: selectedType, id: selectedType,
name: selectedType name: selectedType,
} }
} }
} }
@ -291,7 +291,7 @@ export default {
} }
} }
this.updateContact() this.updateContact()
} },
}, },
@ -316,13 +316,13 @@ export default {
this.property.setValue(data) this.property.setValue(data)
} }
this.updateContact() this.updateContact()
} },
}, },
// property meta type // property meta type
type: { type: {
get() { get() {
let type = this.property.getParameter('type') const type = this.property.getParameter('type')
// ensure we have an array // ensure we have an array
if (type) { if (type) {
return Array.isArray(type) ? type : [type] return Array.isArray(type) ? type : [type]
@ -331,7 +331,7 @@ export default {
}, },
set(data) { set(data) {
this.property.setParameter('type', data) this.property.setParameter('type', data)
} },
}, },
// property meta pref // property meta pref
@ -341,8 +341,8 @@ export default {
}, },
set(data) { set(data) {
this.property.setParameter('pref', data) this.property.setParameter('pref', data)
} },
} },
}, },
methods: { methods: {
@ -352,7 +352,7 @@ export default {
deleteProp() { deleteProp() {
this.localContact.vCard.removeProperty(this.property) this.localContact.vCard.removeProperty(this.property)
this.updateContact() this.updateContact()
} },
} },
} }
</script> </script>

View File

@ -52,31 +52,31 @@ export default {
components: { components: {
ContactsListItem, ContactsListItem,
RecycleScroller RecycleScroller,
}, },
props: { props: {
list: { list: {
type: Array, type: Array,
required: true required: true,
}, },
contacts: { contacts: {
type: Object, type: Object,
required: true required: true,
}, },
loading: { loading: {
type: Boolean, type: Boolean,
default: true default: true,
}, },
searchQuery: { searchQuery: {
type: String, type: String,
default: '' default: '',
} },
}, },
data() { data() {
return { return {
itemHeight: 68 itemHeight: 68,
} }
}, },
@ -89,7 +89,7 @@ export default {
}, },
filteredList() { filteredList() {
return this.list.filter(contact => this.matchSearch(this.contacts[contact.key])) return this.list.filter(contact => this.matchSearch(this.contacts[contact.key]))
} },
}, },
watch: { watch: {
@ -107,7 +107,7 @@ export default {
this.scrollToContact(this.selectedContact) this.scrollToContact(this.selectedContact)
}) })
} }
} },
}, },
methods: { methods: {
@ -159,7 +159,7 @@ export default {
return contact.searchData.toString().toLowerCase().search(this.searchQuery.trim().toLowerCase()) !== -1 return contact.searchData.toString().toLowerCase().search(this.searchQuery.trim().toLowerCase()) !== -1
} }
return true return true
} },
} },
} }
</script> </script>

View File

@ -64,23 +64,23 @@ export default {
filters: { filters: {
firstLetter(value) { firstLetter(value) {
return value.charAt(0) return value.charAt(0)
} },
}, },
props: { props: {
index: { index: {
type: Number, type: Number,
required: true required: true,
}, },
contact: { contact: {
type: Object, type: Object,
required: true required: true,
} },
}, },
data() { data() {
return { return {
deleteInterval: null, deleteInterval: null,
deleteTimeout: null, deleteTimeout: null,
countdown: 7 countdown: 7,
} }
}, },
computed: { computed: {
@ -106,7 +106,7 @@ export default {
*/ */
colorAvatar() { colorAvatar() {
try { try {
let color = this.contact.uid.toRgb() const color = this.contact.uid.toRgb()
return `rgb(${color.r}, ${color.g}, ${color.b})` return `rgb(${color.r}, ${color.g}, ${color.b})`
} catch (e) { } catch (e) {
return 'grey' return 'grey'
@ -117,7 +117,7 @@ export default {
return `url(${this.contact.photoUrl})` return `url(${this.contact.photoUrl})`
} }
return `url(${this.contact.url}?photo)` return `url(${this.contact.url}?photo)`
} },
}, },
methods: { methods: {
/** /**
@ -159,7 +159,7 @@ export default {
selectContact() { selectContact() {
// change url with router // change url with router
this.$router.push({ name: 'contact', params: { selectedGroup: this.selectedGroup, selectedContact: this.contact.key } }) this.$router.push({ name: 'contact', params: { selectedGroup: this.selectedGroup, selectedContact: this.contact.key } })
} },
} },
} }
</script> </script>

View File

@ -76,7 +76,7 @@ export default {
return this.total <= 0 return this.total <= 0
? 0 ? 0
: Math.floor(this.progress / this.total * 100) : Math.floor(this.progress / this.total * 100)
} },
} },
} }
</script> </script>

View File

@ -39,24 +39,24 @@ export default {
name: 'PropertyActions', name: 'PropertyActions',
components: { components: {
ActionButton ActionButton,
}, },
props: { props: {
actions: { actions: {
type: Array, type: Array,
default: () => [] default: () => [],
}, },
propertyComponent: { propertyComponent: {
type: Object, type: Object,
required: true required: true,
} },
}, },
methods: { methods: {
deleteProperty() { deleteProperty() {
this.$emit('delete') this.$emit('delete')
} },
} },
} }
</script> </script>

View File

@ -87,7 +87,7 @@ export default {
components: { components: {
DatetimePicker, DatetimePicker,
PropertyTitle, PropertyTitle,
PropertyActions PropertyActions,
}, },
mixins: [PropertyMixin], mixins: [PropertyMixin],
@ -96,8 +96,8 @@ export default {
value: { value: {
type: [VCardTime, String], type: [VCardTime, String],
default: '', default: '',
required: true required: true,
} },
}, },
data() { data() {
@ -111,26 +111,26 @@ export default {
// locale and lang data // locale and lang data
locale: 'en', locale: 'en',
firstDay: window.firstDay === 0 ? 7 : window.firstDay, // provided by nextcloud firstDay: window.firstDay === 0 ? 7 : window.firstDay, // provided by nextcloud
lang: { lang: {
days: window.dayNamesShort, // provided by nextcloud days: window.dayNamesShort, // provided by nextcloud
months: window.monthNamesShort, // provided by nextcloud months: window.monthNamesShort, // provided by nextcloud
placeholder: { placeholder: {
date: t('contacts', 'Select Date') date: t('contacts', 'Select Date'),
} },
}, },
dateFormat: { dateFormat: {
stringify: (date) => { stringify: (date) => {
return date ? this.formatDateTime() : null return date ? this.formatDateTime() : null
} },
} },
} }
}, },
computed: { computed: {
gridLength() { gridLength() {
let hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 const hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0
let isLast = this.isLastProperty ? 1 : 0 const isLast = this.isLastProperty ? 1 : 0
// length is always one & add one space at the end // length is always one & add one space at the end
return hasTitle + 1 + isLast return hasTitle + 1 + isLast
}, },
@ -142,7 +142,7 @@ export default {
return new VCardTime.fromDateAndOrTimeString(this.localValue) return new VCardTime.fromDateAndOrTimeString(this.localValue)
} }
return this.localValue return this.localValue
} },
}, },
async mounted() { async mounted() {
@ -180,7 +180,7 @@ export default {
const objMap = ['year', 'month', 'day', 'hour', 'minute', 'second'] const objMap = ['year', 'month', 'day', 'hour', 'minute', 'second']
const rawArray = moment(date).toArray() const rawArray = moment(date).toArray()
let dateObject = rawArray.reduce((acc, cur, index) => { const dateObject = rawArray.reduce((acc, cur, index) => {
acc[objMap[index]] = cur acc[objMap[index]] = cur
return acc return acc
}, {}) }, {})
@ -250,7 +250,7 @@ export default {
// this is the only possibility for us to ensure // this is the only possibility for us to ensure
// no data is lost. e.g. if no second are set // no data is lost. e.g. if no second are set
// the second will be null and not 0 // the second will be null and not 0
let datetimeData = this.vcardTimeLocalValue.toJSON() const datetimeData = this.vcardTimeLocalValue.toJSON()
let datetime = '' let datetime = ''
const ignoreYear = this.property.getParameter('x-apple-omit-year') const ignoreYear = this.property.getParameter('x-apple-omit-year')
@ -286,10 +286,10 @@ export default {
.locale(this.locale) .locale(this.locale)
.format( .format(
this.inputType === 'datetime' this.inputType === 'datetime'
? 'llll' // date & time display ? 'llll' // date & time display
: this.inputType === 'date' : this.inputType === 'date'
? 'll' // only date ? 'll' // only date
: 'LTS' // only time : 'LTS' // only time
) )
} }
@ -297,8 +297,8 @@ export default {
// replace year and remove double spaces // replace year and remove double spaces
? datetime.replace(moment(this.vcardTimeLocalValue).year(), '').replace(/\s\s+/g, ' ') ? datetime.replace(moment(this.vcardTimeLocalValue).year(), '').replace(/\s\s+/g, ' ')
: datetime : datetime
} },
} },
} }
</script> </script>

View File

@ -67,28 +67,28 @@ export default {
propModel: { propModel: {
type: Object, type: Object,
default: () => {}, default: () => {},
required: true required: true,
}, },
value: { value: {
type: Array, type: Array,
default: () => [], default: () => [],
required: true required: true,
}, },
contact: { contact: {
type: Contact, type: Contact,
default: null, default: null,
required: true required: true,
}, },
// Is it read-only? // Is it read-only?
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false,
} },
}, },
data() { data() {
return { return {
localValue: this.value localValue: this.value,
} }
}, },
@ -105,7 +105,7 @@ export default {
*/ */
formatGroupsTitle() { formatGroupsTitle() {
return this.localValue.slice(3).join(', ') return this.localValue.slice(3).join(', ')
} },
}, },
watch: { watch: {
@ -119,7 +119,7 @@ export default {
}, },
selectType: function() { selectType: function() {
this.localType = this.selectType this.localType = this.selectType
} },
}, },
methods: { methods: {
@ -140,7 +140,7 @@ export default {
async addContactToGroup(groupName) { async addContactToGroup(groupName) {
await this.$store.dispatch('addContactToGroup', { await this.$store.dispatch('addContactToGroup', {
contact: this.contact, contact: this.contact,
groupName groupName,
}) })
this.updateValue() this.updateValue()
}, },
@ -153,7 +153,7 @@ export default {
removeContactToGroup(groupName) { removeContactToGroup(groupName) {
this.$store.dispatch('removeContactToGroup', { this.$store.dispatch('removeContactToGroup', {
contact: this.contact, contact: this.contact,
groupName groupName,
}) })
}, },
@ -165,15 +165,15 @@ export default {
*/ */
validateGroup(groupName) { validateGroup(groupName) {
// Only allow characters without vcard special chars // Only allow characters without vcard special chars
let groupRegex = /^[^;,:]+$/gmi const groupRegex = /^[^;,:]+$/gmi
if (groupName.match(groupRegex)) { if (groupName.match(groupRegex)) {
this.addContactToGroup(groupName) this.addContactToGroup(groupName)
this.localValue.push(groupName) this.localValue.push(groupName)
return true return true
} }
return false return false
} },
} },
} }
</script> </script>

View File

@ -109,7 +109,7 @@ export default {
components: { components: {
PropertyTitle, PropertyTitle,
PropertyActions PropertyActions,
}, },
mixins: [PropertyMixin], mixins: [PropertyMixin],
@ -118,23 +118,23 @@ export default {
value: { value: {
type: [Array, Object], type: [Array, Object],
default: () => [], default: () => [],
required: true required: true,
} },
}, },
computed: { computed: {
gridLength() { gridLength() {
let hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 const hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0
let isLast = this.isLastProperty const isLast = this.isLastProperty
let hasValueNames = this.propModel.options || this.selectType || !this.property.isStructuredValue ? 1 : 0 const hasValueNames = this.propModel.options || this.selectType || !this.property.isStructuredValue ? 1 : 0
let length = this.propModel.displayOrder ? this.propModel.displayOrder.length : this.value.length const length = this.propModel.displayOrder ? this.propModel.displayOrder.length : this.value.length
return hasValueNames + hasTitle + length + isLast return hasValueNames + hasTitle + length + isLast
}, },
filteredValue() { filteredValue() {
return this.localValue.filter((value, index) => index > 0) return this.localValue.filter((value, index) => index > 0)
} },
} },
} }
</script> </script>

View File

@ -36,14 +36,14 @@ export default {
value: { value: {
type: VCardTime, type: VCardTime,
required: true, required: true,
default: null default: null,
} },
}, },
computed: { computed: {
relativeDate() { relativeDate() {
return OC.Util.relativeModifiedDate(this.value.toUnixTime() * 1000) return OC.Util.relativeModifiedDate(this.value.toUnixTime() * 1000)
} },
} },
} }
</script> </script>

View File

@ -64,7 +64,7 @@ export default {
components: { components: {
PropertyTitle, PropertyTitle,
PropertyActions PropertyActions,
}, },
mixins: [PropertyMixin], mixins: [PropertyMixin],
@ -73,14 +73,14 @@ export default {
value: { value: {
type: [Object, String, Array], type: [Object, String, Array],
default: '', default: '',
required: true required: true,
} },
}, },
computed: { computed: {
gridLength() { gridLength() {
let hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 const hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0
let isLast = this.isLastProperty ? 1 : 0 const isLast = this.isLastProperty ? 1 : 0
// length is one & add one space at the end // length is one & add one space at the end
return hasTitle + 1 + isLast return hasTitle + 1 + isLast
}, },
@ -105,12 +105,12 @@ export default {
if (Array.isArray(this.localValue)) { if (Array.isArray(this.localValue)) {
return selected || { return selected || {
id: this.localValue.join(';'), id: this.localValue.join(';'),
name: this.localValue.join(';') name: this.localValue.join(';'),
} }
} }
return selected || { return selected || {
id: this.localValue, id: this.localValue,
name: this.localValue name: this.localValue,
} }
}, },
set(value) { set(value) {
@ -120,9 +120,9 @@ export default {
} else { } else {
this.localValue = value.id this.localValue = value.id
} }
} },
} },
} },
} }
</script> </script>

View File

@ -97,7 +97,7 @@ export default {
components: { components: {
PropertyTitle, PropertyTitle,
PropertyActions PropertyActions,
}, },
mixins: [PropertyMixin], mixins: [PropertyMixin],
@ -106,28 +106,28 @@ export default {
propName: { propName: {
type: String, type: String,
default: 'text', default: 'text',
required: true required: true,
}, },
value: { value: {
type: String, type: String,
default: '', default: '',
required: true required: true,
} },
}, },
data() { data() {
return { return {
// the textarea additionnal height compared to the // the textarea additionnal height compared to the
// default input text. Min is 2 grid height // default input text. Min is 2 grid height
noteHeight: 1 noteHeight: 1,
} }
}, },
computed: { computed: {
gridLength() { gridLength() {
let hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 const hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0
let isLast = this.isLastProperty ? 1 : 0 const isLast = this.isLastProperty ? 1 : 0
let noteHeight = this.propName === 'note' const noteHeight = this.propName === 'note'
? this.noteHeight ? this.noteHeight
: 0 : 0
// length is one & add one space at the end // length is one & add one space at the end
@ -167,7 +167,7 @@ export default {
haveExtHandler() { haveExtHandler() {
return this.externalHandler.trim() !== '' && this.localValue && this.localValue.length > 0 return this.externalHandler.trim() !== '' && this.localValue && this.localValue.length > 0
} },
}, },
mounted() { mounted() {
@ -198,7 +198,7 @@ export default {
updateValueNoDebounce(e) { updateValueNoDebounce(e) {
this.resizeGrid(e) this.resizeGrid(e)
this.updateValue(e) this.updateValue(e)
} },
} },
} }
</script> </script>

View File

@ -39,18 +39,18 @@ export default {
icon: { icon: {
type: String, type: String,
default: '', default: '',
required: true required: true,
}, },
readableName: { readableName: {
type: String, type: String,
default: '', default: '',
required: true required: true,
}, },
info: { info: {
type: String, type: String,
default: '', default: '',
required: false required: false,
} },
} },
} }
</script> </script>

View File

@ -104,7 +104,7 @@ export default {
ActionLink, ActionLink,
ActionButton, ActionButton,
ActionInput, ActionInput,
ActionCheckbox ActionCheckbox,
}, },
props: { props: {
@ -112,8 +112,8 @@ export default {
type: Object, type: Object,
default() { default() {
return {} return {}
} },
} },
}, },
data() { data() {
return { return {
@ -125,7 +125,7 @@ export default {
menuOpen: false, menuOpen: false,
renameLoading: false, renameLoading: false,
shareOpen: false, shareOpen: false,
toggleEnabledLoading: false toggleEnabledLoading: false,
} }
}, },
computed: { computed: {
@ -148,7 +148,7 @@ export default {
'Shared with {num} entity', 'Shared with {num} entity',
'Shared with {num} entities', 'Shared with {num} entities',
this.addressbook.shares.length, { this.addressbook.shares.length, {
num: this.addressbook.shares.length num: this.addressbook.shares.length,
}) })
: '' // disable the tooltip : '' // disable the tooltip
}, },
@ -159,14 +159,14 @@ export default {
: t('contacts', 'Can not copy') : t('contacts', 'Can not copy')
} }
return t('contacts', 'Copy link') return t('contacts', 'Copy link')
} },
}, },
watch: { watch: {
menuOpen: function() { menuOpen: function() {
if (this.menuOpen === false) { if (this.menuOpen === false) {
this.editingName = false this.editingName = false
} }
} },
}, },
mounted() { mounted() {
// required if popup needs to stay opened after menu click // required if popup needs to stay opened after menu click
@ -226,9 +226,9 @@ export default {
this.editingName = true this.editingName = true
}, },
async updateAddressbookName(e) { async updateAddressbookName(e) {
let addressbook = this.addressbook const addressbook = this.addressbook
// New name for addressbook - inputed value from form // New name for addressbook - inputed value from form
let newName = this.$refs.renameInput.$el.querySelector('input[type="text"]').value const newName = this.$refs.renameInput.$el.querySelector('input[type="text"]').value
// change to loading status // change to loading status
this.renameLoading = true this.renameLoading = true
try { try {
@ -268,7 +268,7 @@ export default {
this.copySuccess = false this.copySuccess = false
}, 2000) }, 2000)
} }
} },
} },
} }
</script> </script>

View File

@ -56,21 +56,21 @@ import debounce from 'debounce'
export default { export default {
name: 'SettingsAddressbookShare', name: 'SettingsAddressbookShare',
components: { components: {
addressBookSharee addressBookSharee,
}, },
props: { props: {
addressbook: { addressbook: {
type: Object, type: Object,
default() { default() {
return {} return {}
} },
} },
}, },
data() { data() {
return { return {
isLoading: false, isLoading: false,
inputGiven: false, inputGiven: false,
usersOrGroups: [] usersOrGroups: [],
} }
}, },
computed: { computed: {
@ -79,7 +79,7 @@ export default {
}, },
noResult() { noResult() {
return t('contacts', 'No users or groups') return t('contacts', 'No users or groups')
} },
}, },
mounted() { mounted() {
// This ensures that the multiselect input is in focus as soon as the user clicks share // This ensures that the multiselect input is in focus as soon as the user clicks share
@ -96,7 +96,7 @@ export default {
* @param {boolean} data.isGroup is this a group ? * @param {boolean} data.isGroup is this a group ?
*/ */
shareAddressbook({ user, displayName, uri, isGroup }) { shareAddressbook({ user, displayName, uri, isGroup }) {
let addressbook = this.addressbook const addressbook = this.addressbook
uri = decodeURI(uri) uri = decodeURI(uri)
user = decodeURI(user) user = decodeURI(user)
this.$store.dispatch('shareAddressbook', { addressbook, user, displayName, uri, isGroup }) this.$store.dispatch('shareAddressbook', { addressbook, user, displayName, uri, isGroup })
@ -113,14 +113,14 @@ export default {
if (query.length > 0) { if (query.length > 0) {
const results = await client.principalPropertySearchByDisplayname(query) const results = await client.principalPropertySearchByDisplayname(query)
this.usersOrGroups = results.reduce((list, result) => { this.usersOrGroups = results.reduce((list, result) => {
if (['GROUP', 'INDIVIDUAL'].indexOf(result.calendarUserType) > -1) { if (['GROUP', 'INDIVIDUAL'].indexOf(result.calendarUserType) > -1) {
const isGroup = result.calendarUserType === 'GROUP' const isGroup = result.calendarUserType === 'GROUP'
list.push({ list.push({
user: result[isGroup ? 'groupId' : 'userId'], user: result[isGroup ? 'groupId' : 'userId'],
displayName: result.displayname, displayName: result.displayname,
icon: isGroup ? 'icon-group' : 'icon-user', icon: isGroup ? 'icon-group' : 'icon-user',
uri: result.principalScheme, uri: result.principalScheme,
isGroup isGroup,
}) })
} }
return list return list
@ -131,7 +131,7 @@ export default {
this.inputGiven = false this.inputGiven = false
this.isLoading = false this.isLoading = false
} }
}, 500) }, 500),
} },
} }
</script> </script>

View File

@ -60,17 +60,17 @@ export default {
props: { props: {
addressbook: { addressbook: {
type: Object, type: Object,
required: true required: true,
}, },
sharee: { sharee: {
type: Object, type: Object,
required: true required: true,
} },
}, },
data() { data() {
return { return {
loading: false loading: false,
} }
}, },
@ -81,7 +81,7 @@ export default {
// generated id for this sharee // generated id for this sharee
uid() { uid() {
return this.sharee.id + this.addressbook.id + Math.floor(Math.random() * 1000) return this.sharee.id + this.addressbook.id + Math.floor(Math.random() * 1000)
} },
}, },
methods: { methods: {
@ -94,7 +94,7 @@ export default {
try { try {
await this.$store.dispatch('removeSharee', { await this.$store.dispatch('removeSharee', {
addressbook: this.addressbook, addressbook: this.addressbook,
uri: this.sharee.uri uri: this.sharee.uri,
}) })
} catch (error) { } catch (error) {
console.error(error) console.error(error)
@ -113,7 +113,7 @@ export default {
await this.$store.dispatch('toggleShareeWritable', { await this.$store.dispatch('toggleShareeWritable', {
addressbook: this.addressbook, addressbook: this.addressbook,
uri: this.sharee.uri, uri: this.sharee.uri,
writeable: !this.sharee.writeable writeable: !this.sharee.writeable,
}) })
} catch (error) { } catch (error) {
console.error(error) console.error(error)
@ -121,7 +121,7 @@ export default {
} finally { } finally {
this.loading = false this.loading = false
} }
} },
} },
} }
</script> </script>

View File

@ -54,7 +54,7 @@ export default {
data() { data() {
return { return {
importDestination: false importDestination: false,
} }
}, },
@ -75,7 +75,7 @@ export default {
.map(addressbook => { .map(addressbook => {
return { return {
id: addressbook.id, id: addressbook.id,
displayName: addressbook.displayName displayName: addressbook.displayName,
} }
}) })
}, },
@ -89,7 +89,7 @@ export default {
}, },
set(value) { set(value) {
this.importDestination = value this.importDestination = value
} },
}, },
// disable multiselect when there is only one address book // disable multiselect when there is only one address book
@ -107,23 +107,23 @@ export default {
// are we currently importing ? // are we currently importing ?
isImporting() { isImporting() {
return this.importState.stage !== 'default' return this.importState.stage !== 'default'
} },
}, },
methods: { methods: {
processFile(event) { processFile(event) {
let file = event.target.files[0] const file = event.target.files[0]
let reader = new FileReader() const reader = new FileReader()
let selectedAddressbook = this.selectedAddressbook const selectedAddressbook = this.selectedAddressbook
this.$store.dispatch('changeStage', 'parsing') this.$store.dispatch('changeStage', 'parsing')
this.$store.dispatch('setAddressbook', selectedAddressbook.displayName) this.$store.dispatch('setAddressbook', selectedAddressbook.displayName)
let self = this const self = this
reader.onload = function(e) { reader.onload = function(e) {
self.$store.dispatch('importContactsIntoAddressbook', { vcf: reader.result, addressbook: selectedAddressbook }) self.$store.dispatch('importContactsIntoAddressbook', { vcf: reader.result, addressbook: selectedAddressbook })
// reset input // reset input
event.target.value = '' event.target.value = ''
} }
reader.readAsText(file) reader.readAsText(file)
} },
} },
} }
</script> </script>

View File

@ -74,7 +74,7 @@ export default {
OC.Notification.showTemporary(t('contacts', 'An error occurred, unable to create the addressbook.')) OC.Notification.showTemporary(t('contacts', 'An error occurred, unable to create the addressbook.'))
this.loading = false this.loading = false
}) })
} },
} },
} }
</script> </script>

View File

@ -46,20 +46,20 @@ export default {
return [ return [
{ {
label: t('contacts', 'First name'), label: t('contacts', 'First name'),
key: 'firstName' key: 'firstName',
}, },
{ {
label: t('contacts', 'Last name'), label: t('contacts', 'Last name'),
key: 'lastName' key: 'lastName',
}, },
{ {
label: t('contacts', 'Display name'), label: t('contacts', 'Display name'),
key: 'displayName' key: 'displayName',
}, },
{ {
label: t('contacts', 'Last modified'), label: t('contacts', 'Last modified'),
key: 'rev' key: 'rev',
} },
] ]
}, },
/* Current order Key */ /* Current order Key */
@ -68,7 +68,7 @@ export default {
}, },
orderKeyOption() { orderKeyOption() {
return this.options.filter(option => option.key === this.orderKey)[0] return this.options.filter(option => option.key === this.orderKey)[0]
} },
}, },
methods: { methods: {
sortContacts(orderKey) { sortContacts(orderKey) {
@ -79,7 +79,7 @@ export default {
}, },
formatSortByLabel(option) { formatSortByLabel(option) {
return t('contacts', 'Sort by {sorting}', { sorting: option.label }) return t('contacts', 'Sort by {sorting}', { sorting: option.label })
} },
} },
} }
</script> </script>

View File

@ -46,13 +46,13 @@ export default {
SettingsAddressbook, SettingsAddressbook,
SettingsNewAddressbook, SettingsNewAddressbook,
SettingsImportContacts, SettingsImportContacts,
SettingsSortContacts SettingsSortContacts,
}, },
computed: { computed: {
// store getters // store getters
addressbooks() { addressbooks() {
return this.$store.getters.getAddressbooks return this.$store.getters.getAddressbooks
} },
}, },
methods: { methods: {
onClickImport(event) { onClickImport(event) {
@ -60,7 +60,7 @@ export default {
}, },
onLoad(event) { onLoad(event) {
this.$emit('fileLoaded', false) this.$emit('fileLoaded', false)
} },
} },
} }
</script> </script>

View File

@ -75,7 +75,7 @@ if (window.location.pathname.split('/')[1] === 'index.php'
&& oc_config.modRewriteWorking) { && oc_config.modRewriteWorking) {
router.push({ router.push({
name: 'group', name: 'group',
params: { selectedGroup: t('contacts', 'All contacts') } params: { selectedGroup: t('contacts', 'All contacts') },
}) })
} }
@ -84,5 +84,5 @@ export default new Vue({
name: 'ContactsApp', name: 'ContactsApp',
router, router,
store, store,
render: h => h(App) render: h => h(App),
}) })

View File

@ -26,7 +26,7 @@ export default {
component: { component: {
type: Object, type: Object,
default: () => {}, default: () => {},
required: true required: true,
} },
} },
} }

View File

@ -28,51 +28,51 @@ export default {
// Default property type. e.g. "WORK,HOME" // Default property type. e.g. "WORK,HOME"
selectType: { selectType: {
type: [Object], type: [Object],
default: () => {} default: () => {},
}, },
// Coming from the rfcProps Model // Coming from the rfcProps Model
propModel: { propModel: {
type: Object, type: Object,
default: () => {}, default: () => {},
required: true required: true,
}, },
propType: { propType: {
type: String, type: String,
default: 'text' default: 'text',
}, },
// The current property passed as Object // The current property passed as Object
property: { property: {
type: Object, type: Object,
default: () => {}, default: () => {},
required: true required: true,
}, },
// Allows us to know if we need to // Allows us to know if we need to
// add the property header or not // add the property header or not
isFirstProperty: { isFirstProperty: {
type: Boolean, type: Boolean,
default: true default: true,
}, },
// Allows us to know if we need to // Allows us to know if we need to
// add an extra space at the end // add an extra space at the end
isLastProperty: { isLastProperty: {
type: Boolean, type: Boolean,
default: true default: true,
}, },
// Is it read-only? // Is it read-only?
isReadOnly: { isReadOnly: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
// The available TYPE options from the propModel // The available TYPE options from the propModel
// not used on the PropertySelect // not used on the PropertySelect
options: { options: {
type: Array, type: Array,
default: () => [] default: () => [],
}, },
localContact: { localContact: {
type: Contact, type: Contact,
default: null default: null,
} },
}, },
data() { data() {
@ -82,7 +82,7 @@ export default {
// many times as we can and debounce-fire the update // many times as we can and debounce-fire the update
// later // later
localValue: this.value, localValue: this.value,
localType: this.selectType localType: this.selectType,
} }
}, },
@ -92,7 +92,7 @@ export default {
}, },
haveAction() { haveAction() {
return this.actions && this.actions.length > 0 return this.actions && this.actions.length > 0
} },
}, },
watch: { watch: {
@ -106,7 +106,7 @@ export default {
}, },
selectType: function() { selectType: function() {
this.localType = this.selectType this.localType = this.selectType
} },
}, },
methods: { methods: {
@ -156,12 +156,12 @@ export default {
getNcGroupCount() { getNcGroupCount() {
const props = this.localContact.jCal[1] const props = this.localContact.jCal[1]
.map(prop => prop[0].split('.')[0]) // itemxxx.adr => itemxxx .map(prop => prop[0].split('.')[0]) // itemxxx.adr => itemxxx
.filter(name => name.startsWith('nextcloud')) // filter nextcloudxxx.adr .filter(name => name.startsWith('nextcloud')) // filter nextcloudxxx.adr
.map(prop => parseInt(prop.split('nextcloud')[1])) // nextcloudxxx => xxx .map(prop => parseInt(prop.split('nextcloud')[1])) // nextcloudxxx => xxx
return props.length > 0 return props.length > 0
? Math.max.apply(null, props) // get max iteration of nextcloud grouped props ? Math.max.apply(null, props) // get max iteration of nextcloud grouped props
: 0 : 0
} },
} },
} }

View File

@ -293,7 +293,7 @@ export default class Contact {
* @memberof Contact * @memberof Contact
*/ */
get groups() { get groups() {
let groupsProp = this.vCard.getFirstProperty('categories') const groupsProp = this.vCard.getFirstProperty('categories')
if (groupsProp) { if (groupsProp) {
return groupsProp.getValues() return groupsProp.getValues()
.filter(group => group.trim() !== '') .filter(group => group.trim() !== '')

View File

@ -33,14 +33,14 @@ const localesState = loadState('contacts', 'locales')
const locales = localesState const locales = localesState
? localesState.map(({ code, name }) => ({ ? localesState.map(({ code, name }) => ({
id: code.toLowerCase().replace('_', '-'), id: code.toLowerCase().replace('_', '-'),
name name,
})) }))
: [] : []
const properties = { const properties = {
nickname: { nickname: {
readableName: t('contacts', 'Nickname'), readableName: t('contacts', 'Nickname'),
icon: 'icon-user' icon: 'icon-user',
}, },
n: { n: {
readableName: t('contacts', 'Detailed name'), readableName: t('contacts', 'Detailed name'),
@ -49,25 +49,25 @@ const properties = {
t('contacts', 'First name'), t('contacts', 'First name'),
t('contacts', 'Additional names'), t('contacts', 'Additional names'),
t('contacts', 'Prefix'), t('contacts', 'Prefix'),
t('contacts', 'Suffix') t('contacts', 'Suffix'),
], ],
displayOrder: [3, 1, 2, 0, 4], displayOrder: [3, 1, 2, 0, 4],
defaultValue: { defaultValue: {
value: ['', '', '', '', ''] value: ['', '', '', '', ''],
}, },
icon: 'icon-user', icon: 'icon-user',
actions: [ actions: [
ActionCopyNtoFN ActionCopyNtoFN,
] ],
}, },
note: { note: {
readableName: t('contacts', 'Notes'), readableName: t('contacts', 'Notes'),
icon: 'icon-rename' icon: 'icon-rename',
}, },
url: { url: {
multiple: true, multiple: true,
readableName: t('contacts', 'Website'), readableName: t('contacts', 'Website'),
icon: 'icon-public' icon: 'icon-public',
}, },
geo: { geo: {
multiple: true, multiple: true,
@ -75,8 +75,8 @@ const properties = {
icon: 'icon-address', icon: 'icon-address',
defaultjCal: { defaultjCal: {
'3.0': [{}, 'FLOAT', '90.000;0.000'], '3.0': [{}, 'FLOAT', '90.000;0.000'],
'4.0': [{}, 'URI', 'geo:90.000,0.000'] '4.0': [{}, 'URI', 'geo:90.000,0.000'],
} },
}, },
cloud: { cloud: {
multiple: true, multiple: true,
@ -85,13 +85,13 @@ const properties = {
force: 'text', force: 'text',
defaultValue: { defaultValue: {
value: [''], value: [''],
type: [defaultProfileState] type: [defaultProfileState],
}, },
options: [ options: [
{ id: 'HOME', name: t('contacts', 'Home') }, { id: 'HOME', name: t('contacts', 'Home') },
{ id: 'WORK', name: t('contacts', 'Work') }, { id: 'WORK', name: t('contacts', 'Work') },
{ id: 'OTHER', name: t('contacts', 'Other') } { id: 'OTHER', name: t('contacts', 'Other') },
] ],
}, },
adr: { adr: {
multiple: true, multiple: true,
@ -103,31 +103,31 @@ const properties = {
t('contacts', 'City'), t('contacts', 'City'),
t('contacts', 'State or province'), t('contacts', 'State or province'),
t('contacts', 'Postal code'), t('contacts', 'Postal code'),
t('contacts', 'Country') t('contacts', 'Country'),
], ],
displayOrder: [0, 2, 1, 5, 3, 4, 6], displayOrder: [0, 2, 1, 5, 3, 4, 6],
icon: 'icon-address', icon: 'icon-address',
default: true, default: true,
defaultValue: { defaultValue: {
value: ['', '', '', '', '', '', ''], value: ['', '', '', '', '', '', ''],
type: [defaultProfileState] type: [defaultProfileState],
}, },
options: [ options: [
{ id: 'HOME', name: t('contacts', 'Home') }, { id: 'HOME', name: t('contacts', 'Home') },
{ id: 'WORK', name: t('contacts', 'Work') }, { id: 'WORK', name: t('contacts', 'Work') },
{ id: 'OTHER', name: t('contacts', 'Other') } { id: 'OTHER', name: t('contacts', 'Other') },
] ],
}, },
bday: { bday: {
readableName: t('contacts', 'Birthday'), readableName: t('contacts', 'Birthday'),
icon: 'icon-calendar-dark', icon: 'icon-calendar-dark',
force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant
defaultValue: { defaultValue: {
value: new VCardTime(null, null, 'date').fromJSDate(new Date()) value: new VCardTime(null, null, 'date').fromJSDate(new Date()),
}, },
actions: [ actions: [
ActionToggleYear ActionToggleYear,
] ],
}, },
anniversary: { anniversary: {
readableName: t('contacts', 'Anniversary'), readableName: t('contacts', 'Anniversary'),
@ -135,16 +135,16 @@ const properties = {
icon: 'icon-calendar-dark', icon: 'icon-calendar-dark',
force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant
defaultValue: { defaultValue: {
value: new VCardTime(null, null, 'date').fromJSDate(new Date()) value: new VCardTime(null, null, 'date').fromJSDate(new Date()),
} },
}, },
deathdate: { deathdate: {
readableName: t('contacts', 'Date of death'), readableName: t('contacts', 'Date of death'),
icon: 'icon-calendar-dark', icon: 'icon-calendar-dark',
force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant
defaultValue: { defaultValue: {
value: new VCardTime(null, null, 'date').fromJSDate(new Date()) value: new VCardTime(null, null, 'date').fromJSDate(new Date()),
} },
}, },
email: { email: {
multiple: true, multiple: true,
@ -153,13 +153,13 @@ const properties = {
default: true, default: true,
defaultValue: { defaultValue: {
value: '', value: '',
type: [defaultProfileState] type: [defaultProfileState],
}, },
options: [ options: [
{ id: 'HOME', name: t('contacts', 'Home') }, { id: 'HOME', name: t('contacts', 'Home') },
{ id: 'WORK', name: t('contacts', 'Work') }, { id: 'WORK', name: t('contacts', 'Work') },
{ id: 'OTHER', name: t('contacts', 'Other') } { id: 'OTHER', name: t('contacts', 'Other') },
] ],
}, },
impp: { impp: {
multiple: true, multiple: true,
@ -167,15 +167,15 @@ const properties = {
icon: 'icon-comment', icon: 'icon-comment',
defaultValue: { defaultValue: {
value: [''], value: [''],
type: ['SKYPE'] type: ['SKYPE'],
}, },
options: [ options: [
{ id: 'IRC', name: 'IRC' }, { id: 'IRC', name: 'IRC' },
{ id: 'KIK', name: 'KiK' }, { id: 'KIK', name: 'KiK' },
{ id: 'SKYPE', name: 'Skype' }, { id: 'SKYPE', name: 'Skype' },
{ id: 'TELEGRAM', name: 'Telegram' }, { id: 'TELEGRAM', name: 'Telegram' },
{ id: 'XMPP', name: 'XMPP' } { id: 'XMPP', name: 'XMPP' },
] ],
}, },
tel: { tel: {
multiple: true, multiple: true,
@ -184,7 +184,7 @@ const properties = {
default: true, default: true,
defaultValue: { defaultValue: {
value: '', value: '',
type: [defaultProfileState, 'VOICE'] type: [defaultProfileState, 'VOICE'],
}, },
options: [ options: [
{ id: 'HOME,VOICE', name: t('contacts', 'Home') }, { id: 'HOME,VOICE', name: t('contacts', 'Home') },
@ -201,8 +201,8 @@ const properties = {
{ id: 'PAGER', name: t('contacts', 'Pager') }, { id: 'PAGER', name: t('contacts', 'Pager') },
{ id: 'VOICE', name: t('contacts', 'Voice') }, { id: 'VOICE', name: t('contacts', 'Voice') },
{ id: 'CAR', name: t('contacts', 'Car') }, { id: 'CAR', name: t('contacts', 'Car') },
{ id: 'WORK,PAGER', name: t('contacts', 'Work pager') } { id: 'WORK,PAGER', name: t('contacts', 'Work pager') },
] ],
}, },
'x-socialprofile': { 'x-socialprofile': {
multiple: true, multiple: true,
@ -211,7 +211,7 @@ const properties = {
readableName: t('contacts', 'Social network'), readableName: t('contacts', 'Social network'),
defaultValue: { defaultValue: {
value: '', value: '',
type: ['facebook'] type: ['facebook'],
}, },
info: t( info: t(
'contacts', 'contacts',
@ -231,8 +231,8 @@ const properties = {
{ id: 'YOUTUBE', name: 'YouTube' }, { id: 'YOUTUBE', name: 'YouTube' },
{ id: 'MASTODON', name: 'Mastodon' }, { id: 'MASTODON', name: 'Mastodon' },
{ id: 'DIASPORA', name: 'Diaspora' }, { id: 'DIASPORA', name: 'Diaspora' },
{ id: 'OTHER', name: 'other Social Media' } { id: 'OTHER', name: 'other Social Media' },
] ],
}, },
relationship: { relationship: {
readableName: t('contacts', 'Relationship'), readableName: t('contacts', 'Relationship'),
@ -254,8 +254,8 @@ const properties = {
{ id: 'FRIEND', name: t('contacts', 'Friend') }, { id: 'FRIEND', name: t('contacts', 'Friend') },
{ id: 'COLLEAGUE', name: t('contacts', 'Colleague') }, { id: 'COLLEAGUE', name: t('contacts', 'Colleague') },
{ id: 'MANAGER', name: t('contacts', 'Manager') }, { id: 'MANAGER', name: t('contacts', 'Manager') },
{ id: 'ASSISTANT', name: t('contacts', 'Assistant') } { id: 'ASSISTANT', name: t('contacts', 'Assistant') },
] ],
}, },
related: { related: {
multiple: true, multiple: true,
@ -267,7 +267,7 @@ const properties = {
), ),
defaultValue: { defaultValue: {
value: [''], value: [''],
type: ['CONTACT'] type: ['CONTACT'],
}, },
options: [ options: [
{ id: 'CONTACT', name: t('contacts', 'Contact') }, { id: 'CONTACT', name: t('contacts', 'Contact') },
@ -285,14 +285,14 @@ const properties = {
{ id: 'PARENT', name: t('contacts', 'Parent') }, { id: 'PARENT', name: t('contacts', 'Parent') },
{ id: 'BROTHER', name: t('contacts', 'Brother') }, { id: 'BROTHER', name: t('contacts', 'Brother') },
{ id: 'SISTER', name: t('contacts', 'Sister') }, { id: 'SISTER', name: t('contacts', 'Sister') },
{ id: 'RELATIVE', name: t('contacts', 'Relative') } { id: 'RELATIVE', name: t('contacts', 'Relative') },
] ],
}, },
gender: { gender: {
readableName: t('contacts', 'Gender'), readableName: t('contacts', 'Gender'),
defaultValue: { defaultValue: {
// default to Female 🙋 // default to Female 🙋
value: 'F' value: 'F',
}, },
force: 'select', force: 'select',
options: [ options: [
@ -300,8 +300,8 @@ const properties = {
{ id: 'M', name: t('contacts', 'Male') }, { id: 'M', name: t('contacts', 'Male') },
{ id: 'O', name: t('contacts', 'Other') }, { id: 'O', name: t('contacts', 'Other') },
{ id: 'N', name: t('contacts', 'None') }, { id: 'N', name: t('contacts', 'None') },
{ id: 'U', name: t('contacts', 'Unknown') } { id: 'U', name: t('contacts', 'Unknown') },
] ],
}, },
tz: { tz: {
readableName: t('contacts', 'Timezone'), readableName: t('contacts', 'Timezone'),
@ -309,17 +309,17 @@ const properties = {
icon: 'icon-timezone', icon: 'icon-timezone',
options: zones.map(zone => ({ options: zones.map(zone => ({
id: zone, id: zone,
name: zone name: zone,
})) })),
}, },
lang: { lang: {
readableName: t('contacts', 'Spoken languages'), readableName: t('contacts', 'Spoken languages'),
icon: 'icon-language', icon: 'icon-language',
defaultValue: { defaultValue: {
value: 'en' value: 'en',
}, },
multiple: true multiple: true,
} },
} }
if (locales.length > 0) { if (locales.length > 0) {
@ -356,7 +356,7 @@ const fieldOrder = [
'note', 'note',
'categories', 'categories',
'role', 'role',
'gender' 'gender',
] ]
export default { properties, fieldOrder } export default { properties, fieldOrder }

View File

@ -446,5 +446,5 @@ export default [
'Pacific/Tarawa', 'Pacific/Tarawa',
'Pacific/Tongatapu', 'Pacific/Tongatapu',
'Pacific/Wake', 'Pacific/Wake',
'Pacific/Wallis' 'Pacific/Wallis',
] ]

View File

@ -42,20 +42,20 @@ export default new Router({
// always load default group // always load default group
redirect: { redirect: {
name: 'group', name: 'group',
params: { selectedGroup: t('contacts', 'All contacts') } params: { selectedGroup: t('contacts', 'All contacts') },
}, },
children: [ children: [
{ {
path: ':selectedGroup', path: ':selectedGroup',
name: 'group', name: 'group',
component: Contacts component: Contacts,
}, },
{ {
path: ':selectedGroup/:selectedContact', path: ':selectedGroup/:selectedContact',
name: 'contact', name: 'contact',
component: Contacts component: Contacts,
} },
] ],
} },
] ],
}) })

View File

@ -25,17 +25,17 @@ import { generateRemoteUrl } from 'nextcloud-router'
import { getRequestToken } from 'nextcloud-auth' import { getRequestToken } from 'nextcloud-auth'
function xhrProvider() { function xhrProvider() {
var headers = { const headers = {
'X-Requested-With': 'XMLHttpRequest', 'X-Requested-With': 'XMLHttpRequest',
'requesttoken': getRequestToken() 'requesttoken': getRequestToken(),
} }
var xhr = new XMLHttpRequest() const xhr = new XMLHttpRequest()
var oldOpen = xhr.open const oldOpen = xhr.open
// override open() method to add headers // override open() method to add headers
xhr.open = function() { xhr.open = function() {
var result = oldOpen.apply(this, arguments) const result = oldOpen.apply(this, arguments)
for (let name in headers) { for (const name in headers) {
xhr.setRequestHeader(name, headers[name]) xhr.setRequestHeader(name, headers[name])
} }
return result return result
@ -45,5 +45,5 @@ function xhrProvider() {
} }
export default new DavClient({ export default new DavClient({
rootUrl: generateRemoteUrl('dav') rootUrl: generateRemoteUrl('dav'),
}, xhrProvider) }, xhrProvider)

View File

@ -40,5 +40,5 @@ export default {
return true return true
} }
return false return false
} },
} }

View File

@ -60,5 +60,5 @@ export default {
console.error(error) console.error(error)
} }
return results return results
} },
} }

View File

@ -29,5 +29,5 @@ export default [
badGenderType, badGenderType,
duplicateTypes, duplicateTypes,
invalidREV, invalidREV,
missingFN missingFN,
] ]

View File

@ -52,5 +52,5 @@ export default {
} catch (error) { } catch (error) {
return false return false
} }
} },
} }

View File

@ -27,12 +27,12 @@
export default { export default {
name: 'missing FN', name: 'missing FN',
run: contact => { run: contact => {
return !contact.vCard.hasProperty('fn') // No FN return !contact.vCard.hasProperty('fn') // No FN
|| contact.vCard.getFirstPropertyValue('fn') === '' // Empty FN || contact.vCard.getFirstPropertyValue('fn') === '' // Empty FN
|| ( // we don't want to fix newly created contacts || ( // we don't want to fix newly created contacts
contact.dav // Existing contact contact.dav // Existing contact
&& contact.vCard.getFirstPropertyValue('fn') && contact.vCard.getFirstPropertyValue('fn')
.toLowerCase() === t('contacts', 'New contact').toLowerCase() // AND Unchanged FN .toLowerCase() === t('contacts', 'New contact').toLowerCase() // AND Unchanged FN
) )
}, },
fix: contact => { fix: contact => {
@ -60,5 +60,5 @@ export default {
return false return false
} }
return false return false
} },
} }

View File

@ -24,8 +24,8 @@ import Contact from '../models/contact'
import Store from '../store/index' import Store from '../store/index'
export default function parseVcf(data = '', addressbook) { export default function parseVcf(data = '', addressbook) {
let regexp = /BEGIN:VCARD[\s\S]*?END:VCARD/mgi const regexp = /BEGIN:VCARD[\s\S]*?END:VCARD/mgi
let vCards = data.match(regexp) const vCards = data.match(regexp)
if (!vCards) { if (!vCards) {
console.error('Error during the parsing of the following vcf file: ', data) console.error('Error during the parsing of the following vcf file: ', data)
@ -39,7 +39,7 @@ export default function parseVcf(data = '', addressbook) {
return vCards.reduce((contacts, vCard) => { return vCards.reduce((contacts, vCard) => {
try { try {
// console.log(vCards.indexOf(vCard)) // console.log(vCards.indexOf(vCard))
let contact = new Contact(vCard, addressbook) const contact = new Contact(vCard, addressbook)
contacts.push(contact) contacts.push(contact)
} catch (e) { } catch (e) {
// Parse error! Do not stop here... // Parse error! Do not stop here...

View File

@ -39,11 +39,11 @@ const addressbookModel = {
contacts: {}, contacts: {},
url: '', url: '',
readOnly: false, readOnly: false,
dav: false dav: false,
} }
const state = { const state = {
addressbooks: [] addressbooks: [],
} }
/** /**
@ -62,7 +62,7 @@ export function mapDavCollectionToAddressbook(addressbook) {
readOnly: addressbook.readOnly === true, readOnly: addressbook.readOnly === true,
url: addressbook.url, url: addressbook.url,
dav: addressbook, dav: addressbook,
shares: addressbook.shares.map(sharee => Object.assign({}, mapDavShareeToSharee(sharee))) shares: addressbook.shares.map(sharee => Object.assign({}, mapDavShareeToSharee(sharee))),
} }
} }
@ -82,7 +82,7 @@ export function mapDavShareeToSharee(sharee) {
id: id, id: id,
writeable: sharee.access[0].endsWith('read-write'), writeable: sharee.access[0].endsWith('read-write'),
isGroup: sharee.href.startsWith('principal:principals/groups/'), isGroup: sharee.href.startsWith('principal:principals/groups/'),
uri: sharee.href uri: sharee.href,
} }
} }
@ -164,7 +164,7 @@ const mutations = {
* @param {Contact} contact the contact to add * @param {Contact} contact the contact to add
*/ */
addContactToAddressbook(state, contact) { addContactToAddressbook(state, contact) {
let addressbook = state.addressbooks.find(search => search.id === contact.addressbook.id) const addressbook = state.addressbooks.find(search => search.id === contact.addressbook.id)
Vue.set(addressbook.contacts, contact.uid, contact) Vue.set(addressbook.contacts, contact.uid, contact)
}, },
@ -175,7 +175,7 @@ const mutations = {
* @param {Contact} contact the contact to delete * @param {Contact} contact the contact to delete
*/ */
deleteContactFromAddressbook(state, contact) { deleteContactFromAddressbook(state, contact) {
let addressbook = state.addressbooks.find(search => search.id === contact.addressbook.id) const addressbook = state.addressbooks.find(search => search.id === contact.addressbook.id)
Vue.delete(addressbook, contact.uid) Vue.delete(addressbook, contact.uid)
}, },
@ -197,7 +197,7 @@ const mutations = {
id: user, id: user,
writeable: false, writeable: false,
isGroup, isGroup,
uri uri,
} }
addressbook.shares.push(newSharee) addressbook.shares.push(newSharee)
}, },
@ -212,7 +212,7 @@ const mutations = {
*/ */
removeSharee(state, { addressbook, uri }) { removeSharee(state, { addressbook, uri }) {
addressbook = state.addressbooks.find(search => search.id === addressbook.id) addressbook = state.addressbooks.find(search => search.id === addressbook.id)
let shareIndex = addressbook.shares.findIndex(sharee => sharee.uri === uri) const shareIndex = addressbook.shares.findIndex(sharee => sharee.uri === uri)
addressbook.shares.splice(shareIndex, 1) addressbook.shares.splice(shareIndex, 1)
}, },
@ -226,14 +226,14 @@ const mutations = {
*/ */
updateShareeWritable(state, { addressbook, uri }) { updateShareeWritable(state, { addressbook, uri }) {
addressbook = state.addressbooks.find(search => search.id === addressbook.id) addressbook = state.addressbooks.find(search => search.id === addressbook.id)
let sharee = addressbook.shares.find(sharee => sharee.uri === uri) const sharee = addressbook.shares.find(sharee => sharee.uri === uri)
sharee.writeable = !sharee.writeable sharee.writeable = !sharee.writeable
} },
} }
const getters = { const getters = {
getAddressbooks: state => state.addressbooks getAddressbooks: state => state.addressbooks,
} }
const actions = { const actions = {
@ -245,7 +245,7 @@ const actions = {
* @returns {Object[]} the addressbooks * @returns {Object[]} the addressbooks
*/ */
async getAddressbooks(context) { async getAddressbooks(context) {
let addressbooks = await client.addressBookHomes[0] const addressbooks = await client.addressBookHomes[0]
.findAllAddressBooks() .findAllAddressBooks()
.then(addressbooks => { .then(addressbooks => {
return addressbooks.map(addressbook => { return addressbooks.map(addressbook => {
@ -347,10 +347,10 @@ const actions = {
// We don't want to lose the url information // We don't want to lose the url information
// so we need to parse one by one // so we need to parse one by one
let failed = 0 let failed = 0
let contacts = response const contacts = response
.reduce((contacts, item) => { .reduce((contacts, item) => {
try { try {
let contact = new Contact(item.data, addressbook) const contact = new Contact(item.data, addressbook)
Vue.set(contact, 'dav', item) Vue.set(contact, 'dav', item)
contacts.push(contact) contacts.push(contact)
} catch (error) { } catch (error) {
@ -405,7 +405,7 @@ const actions = {
// Get vcard string // Get vcard string
try { try {
let vData = ICAL.stringify(contact.vCard.jCal) const vData = ICAL.stringify(contact.vCard.jCal)
// push contact to server and use limit // push contact to server and use limit
requests.push(limit(() => contact.addressbook.dav.createVCard(vData) requests.push(limit(() => contact.addressbook.dav.createVCard(vData)
.then((response) => { .then((response) => {
@ -509,7 +509,7 @@ const actions = {
await context.commit('updateContactAddressbook', { contact, addressbook }) await context.commit('updateContactAddressbook', { contact, addressbook })
await context.commit('addContactToAddressbook', contact) await context.commit('addContactToAddressbook', contact)
return contact return contact
} },
} }
export default { state, mutations, getters, actions } export default { state, mutations, getters, actions }

View File

@ -26,14 +26,14 @@ import Contact from '../models/contact'
import validate from '../services/validate' import validate from '../services/validate'
const sortData = (a, b) => { const sortData = (a, b) => {
var nameA = typeof a.value === 'string' const nameA = typeof a.value === 'string'
? a.value.toUpperCase() // ignore upper and lowercase ? a.value.toUpperCase() // ignore upper and lowercase
: a.value.toUnixTime() // only other sorting we support is a vCardTime : a.value.toUnixTime() // only other sorting we support is a vCardTime
var nameB = typeof b.value === 'string' const nameB = typeof b.value === 'string'
? b.value.toUpperCase() // ignore upper and lowercase ? b.value.toUpperCase() // ignore upper and lowercase
: b.value.toUnixTime() // only other sorting we support is a vCardTime : b.value.toUnixTime() // only other sorting we support is a vCardTime
let score = nameA.localeCompare const score = nameA.localeCompare
? nameA.localeCompare(nameB) ? nameA.localeCompare(nameB)
: nameB - nameA : nameB - nameA
// if equal, fallback to the key // if equal, fallback to the key
@ -47,7 +47,7 @@ const state = {
// https://codepen.io/skjnldsv/pen/ZmKvQo // https://codepen.io/skjnldsv/pen/ZmKvQo
contacts: {}, contacts: {},
sortedContacts: [], sortedContacts: [],
orderKey: 'displayName' orderKey: 'displayName',
} }
const mutations = { const mutations = {
@ -79,7 +79,7 @@ const mutations = {
deleteContact(state, contact) { deleteContact(state, contact) {
if (state.contacts[contact.key] && contact instanceof Contact) { if (state.contacts[contact.key] && contact instanceof Contact) {
let index = state.sortedContacts.findIndex(search => search.key === contact.key) const index = state.sortedContacts.findIndex(search => search.key === contact.key)
state.sortedContacts.splice(index, 1) state.sortedContacts.splice(index, 1)
Vue.delete(state.contacts, contact.key) Vue.delete(state.contacts, contact.key)
@ -100,14 +100,14 @@ const mutations = {
// Checking contact validity 🔍🙈 // Checking contact validity 🔍🙈
validate(contact) validate(contact)
let sortedContact = { const sortedContact = {
key: contact.key, key: contact.key,
value: contact[state.orderKey] value: contact[state.orderKey],
} }
// Not using sort, splice has far better performances // Not using sort, splice has far better performances
// https://jsperf.com/sort-vs-splice-in-array // https://jsperf.com/sort-vs-splice-in-array
for (var i = 0, len = state.sortedContacts.length; i < len; i++) { for (let i = 0, len = state.sortedContacts.length; i < len; i++) {
if (sortData(state.sortedContacts[i], sortedContact) >= 0) { if (sortData(state.sortedContacts[i], sortedContact) >= 0) {
state.sortedContacts.splice(i, 0, sortedContact) state.sortedContacts.splice(i, 0, sortedContact)
break break
@ -141,10 +141,10 @@ const mutations = {
// replace contact object data // replace contact object data
state.contacts[contact.key].updateContact(contact.jCal) state.contacts[contact.key].updateContact(contact.jCal)
let sortedContact = state.sortedContacts.find(search => search.key === contact.key) const sortedContact = state.sortedContacts.find(search => search.key === contact.key)
// has the sort key changed for this contact ? // has the sort key changed for this contact ?
let hasChanged = sortedContact.value !== contact[state.orderKey] const hasChanged = sortedContact.value !== contact[state.orderKey]
if (hasChanged) { if (hasChanged) {
// then update the new data // then update the new data
sortedContact.value = contact[state.orderKey] sortedContact.value = contact[state.orderKey]
@ -168,10 +168,10 @@ const mutations = {
updateContactAddressbook(state, { contact, addressbook }) { updateContactAddressbook(state, { contact, addressbook }) {
if (state.contacts[contact.key] && contact instanceof Contact) { if (state.contacts[contact.key] && contact instanceof Contact) {
// replace contact object data by creating a new contact // replace contact object data by creating a new contact
let oldKey = contact.key const oldKey = contact.key
// hijack reference // hijack reference
var newContact = contact const newContact = contact
// delete old key, cut reference // delete old key, cut reference
Vue.delete(state.contacts, oldKey) Vue.delete(state.contacts, oldKey)
@ -183,10 +183,10 @@ const mutations = {
Vue.set(state.contacts, newContact.key, newContact) Vue.set(state.contacts, newContact.key, newContact)
// Update sorted contacts list, replace at exact same position // Update sorted contacts list, replace at exact same position
let index = state.sortedContacts.findIndex(search => search.key === oldKey) const index = state.sortedContacts.findIndex(search => search.key === oldKey)
state.sortedContacts[index] = { state.sortedContacts[index] = {
key: newContact.key, key: newContact.key,
value: newContact[state.orderKey] value: newContact[state.orderKey],
} }
} else { } else {
console.error('Error while replacing the addressbook of following contact', contact) console.error('Error while replacing the addressbook of following contact', contact)
@ -267,14 +267,14 @@ const mutations = {
} else { } else {
console.error('Error while handling the following contact', contact) console.error('Error while handling the following contact', contact)
} }
} },
} }
const getters = { const getters = {
getContacts: state => state.contacts, getContacts: state => state.contacts,
getSortedContacts: state => state.sortedContacts, getSortedContacts: state => state.sortedContacts,
getContact: (state) => (key) => state.contacts[key], getContact: (state) => (key) => state.contacts[key],
getOrderKey: state => state.orderKey getOrderKey: state => state.orderKey,
} }
const actions = { const actions = {
@ -330,7 +330,7 @@ const actions = {
rev.fromUnixTime(Date.now() / 1000) rev.fromUnixTime(Date.now() / 1000)
contact.rev = rev contact.rev = rev
let vData = ICAL.stringify(contact.vCard.jCal) const vData = ICAL.stringify(contact.vCard.jCal)
// if no dav key, contact does not exists on server // if no dav key, contact does not exists on server
if (!contact.dav) { if (!contact.dav) {
@ -380,11 +380,11 @@ const actions = {
} }
return contact.dav.fetchCompleteData() return contact.dav.fetchCompleteData()
.then((response) => { .then((response) => {
let newContact = new Contact(contact.dav.data, contact.addressbook) const newContact = new Contact(contact.dav.data, contact.addressbook)
context.commit('updateContact', newContact) context.commit('updateContact', newContact)
}) })
.catch((error) => { throw error }) .catch((error) => { throw error })
} },
} }
export default { state, mutations, getters, actions } export default { state, mutations, getters, actions }

View File

@ -21,7 +21,7 @@
*/ */
const state = { const state = {
groups: [] groups: [],
} }
const mutations = { const mutations = {
@ -42,7 +42,7 @@ const mutations = {
if (!group) { if (!group) {
state.groups.push({ state.groups.push({
name: groupName, name: groupName,
contacts: [] contacts: [],
}) })
group = state.groups.find(search => search.name === groupName) group = state.groups.find(search => search.name === groupName)
} }
@ -67,7 +67,7 @@ const mutations = {
if (!group) { if (!group) {
state.groups.push({ state.groups.push({
name: groupName, name: groupName,
contacts: [] contacts: [],
}) })
group = state.groups.find(search => search.name === groupName) group = state.groups.find(search => search.name === groupName)
} }
@ -84,8 +84,8 @@ const mutations = {
* @param {Contact} data.contact the contact * @param {Contact} data.contact the contact
*/ */
removeContactToGroup(state, { groupName, contact }) { removeContactToGroup(state, { groupName, contact }) {
let contacts = state.groups.find(search => search.name === groupName).contacts const contacts = state.groups.find(search => search.name === groupName).contacts
let index = contacts.findIndex(search => search === contact.key) const index = contacts.findIndex(search => search === contact.key)
if (index > -1) { if (index > -1) {
contacts.splice(index, 1) contacts.splice(index, 1)
} }
@ -104,11 +104,11 @@ const mutations = {
group.contacts.splice(index, 1) group.contacts.splice(index, 1)
} }
}) })
} },
} }
const getters = { const getters = {
getGroups: state => state.groups getGroups: state => state.groups,
} }
const actions = { const actions = {
@ -145,7 +145,7 @@ const actions = {
*/ */
removeContactToGroup(context, { groupName, contact }) { removeContactToGroup(context, { groupName, contact }) {
context.commit('removeContactToGroup', { groupName, contact }) context.commit('removeContactToGroup', { groupName, contact })
} },
} }
export default { state, mutations, getters, actions } export default { state, mutations, getters, actions }

View File

@ -26,8 +26,8 @@ const state = {
accepted: 0, accepted: 0,
denied: 0, denied: 0,
stage: 'default', stage: 'default',
addressbook: '' addressbook: '',
} },
} }
const mutations = { const mutations = {
@ -88,11 +88,11 @@ const mutations = {
state.importState.total = 0 state.importState.total = 0
state.importState.accepted = 0 state.importState.accepted = 0
state.importState.denied = 0 state.importState.denied = 0
} },
} }
const getters = { const getters = {
getImportState: state => state.importState getImportState: state => state.importState,
} }
const actions = { const actions = {
@ -146,7 +146,7 @@ const actions = {
if (stage === 'parsing') { if (stage === 'parsing') {
context.commit('resetState') context.commit('resetState')
} }
} },
} }
export default { state, mutations, getters, actions } export default { state, mutations, getters, actions }

View File

@ -36,10 +36,10 @@ export default new Store({
addressbooks, addressbooks,
contacts, contacts,
groups, groups,
importState importState,
}, },
mutations mutations,
/** /**
* the contat ical update itself on property getters * the contat ical update itself on property getters

View File

@ -80,7 +80,7 @@ import {
AppNavigationNew, AppNavigationNew,
AppNavigationSettings, AppNavigationSettings,
Content, Content,
Modal Modal,
} from 'nextcloud-vue' } from 'nextcloud-vue'
import isMobile from 'nextcloud-vue/dist/Mixins/isMobile' import isMobile from 'nextcloud-vue/dist/Mixins/isMobile'
@ -115,11 +115,11 @@ export default {
Content, Content,
ImportScreen, ImportScreen,
Modal, Modal,
SettingsSection SettingsSection,
}, },
mixins: [ mixins: [
isMobile isMobile,
], ],
// passed by the router // passed by the router
@ -127,18 +127,18 @@ export default {
selectedGroup: { selectedGroup: {
type: String, type: String,
default: undefined, default: undefined,
required: true required: true,
}, },
selectedContact: { selectedContact: {
type: String, type: String,
default: undefined default: undefined,
} },
}, },
data() { data() {
return { return {
loading: true, loading: true,
searchQuery: '' searchQuery: '',
} }
}, },
@ -190,7 +190,7 @@ export default {
} else if (this.selectedGroup === GROUP_NO_GROUP_CONTACTS) { } else if (this.selectedGroup === GROUP_NO_GROUP_CONTACTS) {
return this.ungroupedContacts.map(contact => this.sortedContacts.find(item => item.key === contact.key)) return this.ungroupedContacts.map(contact => this.sortedContacts.find(item => item.key === contact.key))
} }
let group = this.groups.filter(group => group.name === this.selectedGroup)[0] const group = this.groups.filter(group => group.name === this.selectedGroup)[0]
if (group) { if (group) {
return this.sortedContacts.filter(contact => group.contacts.indexOf(contact.key) >= 0) return this.sortedContacts.filter(contact => group.contacts.indexOf(contact.key) >= 0)
} }
@ -209,7 +209,7 @@ export default {
key: group.name.replace(' ', '_'), key: group.name.replace(' ', '_'),
router: { router: {
name: 'group', name: 'group',
params: { selectedGroup: group.name } params: { selectedGroup: group.name },
}, },
text: group.name, text: group.name,
utils: { utils: {
@ -218,10 +218,10 @@ export default {
{ {
icon: 'icon-download', icon: 'icon-download',
text: 'Download', text: 'Download',
action: () => this.downloadGroup(group) action: () => this.downloadGroup(group),
} },
] ],
} },
} }
}).sort(function(a, b) { }).sort(function(a, b) {
return parseInt(b.utils.counter) - parseInt(a.utils.counter) return parseInt(b.utils.counter) - parseInt(a.utils.counter)
@ -241,12 +241,12 @@ export default {
icon: 'icon-contacts-dark', icon: 'icon-contacts-dark',
router: { router: {
name: 'group', name: 'group',
params: { selectedGroup: GROUP_ALL_CONTACTS } params: { selectedGroup: GROUP_ALL_CONTACTS },
}, },
text: GROUP_ALL_CONTACTS, text: GROUP_ALL_CONTACTS,
utils: { utils: {
counter: this.sortedContacts.length counter: this.sortedContacts.length,
} },
}] }]
}, },
@ -261,14 +261,14 @@ export default {
icon: 'icon-user', icon: 'icon-user',
router: { router: {
name: 'group', name: 'group',
params: { selectedGroup: GROUP_NO_GROUP_CONTACTS } params: { selectedGroup: GROUP_NO_GROUP_CONTACTS },
}, },
text: GROUP_NO_GROUP_CONTACTS, text: GROUP_NO_GROUP_CONTACTS,
utils: { utils: {
counter: this.ungroupedContacts.length counter: this.ungroupedContacts.length,
} },
}] }]
} },
}, },
watch: { watch: {
@ -283,7 +283,7 @@ export default {
if (!this.isMobile) { if (!this.isMobile) {
this.selectFirstContactIfNone() this.selectFirstContactIfNone()
} }
} },
}, },
mounted() { mounted() {
@ -336,11 +336,11 @@ export default {
// itterate over all properties (filter is not usable on objects and we need the key of the property) // itterate over all properties (filter is not usable on objects and we need the key of the property)
const properties = rfcProps.properties const properties = rfcProps.properties
for (let name in properties) { for (const name in properties) {
if (properties[name].default) { if (properties[name].default) {
let defaultData = properties[name].defaultValue const defaultData = properties[name].defaultValue
// add default field // add default field
let property = contact.vCard.addPropertyWithValue(name, defaultData.value) const property = contact.vCard.addPropertyWithValue(name, defaultData.value)
// add default type // add default type
if (defaultData.type) { if (defaultData.type) {
property.setParameter('type', defaultData.type) property.setParameter('type', defaultData.type)
@ -361,8 +361,8 @@ export default {
name: 'contact', name: 'contact',
params: { params: {
selectedGroup: this.selectedGroup, selectedGroup: this.selectedGroup,
selectedContact: contact.key selectedContact: contact.key,
} },
}) })
} catch (error) { } catch (error) {
OC.Notification.showTemporary(t('contacts', 'Unable to create the contact.')) OC.Notification.showTemporary(t('contacts', 'Unable to create the contact.'))
@ -402,7 +402,7 @@ export default {
* if none are selected already * if none are selected already
*/ */
selectFirstContactIfNone() { selectFirstContactIfNone() {
let inList = this.contactsList.findIndex(contact => contact.key === this.selectedContact) > -1 const inList = this.contactsList.findIndex(contact => contact.key === this.selectedContact) > -1
if (this.selectedContact === undefined || !inList) { if (this.selectedContact === undefined || !inList) {
if (this.selectedContact && !inList) { if (this.selectedContact && !inList) {
OC.Notification.showTemporary(t('contacts', 'Contact not found')) OC.Notification.showTemporary(t('contacts', 'Contact not found'))
@ -412,8 +412,8 @@ export default {
name: 'contact', name: 'contact',
params: { params: {
selectedGroup: this.selectedGroup, selectedGroup: this.selectedGroup,
selectedContact: Object.values(this.contactsList)[0].key selectedContact: Object.values(this.contactsList)[0].key,
} },
}) })
} }
} }
@ -444,8 +444,8 @@ export default {
groupedContacts = Object.assign({ groupedContacts = Object.assign({
[id]: { [id]: {
addressbook: this.contacts[key].addressbook, addressbook: this.contacts[key].addressbook,
contacts: [] contacts: [],
} },
}, groupedContacts) }, groupedContacts)
groupedContacts[id].contacts.push(this.contacts[key].url) groupedContacts[id].contacts.push(this.contacts[key].url)
}) })
@ -455,7 +455,7 @@ export default {
groupedContacts[key].addressbook.dav.addressbookMultigetExport(groupedContacts[key].contacts))) groupedContacts[key].addressbook.dav.addressbookMultigetExport(groupedContacts[key].contacts)))
.then(response => ({ .then(response => ({
groupName: group.name, groupName: group.name,
data: response.map(data => data.body).join('') data: response.map(data => data.body).join(''),
})) }))
// download vcard // download vcard
this.downloadVcardPromise(vcardPromise) this.downloadVcardPromise(vcardPromise)
@ -478,8 +478,8 @@ export default {
name: 'contact', name: 'contact',
params: { params: {
selectedGroup: this.selectedGroup, selectedGroup: this.selectedGroup,
selectedContact: undefined selectedContact: undefined,
} },
}) })
}, },
@ -491,7 +491,7 @@ export default {
if (this.isImportDone) { if (this.isImportDone) {
this.$store.dispatch('changeStage', 'default') this.$store.dispatch('changeStage', 'default')
} }
} },
} },
} }
</script> </script>

View File

@ -30,7 +30,7 @@ global.expect = require('chai').expect
window.Date = Date window.Date = Date
global.OC = { global.OC = {
getLocale: () => 'en' getLocale: () => 'en',
} }
global.t = (app, text) => text global.t = (app, text) => text

View File

@ -23,10 +23,3 @@
// eslint-disable-next-line node/no-unpublished-import // eslint-disable-next-line node/no-unpublished-import
// import { mount } from '@vue/test-utils' // import { mount } from '@vue/test-utils'
// import Contacts from '../../../src/views/Contacts.vue' // import Contacts from '../../../src/views/Contacts.vue'
// describe('Contacts.vue', () => {
// it('Test contacts view', () => {
// const wrapper = mount(Contacts)
// expect(wrapper.text()).toContain('Test')
// })
// })