diff --git a/Makefile b/Makefile index 58148822..72717d70 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ all: dev-setup lint build-js-production test test-php dev-setup: clean clean-dev npm-init npm-init: - npm install + npm ci npm-update: npm update diff --git a/package-lock.json b/package-lock.json index 7426aeef..43b8243e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4650,9 +4650,9 @@ } }, "eslint-config-nextcloud": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/eslint-config-nextcloud/-/eslint-config-nextcloud-0.0.6.tgz", - "integrity": "sha512-ktCzXVA8GrqZVljutkBKOq2hgKvzKyLhNCAB5bCjdmMo7DIky2ZYeMtDmiEUZCPoXbSJY0kyvnZPbcN4VYzyCg==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-nextcloud/-/eslint-config-nextcloud-0.1.0.tgz", + "integrity": "sha512-qaxA/OZzfa4G4JQt0UGNs8uJcKsln7UM71R2vdiSpcgKW5hJ6tqtPP7RExS+4osBOl7ntiXihg9bj7PUwqsNaA==", "dev": true }, "eslint-config-standard": { diff --git a/package.json b/package.json index fbfb29a7..d3aa5845 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "chai": "^4.2.0", "css-loader": "^3.2.1", "eslint": "^5.16.0", - "eslint-config-nextcloud": "0.0.6", + "eslint-config-nextcloud": "0.1.0", "eslint-config-standard": "^12.0.0", "eslint-import-resolver-webpack": "^0.11.1", "eslint-loader": "^3.0.3", diff --git a/src/ContactsRoot.vue b/src/ContactsRoot.vue index 06ab1b3e..9fdd4d87 100644 --- a/src/ContactsRoot.vue +++ b/src/ContactsRoot.vue @@ -26,6 +26,6 @@ diff --git a/src/components/Actions/ActionCopyNtoFN.vue b/src/components/Actions/ActionCopyNtoFN.vue index 278239c6..0d756f7e 100644 --- a/src/components/Actions/ActionCopyNtoFN.vue +++ b/src/components/Actions/ActionCopyNtoFN.vue @@ -32,7 +32,7 @@ import ActionsMixin from '../../mixins/ActionsMixin' export default { name: 'ActionCopyNtoFN', components: { - ActionButton + ActionButton, }, mixins: [ActionsMixin], methods: { @@ -45,7 +45,7 @@ export default { this.component.contact.fullName = n.slice(0, 2).reverse().join(' ') this.component.updateContact() } - } - } + }, + }, } diff --git a/src/components/Actions/ActionToggleYear.vue b/src/components/Actions/ActionToggleYear.vue index 0ad9dacd..9bc3e1b4 100644 --- a/src/components/Actions/ActionToggleYear.vue +++ b/src/components/Actions/ActionToggleYear.vue @@ -34,12 +34,12 @@ import ActionsMixin from '../../mixins/ActionsMixin' export default { name: 'ActionToggleYear', components: { - ActionCheckbox + ActionCheckbox, }, mixins: [ActionsMixin], data() { return { - omitYear: false + omitYear: false, } }, @@ -74,7 +74,7 @@ export default { const dateObject = this.component.localValue.toJSON() this.component.updateValue(dateObject, true) this.omitYear = !this.omitYear - } - } + }, + }, } diff --git a/src/components/ContactDetails.vue b/src/components/ContactDetails.vue index 364d6316..e0980985 100644 --- a/src/components/ContactDetails.vue +++ b/src/components/ContactDetails.vue @@ -218,18 +218,18 @@ export default { ContactProperty, PropertyGroups, PropertyRev, - PropertySelect + PropertySelect, }, props: { loading: { type: Boolean, - default: true + default: true, }, contactKey: { type: String, - default: undefined - } + default: undefined, + }, }, data() { @@ -246,7 +246,7 @@ export default { loadingData: true, loadingUpdate: false, openedMenu: false, - qrcode: '' + qrcode: '', } }, @@ -267,12 +267,12 @@ export default { if (!this.contact.dav) { return { 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) { return { 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 @@ -297,7 +297,7 @@ export default { */ colorAvatar() { try { - let color = this.contact.uid.toRgb() + const color = this.contact.uid.toRgb() return `rgb(${color.r}, ${color.g}, ${color.b})` } catch (e) { return 'grey' @@ -328,7 +328,7 @@ export default { return { readableName: t('contacts', 'Addressbook'), icon: 'icon-address-book', - options: this.addressbooksOptions + options: this.addressbooksOptions, } }, @@ -344,7 +344,7 @@ export default { }, set: function(addressbookId) { this.moveContactToAddressbook(addressbookId) - } + }, }, /** @@ -355,7 +355,7 @@ export default { groupsModel() { return { readableName: t('contacts', 'Groups'), - icon: 'icon-contacts' + icon: 'icon-contacts', } }, @@ -372,7 +372,7 @@ export default { set: function(data) { this.contact.groups = data this.debounceUpdateContact() - } + }, }, /** @@ -386,7 +386,7 @@ export default { .map(addressbook => { return { id: addressbook.id, - name: addressbook.displayName + name: addressbook.displayName, } }) }, @@ -397,7 +397,7 @@ export default { }, contact() { return this.$store.getters.getContact(this.contactKey) - } + }, }, watch: { @@ -405,7 +405,7 @@ export default { if (this.contactKey) { this.selectContact(this.contactKey) } - } + }, }, beforeMount() { @@ -454,11 +454,11 @@ export default { * Generate a qrcode for the contact */ showQRcode() { - let jCal = this.contact.jCal.slice(0) + const jCal = this.contact.jCal.slice(0) // do not encode photo jCal[1] = jCal[1].filter(props => props[0] !== 'photo') - let data = stringify(jCal) + const data = stringify(jCal) if (data.length > 0) { this.qrcode = btoa(qr.imageSync(data, { type: 'svg' })) } @@ -483,7 +483,7 @@ export default { async selectContact(key) { // local version of the contact this.loadingData = true - let contact = this.$store.getters.getContact(key) + const contact = this.$store.getters.getContact(key) if (contact) { // if contact exists AND if exists on server @@ -524,7 +524,7 @@ export default { * @param {string} addressbookId the desired addressbook ID */ async moveContactToAddressbook(addressbookId) { - let addressbook = this.addressbooks.find(search => search.id === addressbookId) + const addressbook = this.addressbooks.find(search => search.id === addressbookId) this.loadingUpdate = true if (addressbook) { try { @@ -532,15 +532,15 @@ export default { // we need to use the store contact, not the local contact // using this.contact and not this.localContact contact: this.contact, - addressbook + addressbook, }) // select the contact again this.$router.push({ name: 'contact', params: { selectedGroup: this.$route.params.selectedGroup, - selectedContact: contact.key - } + selectedContact: contact.key, + }, }) } catch (error) { console.error(error) @@ -572,7 +572,7 @@ export default { */ updateLocalContact(contact) { // create empty contact and copy inner data - let localContact = Object.assign( + const localContact = Object.assign( Object.create(Object.getPrototypeOf(contact)), contact ) @@ -588,7 +588,7 @@ export default { e.preventDefault() this.debounceUpdateContact() } - } - } + }, + }, } diff --git a/src/components/ContactDetails/ContactDetailsAddNewProp.vue b/src/components/ContactDetails/ContactDetailsAddNewProp.vue index 13520ac7..c6b3ac64 100644 --- a/src/components/ContactDetails/ContactDetailsAddNewProp.vue +++ b/src/components/ContactDetails/ContactDetailsAddNewProp.vue @@ -49,14 +49,14 @@ export default { name: 'ContactDetailsAddNewProp', components: { - PropertyTitle + PropertyTitle, }, props: { contact: { type: Contact, - default: null - } + default: null, + }, }, computed: { @@ -92,10 +92,10 @@ export default { .map(key => { return { id: key, - name: this.properties[key].readableName + name: this.properties[key].readableName, } }).sort((a, b) => a.name.localeCompare(b.name)) - } + }, }, methods: { @@ -108,17 +108,17 @@ export default { addProp({ id }) { if (this.properties[id] && this.properties[id].defaultjCal && this.properties[id].defaultjCal[this.contact.version]) { - let defaultjCal = this.properties[id].defaultjCal[this.contact.version] - let property = new ICAL.Property([id, ...defaultjCal]) + const defaultjCal = this.properties[id].defaultjCal[this.contact.version] + const property = new ICAL.Property([id, ...defaultjCal]) this.contact.vCard.addProperty(property) } else { - let defaultData = this.properties[id].defaultValue - let property = this.contact.vCard.addPropertyWithValue(id, defaultData ? defaultData.value : '') + const defaultData = this.properties[id].defaultValue + const property = this.contact.vCard.addPropertyWithValue(id, defaultData ? defaultData.value : '') if (defaultData && defaultData.type) { property.setParameter('type', defaultData.type) } } - } - } + }, + }, } diff --git a/src/components/ContactDetails/ContactDetailsAvatar.vue b/src/components/ContactDetails/ContactDetailsAvatar.vue index a8762983..8aa0e125 100644 --- a/src/components/ContactDetails/ContactDetailsAvatar.vue +++ b/src/components/ContactDetails/ContactDetailsAvatar.vue @@ -98,14 +98,14 @@ export default { components: { ActionLink, - ActionButton + ActionButton, }, props: { contact: { type: Object, - required: true - } + required: true, + }, }, data() { @@ -115,7 +115,7 @@ export default { loading: false, root: generateRemoteUrl(`dav/files/${OC.getCurrentUser().uid}`), width: 0, - height: 0 + height: 0, } }, computed: { @@ -124,7 +124,7 @@ export default { return this.contact.addressbook.readOnly } return false - } + }, }, mounted() { // update image size on window resize @@ -142,10 +142,10 @@ export default { if (event.target.files && !this.loading) { this.closeMenu() - let file = event.target.files[0] + const file = event.target.files[0] if (file && file.size && file.size <= 1 * 1024 * 1024) { - let reader = new FileReader() - let self = this + const reader = new FileReader() + const self = this reader.onload = function(e) { // only getting the raw binary base64 @@ -228,7 +228,7 @@ export default { 'image/gif', 'image/x-xbitmap', 'image/bmp', - 'image/svg+xml' + 'image/svg+xml', ]) .build() @@ -238,7 +238,7 @@ export default { try { const { get } = await axios() const response = await get(`${this.root}${file}`, { - responseType: 'arraybuffer' + responseType: 'arraybuffer', }) const type = response.headers['content-type'] const data = Buffer.from(response.data, 'binary').toString('base64') @@ -317,9 +317,9 @@ export default { } } } - } + }, - } + }, } diff --git a/src/components/ContactDetails/ContactDetailsProperty.vue b/src/components/ContactDetails/ContactDetailsProperty.vue index ece501e1..bcbfbe4e 100644 --- a/src/components/ContactDetails/ContactDetailsProperty.vue +++ b/src/components/ContactDetails/ContactDetailsProperty.vue @@ -57,25 +57,25 @@ export default { props: { property: { type: Property, - default: true + default: true, }, sortedProperties: { type: Array, default() { return [] - } + }, }, index: { type: Number, - default: 0 + default: 0, }, contact: { type: Contact, - default: null + default: null, }, localContact: { type: Contact, - default: null + default: null, }, /** * This is needed so that we can update @@ -83,8 +83,8 @@ export default { */ updateContact: { type: Function, - default: () => {} - } + default: () => {}, + }, }, computed: { @@ -222,12 +222,12 @@ export default { if (this.propLabel) { return { id: this.propLabel.name, - name: this.propLabel.getFirstValue() + name: this.propLabel.getFirstValue(), } } if (this.propModel && this.propModel.options && this.type) { - let selectedType = this.type + const selectedType = this.type // vcard 3.0 save pref alongside TYPE .filter(type => type !== 'pref') // 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 // sorting directly is cleaner but slower // https://jsperf.com/array-map-and-intersection-perf - let matchingTypes = this.propModel.options + const matchingTypes = this.propModel.options .map(type => { return { type, // "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 - let matchingType = matchingTypes + const matchingType = matchingTypes .sort((a, b) => b.score - a.score) .filter(type => type.score > 0)[0] @@ -256,13 +256,13 @@ export default { } if (this.type) { // vcard 3.0 save pref alongside TYPE - let selectedType = this.type + const selectedType = this.type .filter(type => type !== 'pref') .join(',') if (selectedType.trim() !== '') { return { id: selectedType, - name: selectedType + name: selectedType, } } } @@ -291,7 +291,7 @@ export default { } } this.updateContact() - } + }, }, @@ -316,13 +316,13 @@ export default { this.property.setValue(data) } this.updateContact() - } + }, }, // property meta type type: { get() { - let type = this.property.getParameter('type') + const type = this.property.getParameter('type') // ensure we have an array if (type) { return Array.isArray(type) ? type : [type] @@ -331,7 +331,7 @@ export default { }, set(data) { this.property.setParameter('type', data) - } + }, }, // property meta pref @@ -341,8 +341,8 @@ export default { }, set(data) { this.property.setParameter('pref', data) - } - } + }, + }, }, methods: { @@ -352,7 +352,7 @@ export default { deleteProp() { this.localContact.vCard.removeProperty(this.property) this.updateContact() - } - } + }, + }, } diff --git a/src/components/ContactsList.vue b/src/components/ContactsList.vue index a4dd589a..a8a20312 100644 --- a/src/components/ContactsList.vue +++ b/src/components/ContactsList.vue @@ -52,31 +52,31 @@ export default { components: { ContactsListItem, - RecycleScroller + RecycleScroller, }, props: { list: { type: Array, - required: true + required: true, }, contacts: { type: Object, - required: true + required: true, }, loading: { type: Boolean, - default: true + default: true, }, searchQuery: { type: String, - default: '' - } + default: '', + }, }, data() { return { - itemHeight: 68 + itemHeight: 68, } }, @@ -89,7 +89,7 @@ export default { }, filteredList() { return this.list.filter(contact => this.matchSearch(this.contacts[contact.key])) - } + }, }, watch: { @@ -107,7 +107,7 @@ export default { this.scrollToContact(this.selectedContact) }) } - } + }, }, methods: { @@ -159,7 +159,7 @@ export default { return contact.searchData.toString().toLowerCase().search(this.searchQuery.trim().toLowerCase()) !== -1 } return true - } - } + }, + }, } diff --git a/src/components/ContactsList/ContactsListItem.vue b/src/components/ContactsList/ContactsListItem.vue index af6846e6..40a0ef87 100644 --- a/src/components/ContactsList/ContactsListItem.vue +++ b/src/components/ContactsList/ContactsListItem.vue @@ -64,23 +64,23 @@ export default { filters: { firstLetter(value) { return value.charAt(0) - } + }, }, props: { index: { type: Number, - required: true + required: true, }, contact: { type: Object, - required: true - } + required: true, + }, }, data() { return { deleteInterval: null, deleteTimeout: null, - countdown: 7 + countdown: 7, } }, computed: { @@ -106,7 +106,7 @@ export default { */ colorAvatar() { try { - let color = this.contact.uid.toRgb() + const color = this.contact.uid.toRgb() return `rgb(${color.r}, ${color.g}, ${color.b})` } catch (e) { return 'grey' @@ -117,7 +117,7 @@ export default { return `url(${this.contact.photoUrl})` } return `url(${this.contact.url}?photo)` - } + }, }, methods: { /** @@ -159,7 +159,7 @@ export default { selectContact() { // change url with router this.$router.push({ name: 'contact', params: { selectedGroup: this.selectedGroup, selectedContact: this.contact.key } }) - } - } + }, + }, } diff --git a/src/components/ImportScreen.vue b/src/components/ImportScreen.vue index 6da8a09a..e6e665bc 100644 --- a/src/components/ImportScreen.vue +++ b/src/components/ImportScreen.vue @@ -76,7 +76,7 @@ export default { return this.total <= 0 ? 0 : Math.floor(this.progress / this.total * 100) - } - } + }, + }, } diff --git a/src/components/Properties/PropertyActions.vue b/src/components/Properties/PropertyActions.vue index 19ce5f02..2232e2ca 100644 --- a/src/components/Properties/PropertyActions.vue +++ b/src/components/Properties/PropertyActions.vue @@ -39,24 +39,24 @@ export default { name: 'PropertyActions', components: { - ActionButton + ActionButton, }, props: { actions: { type: Array, - default: () => [] + default: () => [], }, propertyComponent: { type: Object, - required: true - } + required: true, + }, }, methods: { deleteProperty() { this.$emit('delete') - } - } + }, + }, } diff --git a/src/components/Properties/PropertyDateTime.vue b/src/components/Properties/PropertyDateTime.vue index a9b2cce2..31c6bab5 100644 --- a/src/components/Properties/PropertyDateTime.vue +++ b/src/components/Properties/PropertyDateTime.vue @@ -87,7 +87,7 @@ export default { components: { DatetimePicker, PropertyTitle, - PropertyActions + PropertyActions, }, mixins: [PropertyMixin], @@ -96,8 +96,8 @@ export default { value: { type: [VCardTime, String], default: '', - required: true - } + required: true, + }, }, data() { @@ -111,26 +111,26 @@ export default { // locale and lang data locale: 'en', - firstDay: window.firstDay === 0 ? 7 : window.firstDay, // provided by nextcloud + firstDay: window.firstDay === 0 ? 7 : window.firstDay, // provided by nextcloud lang: { - days: window.dayNamesShort, // provided by nextcloud - months: window.monthNamesShort, // provided by nextcloud + days: window.dayNamesShort, // provided by nextcloud + months: window.monthNamesShort, // provided by nextcloud placeholder: { - date: t('contacts', 'Select Date') - } + date: t('contacts', 'Select Date'), + }, }, dateFormat: { stringify: (date) => { return date ? this.formatDateTime() : null - } - } + }, + }, } }, computed: { gridLength() { - let hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 - let isLast = this.isLastProperty ? 1 : 0 + const hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 + const isLast = this.isLastProperty ? 1 : 0 // length is always one & add one space at the end return hasTitle + 1 + isLast }, @@ -142,7 +142,7 @@ export default { return new VCardTime.fromDateAndOrTimeString(this.localValue) } return this.localValue - } + }, }, async mounted() { @@ -180,7 +180,7 @@ export default { const objMap = ['year', 'month', 'day', 'hour', 'minute', 'second'] const rawArray = moment(date).toArray() - let dateObject = rawArray.reduce((acc, cur, index) => { + const dateObject = rawArray.reduce((acc, cur, index) => { acc[objMap[index]] = cur return acc }, {}) @@ -250,7 +250,7 @@ export default { // this is the only possibility for us to ensure // no data is lost. e.g. if no second are set // the second will be null and not 0 - let datetimeData = this.vcardTimeLocalValue.toJSON() + const datetimeData = this.vcardTimeLocalValue.toJSON() let datetime = '' const ignoreYear = this.property.getParameter('x-apple-omit-year') @@ -286,10 +286,10 @@ export default { .locale(this.locale) .format( this.inputType === 'datetime' - ? 'llll' // date & time display + ? 'llll' // date & time display : this.inputType === 'date' - ? 'll' // only date - : 'LTS' // only time + ? 'll' // only date + : 'LTS' // only time ) } @@ -297,8 +297,8 @@ export default { // replace year and remove double spaces ? datetime.replace(moment(this.vcardTimeLocalValue).year(), '').replace(/\s\s+/g, ' ') : datetime - } - } + }, + }, } diff --git a/src/components/Properties/PropertyGroups.vue b/src/components/Properties/PropertyGroups.vue index 41964ef5..b2ce1547 100644 --- a/src/components/Properties/PropertyGroups.vue +++ b/src/components/Properties/PropertyGroups.vue @@ -67,28 +67,28 @@ export default { propModel: { type: Object, default: () => {}, - required: true + required: true, }, value: { type: Array, default: () => [], - required: true + required: true, }, contact: { type: Contact, default: null, - required: true + required: true, }, // Is it read-only? isReadOnly: { type: Boolean, - default: false - } + default: false, + }, }, data() { return { - localValue: this.value + localValue: this.value, } }, @@ -105,7 +105,7 @@ export default { */ formatGroupsTitle() { return this.localValue.slice(3).join(', ') - } + }, }, watch: { @@ -119,7 +119,7 @@ export default { }, selectType: function() { this.localType = this.selectType - } + }, }, methods: { @@ -140,7 +140,7 @@ export default { async addContactToGroup(groupName) { await this.$store.dispatch('addContactToGroup', { contact: this.contact, - groupName + groupName, }) this.updateValue() }, @@ -153,7 +153,7 @@ export default { removeContactToGroup(groupName) { this.$store.dispatch('removeContactToGroup', { contact: this.contact, - groupName + groupName, }) }, @@ -165,15 +165,15 @@ export default { */ validateGroup(groupName) { // Only allow characters without vcard special chars - let groupRegex = /^[^;,:]+$/gmi + const groupRegex = /^[^;,:]+$/gmi if (groupName.match(groupRegex)) { this.addContactToGroup(groupName) this.localValue.push(groupName) return true } return false - } - } + }, + }, } diff --git a/src/components/Properties/PropertyMultipleText.vue b/src/components/Properties/PropertyMultipleText.vue index 6579fb12..efa09c5c 100644 --- a/src/components/Properties/PropertyMultipleText.vue +++ b/src/components/Properties/PropertyMultipleText.vue @@ -109,7 +109,7 @@ export default { components: { PropertyTitle, - PropertyActions + PropertyActions, }, mixins: [PropertyMixin], @@ -118,23 +118,23 @@ export default { value: { type: [Array, Object], default: () => [], - required: true - } + required: true, + }, }, computed: { gridLength() { - let hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 - let isLast = this.isLastProperty - let hasValueNames = this.propModel.options || this.selectType || !this.property.isStructuredValue ? 1 : 0 - let length = this.propModel.displayOrder ? this.propModel.displayOrder.length : this.value.length + const hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 + const isLast = this.isLastProperty + const hasValueNames = this.propModel.options || this.selectType || !this.property.isStructuredValue ? 1 : 0 + const length = this.propModel.displayOrder ? this.propModel.displayOrder.length : this.value.length return hasValueNames + hasTitle + length + isLast }, filteredValue() { return this.localValue.filter((value, index) => index > 0) - } - } + }, + }, } diff --git a/src/components/Properties/PropertyRev.vue b/src/components/Properties/PropertyRev.vue index 03bbff8b..321ef69c 100644 --- a/src/components/Properties/PropertyRev.vue +++ b/src/components/Properties/PropertyRev.vue @@ -36,14 +36,14 @@ export default { value: { type: VCardTime, required: true, - default: null - } + default: null, + }, }, computed: { relativeDate() { return OC.Util.relativeModifiedDate(this.value.toUnixTime() * 1000) - } - } + }, + }, } diff --git a/src/components/Properties/PropertySelect.vue b/src/components/Properties/PropertySelect.vue index ec8dc517..a2c5989d 100644 --- a/src/components/Properties/PropertySelect.vue +++ b/src/components/Properties/PropertySelect.vue @@ -64,7 +64,7 @@ export default { components: { PropertyTitle, - PropertyActions + PropertyActions, }, mixins: [PropertyMixin], @@ -73,14 +73,14 @@ export default { value: { type: [Object, String, Array], default: '', - required: true - } + required: true, + }, }, computed: { gridLength() { - let hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 - let isLast = this.isLastProperty ? 1 : 0 + const hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 + const isLast = this.isLastProperty ? 1 : 0 // length is one & add one space at the end return hasTitle + 1 + isLast }, @@ -105,12 +105,12 @@ export default { if (Array.isArray(this.localValue)) { return selected || { id: this.localValue.join(';'), - name: this.localValue.join(';') + name: this.localValue.join(';'), } } return selected || { id: this.localValue, - name: this.localValue + name: this.localValue, } }, set(value) { @@ -120,9 +120,9 @@ export default { } else { this.localValue = value.id } - } - } - } + }, + }, + }, } diff --git a/src/components/Properties/PropertyText.vue b/src/components/Properties/PropertyText.vue index 2d300b6f..089c47da 100644 --- a/src/components/Properties/PropertyText.vue +++ b/src/components/Properties/PropertyText.vue @@ -97,7 +97,7 @@ export default { components: { PropertyTitle, - PropertyActions + PropertyActions, }, mixins: [PropertyMixin], @@ -106,28 +106,28 @@ export default { propName: { type: String, default: 'text', - required: true + required: true, }, value: { type: String, default: '', - required: true - } + required: true, + }, }, data() { return { // the textarea additionnal height compared to the // default input text. Min is 2 grid height - noteHeight: 1 + noteHeight: 1, } }, computed: { gridLength() { - let hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 - let isLast = this.isLastProperty ? 1 : 0 - let noteHeight = this.propName === 'note' + const hasTitle = this.isFirstProperty && this.propModel.icon ? 1 : 0 + const isLast = this.isLastProperty ? 1 : 0 + const noteHeight = this.propName === 'note' ? this.noteHeight : 0 // length is one & add one space at the end @@ -167,7 +167,7 @@ export default { haveExtHandler() { return this.externalHandler.trim() !== '' && this.localValue && this.localValue.length > 0 - } + }, }, mounted() { @@ -198,7 +198,7 @@ export default { updateValueNoDebounce(e) { this.resizeGrid(e) this.updateValue(e) - } - } + }, + }, } diff --git a/src/components/Properties/PropertyTitle.vue b/src/components/Properties/PropertyTitle.vue index 56d64b8f..4bda3363 100644 --- a/src/components/Properties/PropertyTitle.vue +++ b/src/components/Properties/PropertyTitle.vue @@ -39,18 +39,18 @@ export default { icon: { type: String, default: '', - required: true + required: true, }, readableName: { type: String, default: '', - required: true + required: true, }, info: { type: String, default: '', - required: false - } - } + required: false, + }, + }, } diff --git a/src/components/Settings/SettingsAddressbook.vue b/src/components/Settings/SettingsAddressbook.vue index b136aed8..61fd301c 100644 --- a/src/components/Settings/SettingsAddressbook.vue +++ b/src/components/Settings/SettingsAddressbook.vue @@ -104,7 +104,7 @@ export default { ActionLink, ActionButton, ActionInput, - ActionCheckbox + ActionCheckbox, }, props: { @@ -112,8 +112,8 @@ export default { type: Object, default() { return {} - } - } + }, + }, }, data() { return { @@ -125,7 +125,7 @@ export default { menuOpen: false, renameLoading: false, shareOpen: false, - toggleEnabledLoading: false + toggleEnabledLoading: false, } }, computed: { @@ -148,7 +148,7 @@ export default { 'Shared with {num} entity', 'Shared with {num} entities', this.addressbook.shares.length, { - num: this.addressbook.shares.length + num: this.addressbook.shares.length, }) : '' // disable the tooltip }, @@ -159,14 +159,14 @@ export default { : t('contacts', 'Can not copy') } return t('contacts', 'Copy link') - } + }, }, watch: { menuOpen: function() { if (this.menuOpen === false) { this.editingName = false } - } + }, }, mounted() { // required if popup needs to stay opened after menu click @@ -226,9 +226,9 @@ export default { this.editingName = true }, async updateAddressbookName(e) { - let addressbook = this.addressbook + const addressbook = this.addressbook // 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 this.renameLoading = true try { @@ -268,7 +268,7 @@ export default { this.copySuccess = false }, 2000) } - } - } + }, + }, } diff --git a/src/components/Settings/SettingsAddressbookShare.vue b/src/components/Settings/SettingsAddressbookShare.vue index ef5cd9aa..632aabb2 100644 --- a/src/components/Settings/SettingsAddressbookShare.vue +++ b/src/components/Settings/SettingsAddressbookShare.vue @@ -56,21 +56,21 @@ import debounce from 'debounce' export default { name: 'SettingsAddressbookShare', components: { - addressBookSharee + addressBookSharee, }, props: { addressbook: { type: Object, default() { return {} - } - } + }, + }, }, data() { return { isLoading: false, inputGiven: false, - usersOrGroups: [] + usersOrGroups: [], } }, computed: { @@ -79,7 +79,7 @@ export default { }, noResult() { return t('contacts', 'No users or groups') - } + }, }, mounted() { // 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 ? */ shareAddressbook({ user, displayName, uri, isGroup }) { - let addressbook = this.addressbook + const addressbook = this.addressbook uri = decodeURI(uri) user = decodeURI(user) this.$store.dispatch('shareAddressbook', { addressbook, user, displayName, uri, isGroup }) @@ -113,14 +113,14 @@ export default { if (query.length > 0) { const results = await client.principalPropertySearchByDisplayname(query) 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' list.push({ user: result[isGroup ? 'groupId' : 'userId'], displayName: result.displayname, icon: isGroup ? 'icon-group' : 'icon-user', uri: result.principalScheme, - isGroup + isGroup, }) } return list @@ -131,7 +131,7 @@ export default { this.inputGiven = false this.isLoading = false } - }, 500) - } + }, 500), + }, } diff --git a/src/components/Settings/SettingsAddressbookSharee.vue b/src/components/Settings/SettingsAddressbookSharee.vue index 350aaa0b..ddb43a37 100644 --- a/src/components/Settings/SettingsAddressbookSharee.vue +++ b/src/components/Settings/SettingsAddressbookSharee.vue @@ -60,17 +60,17 @@ export default { props: { addressbook: { type: Object, - required: true + required: true, }, sharee: { type: Object, - required: true - } + required: true, + }, }, data() { return { - loading: false + loading: false, } }, @@ -81,7 +81,7 @@ export default { // generated id for this sharee uid() { return this.sharee.id + this.addressbook.id + Math.floor(Math.random() * 1000) - } + }, }, methods: { @@ -94,7 +94,7 @@ export default { try { await this.$store.dispatch('removeSharee', { addressbook: this.addressbook, - uri: this.sharee.uri + uri: this.sharee.uri, }) } catch (error) { console.error(error) @@ -113,7 +113,7 @@ export default { await this.$store.dispatch('toggleShareeWritable', { addressbook: this.addressbook, uri: this.sharee.uri, - writeable: !this.sharee.writeable + writeable: !this.sharee.writeable, }) } catch (error) { console.error(error) @@ -121,7 +121,7 @@ export default { } finally { this.loading = false } - } - } + }, + }, } diff --git a/src/components/Settings/SettingsImportContacts.vue b/src/components/Settings/SettingsImportContacts.vue index 9f2c13d0..d7583a3a 100644 --- a/src/components/Settings/SettingsImportContacts.vue +++ b/src/components/Settings/SettingsImportContacts.vue @@ -54,7 +54,7 @@ export default { data() { return { - importDestination: false + importDestination: false, } }, @@ -75,7 +75,7 @@ export default { .map(addressbook => { return { id: addressbook.id, - displayName: addressbook.displayName + displayName: addressbook.displayName, } }) }, @@ -89,7 +89,7 @@ export default { }, set(value) { this.importDestination = value - } + }, }, // disable multiselect when there is only one address book @@ -107,23 +107,23 @@ export default { // are we currently importing ? isImporting() { return this.importState.stage !== 'default' - } + }, }, methods: { processFile(event) { - let file = event.target.files[0] - let reader = new FileReader() - let selectedAddressbook = this.selectedAddressbook + const file = event.target.files[0] + const reader = new FileReader() + const selectedAddressbook = this.selectedAddressbook this.$store.dispatch('changeStage', 'parsing') this.$store.dispatch('setAddressbook', selectedAddressbook.displayName) - let self = this + const self = this reader.onload = function(e) { self.$store.dispatch('importContactsIntoAddressbook', { vcf: reader.result, addressbook: selectedAddressbook }) // reset input event.target.value = '' } reader.readAsText(file) - } - } + }, + }, } diff --git a/src/components/Settings/SettingsNewAddressbook.vue b/src/components/Settings/SettingsNewAddressbook.vue index b8e338b9..3f2abbb5 100644 --- a/src/components/Settings/SettingsNewAddressbook.vue +++ b/src/components/Settings/SettingsNewAddressbook.vue @@ -74,7 +74,7 @@ export default { OC.Notification.showTemporary(t('contacts', 'An error occurred, unable to create the addressbook.')) this.loading = false }) - } - } + }, + }, } diff --git a/src/components/Settings/SettingsSortContacts.vue b/src/components/Settings/SettingsSortContacts.vue index 0ae3de2b..7bf0644f 100644 --- a/src/components/Settings/SettingsSortContacts.vue +++ b/src/components/Settings/SettingsSortContacts.vue @@ -46,20 +46,20 @@ export default { return [ { label: t('contacts', 'First name'), - key: 'firstName' + key: 'firstName', }, { label: t('contacts', 'Last name'), - key: 'lastName' + key: 'lastName', }, { label: t('contacts', 'Display name'), - key: 'displayName' + key: 'displayName', }, { label: t('contacts', 'Last modified'), - key: 'rev' - } + key: 'rev', + }, ] }, /* Current order Key */ @@ -68,7 +68,7 @@ export default { }, orderKeyOption() { return this.options.filter(option => option.key === this.orderKey)[0] - } + }, }, methods: { sortContacts(orderKey) { @@ -79,7 +79,7 @@ export default { }, formatSortByLabel(option) { return t('contacts', 'Sort by {sorting}', { sorting: option.label }) - } - } + }, + }, } diff --git a/src/components/SettingsSection.vue b/src/components/SettingsSection.vue index f6c47365..7053356b 100644 --- a/src/components/SettingsSection.vue +++ b/src/components/SettingsSection.vue @@ -46,13 +46,13 @@ export default { SettingsAddressbook, SettingsNewAddressbook, SettingsImportContacts, - SettingsSortContacts + SettingsSortContacts, }, computed: { // store getters addressbooks() { return this.$store.getters.getAddressbooks - } + }, }, methods: { onClickImport(event) { @@ -60,7 +60,7 @@ export default { }, onLoad(event) { this.$emit('fileLoaded', false) - } - } + }, + }, } diff --git a/src/main.js b/src/main.js index 23b16dc9..8d25bff1 100644 --- a/src/main.js +++ b/src/main.js @@ -75,7 +75,7 @@ if (window.location.pathname.split('/')[1] === 'index.php' && oc_config.modRewriteWorking) { router.push({ name: 'group', - params: { selectedGroup: t('contacts', 'All contacts') } + params: { selectedGroup: t('contacts', 'All contacts') }, }) } @@ -84,5 +84,5 @@ export default new Vue({ name: 'ContactsApp', router, store, - render: h => h(App) + render: h => h(App), }) diff --git a/src/mixins/ActionsMixin.js b/src/mixins/ActionsMixin.js index 829efc24..304dd845 100644 --- a/src/mixins/ActionsMixin.js +++ b/src/mixins/ActionsMixin.js @@ -26,7 +26,7 @@ export default { component: { type: Object, default: () => {}, - required: true - } - } + required: true, + }, + }, } diff --git a/src/mixins/PropertyMixin.js b/src/mixins/PropertyMixin.js index af2d9885..031b0437 100644 --- a/src/mixins/PropertyMixin.js +++ b/src/mixins/PropertyMixin.js @@ -28,51 +28,51 @@ export default { // Default property type. e.g. "WORK,HOME" selectType: { type: [Object], - default: () => {} + default: () => {}, }, // Coming from the rfcProps Model propModel: { type: Object, default: () => {}, - required: true + required: true, }, propType: { type: String, - default: 'text' + default: 'text', }, // The current property passed as Object property: { type: Object, default: () => {}, - required: true + required: true, }, // Allows us to know if we need to // add the property header or not isFirstProperty: { type: Boolean, - default: true + default: true, }, // Allows us to know if we need to // add an extra space at the end isLastProperty: { type: Boolean, - default: true + default: true, }, // Is it read-only? isReadOnly: { type: Boolean, - default: false + default: false, }, // The available TYPE options from the propModel // not used on the PropertySelect options: { type: Array, - default: () => [] + default: () => [], }, localContact: { type: Contact, - default: null - } + default: null, + }, }, data() { @@ -82,7 +82,7 @@ export default { // many times as we can and debounce-fire the update // later localValue: this.value, - localType: this.selectType + localType: this.selectType, } }, @@ -92,7 +92,7 @@ export default { }, haveAction() { return this.actions && this.actions.length > 0 - } + }, }, watch: { @@ -106,7 +106,7 @@ export default { }, selectType: function() { this.localType = this.selectType - } + }, }, methods: { @@ -156,12 +156,12 @@ export default { getNcGroupCount() { const props = this.localContact.jCal[1] - .map(prop => prop[0].split('.')[0]) // itemxxx.adr => itemxxx - .filter(name => name.startsWith('nextcloud')) // filter nextcloudxxx.adr - .map(prop => parseInt(prop.split('nextcloud')[1])) // nextcloudxxx => xxx + .map(prop => prop[0].split('.')[0]) // itemxxx.adr => itemxxx + .filter(name => name.startsWith('nextcloud')) // filter nextcloudxxx.adr + .map(prop => parseInt(prop.split('nextcloud')[1])) // nextcloudxxx => xxx return props.length > 0 ? Math.max.apply(null, props) // get max iteration of nextcloud grouped props : 0 - } - } + }, + }, } diff --git a/src/models/contact.js b/src/models/contact.js index 15f0d7e2..199ffc37 100644 --- a/src/models/contact.js +++ b/src/models/contact.js @@ -293,7 +293,7 @@ export default class Contact { * @memberof Contact */ get groups() { - let groupsProp = this.vCard.getFirstProperty('categories') + const groupsProp = this.vCard.getFirstProperty('categories') if (groupsProp) { return groupsProp.getValues() .filter(group => group.trim() !== '') diff --git a/src/models/rfcProps.js b/src/models/rfcProps.js index 34df17c3..ca9b4e33 100644 --- a/src/models/rfcProps.js +++ b/src/models/rfcProps.js @@ -33,14 +33,14 @@ const localesState = loadState('contacts', 'locales') const locales = localesState ? localesState.map(({ code, name }) => ({ id: code.toLowerCase().replace('_', '-'), - name + name, })) : [] const properties = { nickname: { readableName: t('contacts', 'Nickname'), - icon: 'icon-user' + icon: 'icon-user', }, n: { readableName: t('contacts', 'Detailed name'), @@ -49,25 +49,25 @@ const properties = { t('contacts', 'First name'), t('contacts', 'Additional names'), t('contacts', 'Prefix'), - t('contacts', 'Suffix') + t('contacts', 'Suffix'), ], displayOrder: [3, 1, 2, 0, 4], defaultValue: { - value: ['', '', '', '', ''] + value: ['', '', '', '', ''], }, icon: 'icon-user', actions: [ - ActionCopyNtoFN - ] + ActionCopyNtoFN, + ], }, note: { readableName: t('contacts', 'Notes'), - icon: 'icon-rename' + icon: 'icon-rename', }, url: { multiple: true, readableName: t('contacts', 'Website'), - icon: 'icon-public' + icon: 'icon-public', }, geo: { multiple: true, @@ -75,8 +75,8 @@ const properties = { icon: 'icon-address', defaultjCal: { '3.0': [{}, 'FLOAT', '90.000;0.000'], - '4.0': [{}, 'URI', 'geo:90.000,0.000'] - } + '4.0': [{}, 'URI', 'geo:90.000,0.000'], + }, }, cloud: { multiple: true, @@ -85,13 +85,13 @@ const properties = { force: 'text', defaultValue: { value: [''], - type: [defaultProfileState] + type: [defaultProfileState], }, options: [ { id: 'HOME', name: t('contacts', 'Home') }, { id: 'WORK', name: t('contacts', 'Work') }, - { id: 'OTHER', name: t('contacts', 'Other') } - ] + { id: 'OTHER', name: t('contacts', 'Other') }, + ], }, adr: { multiple: true, @@ -103,31 +103,31 @@ const properties = { t('contacts', 'City'), t('contacts', 'State or province'), t('contacts', 'Postal code'), - t('contacts', 'Country') + t('contacts', 'Country'), ], displayOrder: [0, 2, 1, 5, 3, 4, 6], icon: 'icon-address', default: true, defaultValue: { value: ['', '', '', '', '', '', ''], - type: [defaultProfileState] + type: [defaultProfileState], }, options: [ { id: 'HOME', name: t('contacts', 'Home') }, { id: 'WORK', name: t('contacts', 'Work') }, - { id: 'OTHER', name: t('contacts', 'Other') } - ] + { id: 'OTHER', name: t('contacts', 'Other') }, + ], }, bday: { readableName: t('contacts', 'Birthday'), icon: 'icon-calendar-dark', force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant defaultValue: { - value: new VCardTime(null, null, 'date').fromJSDate(new Date()) + value: new VCardTime(null, null, 'date').fromJSDate(new Date()), }, actions: [ - ActionToggleYear - ] + ActionToggleYear, + ], }, anniversary: { readableName: t('contacts', 'Anniversary'), @@ -135,16 +135,16 @@ const properties = { icon: 'icon-calendar-dark', force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant defaultValue: { - value: new VCardTime(null, null, 'date').fromJSDate(new Date()) - } + value: new VCardTime(null, null, 'date').fromJSDate(new Date()), + }, }, deathdate: { readableName: t('contacts', 'Date of death'), icon: 'icon-calendar-dark', force: 'date', // most ppl prefer date for birthdays, time is usually irrelevant defaultValue: { - value: new VCardTime(null, null, 'date').fromJSDate(new Date()) - } + value: new VCardTime(null, null, 'date').fromJSDate(new Date()), + }, }, email: { multiple: true, @@ -153,13 +153,13 @@ const properties = { default: true, defaultValue: { value: '', - type: [defaultProfileState] + type: [defaultProfileState], }, options: [ { id: 'HOME', name: t('contacts', 'Home') }, { id: 'WORK', name: t('contacts', 'Work') }, - { id: 'OTHER', name: t('contacts', 'Other') } - ] + { id: 'OTHER', name: t('contacts', 'Other') }, + ], }, impp: { multiple: true, @@ -167,15 +167,15 @@ const properties = { icon: 'icon-comment', defaultValue: { value: [''], - type: ['SKYPE'] + type: ['SKYPE'], }, options: [ { id: 'IRC', name: 'IRC' }, { id: 'KIK', name: 'KiK' }, { id: 'SKYPE', name: 'Skype' }, { id: 'TELEGRAM', name: 'Telegram' }, - { id: 'XMPP', name: 'XMPP' } - ] + { id: 'XMPP', name: 'XMPP' }, + ], }, tel: { multiple: true, @@ -184,7 +184,7 @@ const properties = { default: true, defaultValue: { value: '', - type: [defaultProfileState, 'VOICE'] + type: [defaultProfileState, 'VOICE'], }, options: [ { id: 'HOME,VOICE', name: t('contacts', 'Home') }, @@ -201,8 +201,8 @@ const properties = { { id: 'PAGER', name: t('contacts', 'Pager') }, { id: 'VOICE', name: t('contacts', 'Voice') }, { id: 'CAR', name: t('contacts', 'Car') }, - { id: 'WORK,PAGER', name: t('contacts', 'Work pager') } - ] + { id: 'WORK,PAGER', name: t('contacts', 'Work pager') }, + ], }, 'x-socialprofile': { multiple: true, @@ -211,7 +211,7 @@ const properties = { readableName: t('contacts', 'Social network'), defaultValue: { value: '', - type: ['facebook'] + type: ['facebook'], }, info: t( 'contacts', @@ -231,8 +231,8 @@ const properties = { { id: 'YOUTUBE', name: 'YouTube' }, { id: 'MASTODON', name: 'Mastodon' }, { id: 'DIASPORA', name: 'Diaspora' }, - { id: 'OTHER', name: 'other Social Media' } - ] + { id: 'OTHER', name: 'other Social Media' }, + ], }, relationship: { readableName: t('contacts', 'Relationship'), @@ -254,8 +254,8 @@ const properties = { { id: 'FRIEND', name: t('contacts', 'Friend') }, { id: 'COLLEAGUE', name: t('contacts', 'Colleague') }, { id: 'MANAGER', name: t('contacts', 'Manager') }, - { id: 'ASSISTANT', name: t('contacts', 'Assistant') } - ] + { id: 'ASSISTANT', name: t('contacts', 'Assistant') }, + ], }, related: { multiple: true, @@ -267,7 +267,7 @@ const properties = { ), defaultValue: { value: [''], - type: ['CONTACT'] + type: ['CONTACT'], }, options: [ { id: 'CONTACT', name: t('contacts', 'Contact') }, @@ -285,14 +285,14 @@ const properties = { { id: 'PARENT', name: t('contacts', 'Parent') }, { id: 'BROTHER', name: t('contacts', 'Brother') }, { id: 'SISTER', name: t('contacts', 'Sister') }, - { id: 'RELATIVE', name: t('contacts', 'Relative') } - ] + { id: 'RELATIVE', name: t('contacts', 'Relative') }, + ], }, gender: { readableName: t('contacts', 'Gender'), defaultValue: { // default to Female 🙋 - value: 'F' + value: 'F', }, force: 'select', options: [ @@ -300,8 +300,8 @@ const properties = { { id: 'M', name: t('contacts', 'Male') }, { id: 'O', name: t('contacts', 'Other') }, { id: 'N', name: t('contacts', 'None') }, - { id: 'U', name: t('contacts', 'Unknown') } - ] + { id: 'U', name: t('contacts', 'Unknown') }, + ], }, tz: { readableName: t('contacts', 'Timezone'), @@ -309,17 +309,17 @@ const properties = { icon: 'icon-timezone', options: zones.map(zone => ({ id: zone, - name: zone - })) + name: zone, + })), }, lang: { readableName: t('contacts', 'Spoken languages'), icon: 'icon-language', defaultValue: { - value: 'en' + value: 'en', }, - multiple: true - } + multiple: true, + }, } if (locales.length > 0) { @@ -356,7 +356,7 @@ const fieldOrder = [ 'note', 'categories', 'role', - 'gender' + 'gender', ] export default { properties, fieldOrder } diff --git a/src/models/zones.js b/src/models/zones.js index 4ce1c632..9412078d 100644 --- a/src/models/zones.js +++ b/src/models/zones.js @@ -446,5 +446,5 @@ export default [ 'Pacific/Tarawa', 'Pacific/Tongatapu', 'Pacific/Wake', - 'Pacific/Wallis' + 'Pacific/Wallis', ] diff --git a/src/router/index.js b/src/router/index.js index 6d678e4e..1f8fd221 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -42,20 +42,20 @@ export default new Router({ // always load default group redirect: { name: 'group', - params: { selectedGroup: t('contacts', 'All contacts') } + params: { selectedGroup: t('contacts', 'All contacts') }, }, children: [ { path: ':selectedGroup', name: 'group', - component: Contacts + component: Contacts, }, { path: ':selectedGroup/:selectedContact', name: 'contact', - component: Contacts - } - ] - } - ] + component: Contacts, + }, + ], + }, + ], }) diff --git a/src/services/cdav.js b/src/services/cdav.js index 1f6676c0..da5c6549 100644 --- a/src/services/cdav.js +++ b/src/services/cdav.js @@ -25,17 +25,17 @@ import { generateRemoteUrl } from 'nextcloud-router' import { getRequestToken } from 'nextcloud-auth' function xhrProvider() { - var headers = { + const headers = { 'X-Requested-With': 'XMLHttpRequest', - 'requesttoken': getRequestToken() + 'requesttoken': getRequestToken(), } - var xhr = new XMLHttpRequest() - var oldOpen = xhr.open + const xhr = new XMLHttpRequest() + const oldOpen = xhr.open // override open() method to add headers xhr.open = function() { - var result = oldOpen.apply(this, arguments) - for (let name in headers) { + const result = oldOpen.apply(this, arguments) + for (const name in headers) { xhr.setRequestHeader(name, headers[name]) } return result @@ -45,5 +45,5 @@ function xhrProvider() { } export default new DavClient({ - rootUrl: generateRemoteUrl('dav') + rootUrl: generateRemoteUrl('dav'), }, xhrProvider) diff --git a/src/services/checks/badGenderType.js b/src/services/checks/badGenderType.js index b6ebabac..dc61f8ab 100644 --- a/src/services/checks/badGenderType.js +++ b/src/services/checks/badGenderType.js @@ -40,5 +40,5 @@ export default { return true } return false - } + }, } diff --git a/src/services/checks/duplicateTypes.js b/src/services/checks/duplicateTypes.js index 64a5c762..ef630f8a 100644 --- a/src/services/checks/duplicateTypes.js +++ b/src/services/checks/duplicateTypes.js @@ -60,5 +60,5 @@ export default { console.error(error) } return results - } + }, } diff --git a/src/services/checks/index.js b/src/services/checks/index.js index 170bd846..544c8571 100644 --- a/src/services/checks/index.js +++ b/src/services/checks/index.js @@ -29,5 +29,5 @@ export default [ badGenderType, duplicateTypes, invalidREV, - missingFN + missingFN, ] diff --git a/src/services/checks/invalidREV.js b/src/services/checks/invalidREV.js index b9b4a63c..94af2870 100644 --- a/src/services/checks/invalidREV.js +++ b/src/services/checks/invalidREV.js @@ -52,5 +52,5 @@ export default { } catch (error) { return false } - } + }, } diff --git a/src/services/checks/missingFN.js b/src/services/checks/missingFN.js index fc59946b..67ab9249 100644 --- a/src/services/checks/missingFN.js +++ b/src/services/checks/missingFN.js @@ -27,12 +27,12 @@ export default { name: 'missing FN', run: contact => { - return !contact.vCard.hasProperty('fn') // No FN - || contact.vCard.getFirstPropertyValue('fn') === '' // Empty FN + return !contact.vCard.hasProperty('fn') // No FN + || contact.vCard.getFirstPropertyValue('fn') === '' // Empty FN || ( // we don't want to fix newly created contacts - contact.dav // Existing contact + contact.dav // Existing contact && contact.vCard.getFirstPropertyValue('fn') - .toLowerCase() === t('contacts', 'New contact').toLowerCase() // AND Unchanged FN + .toLowerCase() === t('contacts', 'New contact').toLowerCase() // AND Unchanged FN ) }, fix: contact => { @@ -60,5 +60,5 @@ export default { return false } return false - } + }, } diff --git a/src/services/parseVcf.js b/src/services/parseVcf.js index 184c8e76..2b5bef53 100644 --- a/src/services/parseVcf.js +++ b/src/services/parseVcf.js @@ -24,8 +24,8 @@ import Contact from '../models/contact' import Store from '../store/index' export default function parseVcf(data = '', addressbook) { - let regexp = /BEGIN:VCARD[\s\S]*?END:VCARD/mgi - let vCards = data.match(regexp) + const regexp = /BEGIN:VCARD[\s\S]*?END:VCARD/mgi + const vCards = data.match(regexp) if (!vCards) { 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) => { try { // console.log(vCards.indexOf(vCard)) - let contact = new Contact(vCard, addressbook) + const contact = new Contact(vCard, addressbook) contacts.push(contact) } catch (e) { // Parse error! Do not stop here... diff --git a/src/store/addressbooks.js b/src/store/addressbooks.js index d40f6abf..e237c1b6 100644 --- a/src/store/addressbooks.js +++ b/src/store/addressbooks.js @@ -39,11 +39,11 @@ const addressbookModel = { contacts: {}, url: '', readOnly: false, - dav: false + dav: false, } const state = { - addressbooks: [] + addressbooks: [], } /** @@ -62,7 +62,7 @@ export function mapDavCollectionToAddressbook(addressbook) { readOnly: addressbook.readOnly === true, url: addressbook.url, 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, writeable: sharee.access[0].endsWith('read-write'), 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 */ 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) }, @@ -175,7 +175,7 @@ const mutations = { * @param {Contact} contact the contact to delete */ 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) }, @@ -197,7 +197,7 @@ const mutations = { id: user, writeable: false, isGroup, - uri + uri, } addressbook.shares.push(newSharee) }, @@ -212,7 +212,7 @@ const mutations = { */ removeSharee(state, { addressbook, uri }) { 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) }, @@ -226,14 +226,14 @@ const mutations = { */ updateShareeWritable(state, { addressbook, uri }) { 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 - } + }, } const getters = { - getAddressbooks: state => state.addressbooks + getAddressbooks: state => state.addressbooks, } const actions = { @@ -245,7 +245,7 @@ const actions = { * @returns {Object[]} the addressbooks */ async getAddressbooks(context) { - let addressbooks = await client.addressBookHomes[0] + const addressbooks = await client.addressBookHomes[0] .findAllAddressBooks() .then(addressbooks => { return addressbooks.map(addressbook => { @@ -347,10 +347,10 @@ const actions = { // We don't want to lose the url information // so we need to parse one by one let failed = 0 - let contacts = response + const contacts = response .reduce((contacts, item) => { try { - let contact = new Contact(item.data, addressbook) + const contact = new Contact(item.data, addressbook) Vue.set(contact, 'dav', item) contacts.push(contact) } catch (error) { @@ -405,7 +405,7 @@ const actions = { // Get vcard string try { - let vData = ICAL.stringify(contact.vCard.jCal) + const vData = ICAL.stringify(contact.vCard.jCal) // push contact to server and use limit requests.push(limit(() => contact.addressbook.dav.createVCard(vData) .then((response) => { @@ -509,7 +509,7 @@ const actions = { await context.commit('updateContactAddressbook', { contact, addressbook }) await context.commit('addContactToAddressbook', contact) return contact - } + }, } export default { state, mutations, getters, actions } diff --git a/src/store/contacts.js b/src/store/contacts.js index ae9e4970..2b7bd1b3 100644 --- a/src/store/contacts.js +++ b/src/store/contacts.js @@ -26,14 +26,14 @@ import Contact from '../models/contact' import validate from '../services/validate' const sortData = (a, b) => { - var nameA = typeof a.value === 'string' - ? a.value.toUpperCase() // ignore upper and lowercase - : a.value.toUnixTime() // only other sorting we support is a vCardTime - var nameB = typeof b.value === 'string' + const nameA = typeof a.value === 'string' + ? a.value.toUpperCase() // ignore upper and lowercase + : a.value.toUnixTime() // only other sorting we support is a vCardTime + const nameB = typeof b.value === 'string' ? 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) : nameB - nameA // if equal, fallback to the key @@ -47,7 +47,7 @@ const state = { // https://codepen.io/skjnldsv/pen/ZmKvQo contacts: {}, sortedContacts: [], - orderKey: 'displayName' + orderKey: 'displayName', } const mutations = { @@ -79,7 +79,7 @@ const mutations = { deleteContact(state, 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) Vue.delete(state.contacts, contact.key) @@ -100,14 +100,14 @@ const mutations = { // Checking contact validity 🔍🙈 validate(contact) - let sortedContact = { + const sortedContact = { key: contact.key, - value: contact[state.orderKey] + value: contact[state.orderKey], } // Not using sort, splice has far better performances // 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) { state.sortedContacts.splice(i, 0, sortedContact) break @@ -141,10 +141,10 @@ const mutations = { // replace contact object data 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 ? - let hasChanged = sortedContact.value !== contact[state.orderKey] + const hasChanged = sortedContact.value !== contact[state.orderKey] if (hasChanged) { // then update the new data sortedContact.value = contact[state.orderKey] @@ -168,10 +168,10 @@ const mutations = { updateContactAddressbook(state, { contact, addressbook }) { if (state.contacts[contact.key] && contact instanceof Contact) { // replace contact object data by creating a new contact - let oldKey = contact.key + const oldKey = contact.key // hijack reference - var newContact = contact + const newContact = contact // delete old key, cut reference Vue.delete(state.contacts, oldKey) @@ -183,10 +183,10 @@ const mutations = { Vue.set(state.contacts, newContact.key, newContact) // 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] = { key: newContact.key, - value: newContact[state.orderKey] + value: newContact[state.orderKey], } } else { console.error('Error while replacing the addressbook of following contact', contact) @@ -267,14 +267,14 @@ const mutations = { } else { console.error('Error while handling the following contact', contact) } - } + }, } const getters = { getContacts: state => state.contacts, getSortedContacts: state => state.sortedContacts, getContact: (state) => (key) => state.contacts[key], - getOrderKey: state => state.orderKey + getOrderKey: state => state.orderKey, } const actions = { @@ -330,7 +330,7 @@ const actions = { rev.fromUnixTime(Date.now() / 1000) 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 (!contact.dav) { @@ -380,11 +380,11 @@ const actions = { } return contact.dav.fetchCompleteData() .then((response) => { - let newContact = new Contact(contact.dav.data, contact.addressbook) + const newContact = new Contact(contact.dav.data, contact.addressbook) context.commit('updateContact', newContact) }) .catch((error) => { throw error }) - } + }, } export default { state, mutations, getters, actions } diff --git a/src/store/groups.js b/src/store/groups.js index 8b00d593..8df01b19 100644 --- a/src/store/groups.js +++ b/src/store/groups.js @@ -21,7 +21,7 @@ */ const state = { - groups: [] + groups: [], } const mutations = { @@ -42,7 +42,7 @@ const mutations = { if (!group) { state.groups.push({ name: groupName, - contacts: [] + contacts: [], }) group = state.groups.find(search => search.name === groupName) } @@ -67,7 +67,7 @@ const mutations = { if (!group) { state.groups.push({ name: groupName, - contacts: [] + contacts: [], }) group = state.groups.find(search => search.name === groupName) } @@ -84,8 +84,8 @@ const mutations = { * @param {Contact} data.contact the contact */ removeContactToGroup(state, { groupName, contact }) { - let contacts = state.groups.find(search => search.name === groupName).contacts - let index = contacts.findIndex(search => search === contact.key) + const contacts = state.groups.find(search => search.name === groupName).contacts + const index = contacts.findIndex(search => search === contact.key) if (index > -1) { contacts.splice(index, 1) } @@ -104,11 +104,11 @@ const mutations = { group.contacts.splice(index, 1) } }) - } + }, } const getters = { - getGroups: state => state.groups + getGroups: state => state.groups, } const actions = { @@ -145,7 +145,7 @@ const actions = { */ removeContactToGroup(context, { groupName, contact }) { context.commit('removeContactToGroup', { groupName, contact }) - } + }, } export default { state, mutations, getters, actions } diff --git a/src/store/importState.js b/src/store/importState.js index f969725e..84c7ea41 100644 --- a/src/store/importState.js +++ b/src/store/importState.js @@ -26,8 +26,8 @@ const state = { accepted: 0, denied: 0, stage: 'default', - addressbook: '' - } + addressbook: '', + }, } const mutations = { @@ -88,11 +88,11 @@ const mutations = { state.importState.total = 0 state.importState.accepted = 0 state.importState.denied = 0 - } + }, } const getters = { - getImportState: state => state.importState + getImportState: state => state.importState, } const actions = { @@ -146,7 +146,7 @@ const actions = { if (stage === 'parsing') { context.commit('resetState') } - } + }, } export default { state, mutations, getters, actions } diff --git a/src/store/index.js b/src/store/index.js index fcd59385..fda3d8c9 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -36,10 +36,10 @@ export default new Store({ addressbooks, contacts, groups, - importState + importState, }, - mutations + mutations, /** * the contat ical update itself on property getters diff --git a/src/views/Contacts.vue b/src/views/Contacts.vue index 4b7e478a..7be70d2d 100644 --- a/src/views/Contacts.vue +++ b/src/views/Contacts.vue @@ -80,7 +80,7 @@ import { AppNavigationNew, AppNavigationSettings, Content, - Modal + Modal, } from 'nextcloud-vue' import isMobile from 'nextcloud-vue/dist/Mixins/isMobile' @@ -115,11 +115,11 @@ export default { Content, ImportScreen, Modal, - SettingsSection + SettingsSection, }, mixins: [ - isMobile + isMobile, ], // passed by the router @@ -127,18 +127,18 @@ export default { selectedGroup: { type: String, default: undefined, - required: true + required: true, }, selectedContact: { type: String, - default: undefined - } + default: undefined, + }, }, data() { return { loading: true, - searchQuery: '' + searchQuery: '', } }, @@ -190,7 +190,7 @@ export default { } else if (this.selectedGroup === GROUP_NO_GROUP_CONTACTS) { 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) { return this.sortedContacts.filter(contact => group.contacts.indexOf(contact.key) >= 0) } @@ -209,7 +209,7 @@ export default { key: group.name.replace(' ', '_'), router: { name: 'group', - params: { selectedGroup: group.name } + params: { selectedGroup: group.name }, }, text: group.name, utils: { @@ -218,10 +218,10 @@ export default { { icon: 'icon-download', text: 'Download', - action: () => this.downloadGroup(group) - } - ] - } + action: () => this.downloadGroup(group), + }, + ], + }, } }).sort(function(a, b) { return parseInt(b.utils.counter) - parseInt(a.utils.counter) @@ -241,12 +241,12 @@ export default { icon: 'icon-contacts-dark', router: { name: 'group', - params: { selectedGroup: GROUP_ALL_CONTACTS } + params: { selectedGroup: GROUP_ALL_CONTACTS }, }, text: GROUP_ALL_CONTACTS, utils: { - counter: this.sortedContacts.length - } + counter: this.sortedContacts.length, + }, }] }, @@ -261,14 +261,14 @@ export default { icon: 'icon-user', router: { name: 'group', - params: { selectedGroup: GROUP_NO_GROUP_CONTACTS } + params: { selectedGroup: GROUP_NO_GROUP_CONTACTS }, }, text: GROUP_NO_GROUP_CONTACTS, utils: { - counter: this.ungroupedContacts.length - } + counter: this.ungroupedContacts.length, + }, }] - } + }, }, watch: { @@ -283,7 +283,7 @@ export default { if (!this.isMobile) { this.selectFirstContactIfNone() } - } + }, }, 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) const properties = rfcProps.properties - for (let name in properties) { + for (const name in properties) { if (properties[name].default) { - let defaultData = properties[name].defaultValue + const defaultData = properties[name].defaultValue // add default field - let property = contact.vCard.addPropertyWithValue(name, defaultData.value) + const property = contact.vCard.addPropertyWithValue(name, defaultData.value) // add default type if (defaultData.type) { property.setParameter('type', defaultData.type) @@ -361,8 +361,8 @@ export default { name: 'contact', params: { selectedGroup: this.selectedGroup, - selectedContact: contact.key - } + selectedContact: contact.key, + }, }) } catch (error) { OC.Notification.showTemporary(t('contacts', 'Unable to create the contact.')) @@ -402,7 +402,7 @@ export default { * if none are selected already */ 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 && !inList) { OC.Notification.showTemporary(t('contacts', 'Contact not found')) @@ -412,8 +412,8 @@ export default { name: 'contact', params: { 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({ [id]: { addressbook: this.contacts[key].addressbook, - contacts: [] - } + contacts: [], + }, }, groupedContacts) groupedContacts[id].contacts.push(this.contacts[key].url) }) @@ -455,7 +455,7 @@ export default { groupedContacts[key].addressbook.dav.addressbookMultigetExport(groupedContacts[key].contacts))) .then(response => ({ groupName: group.name, - data: response.map(data => data.body).join('') + data: response.map(data => data.body).join(''), })) // download vcard this.downloadVcardPromise(vcardPromise) @@ -478,8 +478,8 @@ export default { name: 'contact', params: { selectedGroup: this.selectedGroup, - selectedContact: undefined - } + selectedContact: undefined, + }, }) }, @@ -491,7 +491,7 @@ export default { if (this.isImportDone) { this.$store.dispatch('changeStage', 'default') } - } - } + }, + }, } diff --git a/tests/setup.js b/tests/setup.js index 46dc39be..ef86d905 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -30,7 +30,7 @@ global.expect = require('chai').expect window.Date = Date global.OC = { - getLocale: () => 'en' + getLocale: () => 'en', } global.t = (app, text) => text diff --git a/tests/unit/specs/Contacts.spec.js b/tests/unit/specs/Contacts.spec.js index 99eb607a..f044d797 100644 --- a/tests/unit/specs/Contacts.spec.js +++ b/tests/unit/specs/Contacts.spec.js @@ -23,10 +23,3 @@ // eslint-disable-next-line node/no-unpublished-import // import { mount } from '@vue/test-utils' // import Contacts from '../../../src/views/Contacts.vue' - -// describe('Contacts.vue', () => { -// it('Test contacts view', () => { -// const wrapper = mount(Contacts) -// expect(wrapper.text()).toContain('Test') -// }) -// })