Contact details update and property components

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
John Molakvoæ (skjnldsv) 2018-08-10 17:46:46 +02:00
parent 2ba22b8110
commit 92ec6bcf43
No known key found for this signature in database
GPG Key ID: 60C25B8C072916CF
9 changed files with 408 additions and 36 deletions

63
js/0.contacts.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

28
package-lock.json generated
View File

@ -4363,14 +4363,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -4385,20 +4383,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -4515,8 +4510,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@ -4528,7 +4522,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -4543,7 +4536,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -4551,14 +4543,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@ -4577,7 +4567,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -4658,8 +4647,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@ -4671,7 +4659,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -4793,7 +4780,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",

View File

@ -21,22 +21,39 @@
-->
<template>
<div class="contact-details-property" />
<!-- If not in the rfcProps then we don't want to display it -->
<component v-if="propModel" :is="componentInstance" :select-type="selectType"
:prop-model="propModel" :value="value" />
</template>
<script>
import { Property } from 'ical.js'
import rfcProps from '../../models/rfcProps.js'
import PropertyText from '../properties/PropertyText'
import PropertyMultipleText from '../properties/PropertyMultipleText'
// import PropertySelect from '../properties/PropertyMultipleText'
export default {
name: 'Property',
props: {
property: {
type: Property,
default: true
}
},
computed: {
// dynamically load component based on property type
componentInstance() {
if (this.property.isMultiValue && this.propType === 'text') {
return PropertyMultipleText
} else if (this.propType && this.propType !== 'unknown') {
return PropertyText
}
return PropertyText
},
// rfc properties list
properties() {
return rfcProps.properties
@ -52,13 +69,46 @@ export default {
propType() {
return this.property.type
},
// template to use
propModel() {
return this.properties[name]
return this.properties[this.propName]
},
// select type handler
selectType: {
get() {
if (this.propModel && this.propModel.options && this.type) {
let selectedType = this.type
// vcard 3.0 save pref alongside TYPE
.filter(type => type !== 'pref')
// we only use uppercase strings
.map(str => str.toUpperCase())
// Compare array and check if the number of exact matches
// equals the array length to find the exact property
return this.propModel.options.find(option => selectedType.length === option.id.split(',').reduce((matches, type) => {
matches += selectedType.indexOf(type) > -1 ? 1 : 0
return matches
}, 0))
} else if (this.type) {
return {
id: this.type.join(','),
name: this.type.join(',')
}
}
return false
},
set(data) {
// ical.js take types as arrays
this.type = data.id.split(',')
}
},
// property value(s)
prop: {
value: {
get() {
if (this.property.isMultiValue) {
return this.property.getValues()
@ -72,15 +122,21 @@ export default {
return this.property.setValue(data)
}
},
// property meta type
type: {
get() {
return this.property.getParameter('type')
let type = this.property.getParameter('type')
// ensure we have an array
if (type) {
return Array.isArray(type) ? type : [type]
}
},
set(data) {
this.property.setParameter('type', data)
}
},
// property meta pref
pref: {
get() {

View File

@ -0,0 +1,75 @@
<!--
- @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
-
- @author John Molakvoæ <skjnldsv@protonmail.com>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<div v-if="propModel" class="contact-details-property">
<!-- type selector -->
<multiselect v-if="propModel.options" v-model="selectType"
:options="propModel.options" :searchable="false" :placeholder="t('contacts', 'Select type')"
class="multiselect-vue contact-details-label" track-by="id" label="name" />
<!-- if we do not support any type on our model but one is set anyway -->
<div v-else-if="selectType" class="contact-details-label">{{ selectType.name }}</div>
<!-- delete the prop -->
<button :title="t('contacts', 'Delete')" class="icon-delete" @click="deleteProperty" />
<div v-for="(data, index) in value" :key="index">
<div class="contact-details-label">{{ propModel.readableValues[index] }}</div>
<input v-model="value[index]" type="text">
</div>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
export default {
name: 'PropertyText',
components: {
Multiselect
},
props: {
selectType: {
type: Object,
default: () => {}
},
propModel: {
type: Object,
default: () => {}
},
value: {
type: [Array, String],
default: ''
}
},
methods: {
deleteProperty() {
alert('deleted')
}
}
}
</script>

View File

@ -0,0 +1,72 @@
<!--
- @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
-
- @author John Molakvoæ <skjnldsv@protonmail.com>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<div v-if="propModel" class="contact-details-property">
<!-- type selector -->
<multiselect v-if="propModel.options" v-model="selectType"
:options="propModel.options" :searchable="false" :placeholder="t('contacts', 'Select type')"
class="multiselect-vue contact-details-label" track-by="id" label="name" />
<!-- if we do not support any type on our model but one is set anyway -->
<div v-else-if="selectType" class="contact-details-label">{{ selectType.name }}</div>
<!-- delete the prop -->
<button :title="t('contacts', 'Delete')" class="icon-delete" @click="deleteProperty" />
<input v-model="value" type="text">
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
export default {
name: 'PropertyText',
components: {
Multiselect
},
props: {
selectType: {
type: Object,
default: () => {}
},
propModel: {
type: Object,
default: () => {}
},
value: {
type: [Array, String],
default: ''
}
},
methods: {
deleteProperty() {
alert('deleted')
}
}
}
</script>

View File

@ -150,7 +150,6 @@ const properties = {
{ id: 'PAGER', name: t('contacts', 'Pager') },
{ id: 'VOICE', name: t('contacts', 'Voice') },
{ id: 'CAR', name: t('contacts', 'Car') },
{ id: 'PAGER', name: t('contacts', 'Pager') },
{ id: 'WORK,PAGER', name: t('contacts', 'Work pager') }
]
},

View File

@ -1459,15 +1459,16 @@ URL:http://google.com
FN:Aðalbjörn Snorrason
NICKNAME:Shaltarea
BDAY;VALUE=text:7/31/1950
GENDER:male
GENDER;TYPE=HOME:male
ORG:Farmer Jack;
LANG;PREF=1:fr
LANG;PREF=2:en
RELATIONSHIP:BROTHER
TITLE:Refuse and recyclable material collector
EMAIL;TYPE=HOME,INTERNET,pref:AalbjornSnorrason@einrot.com
EMAIL;TYPE=HOME,pref:AalbjornSnorrason@einrot.com
CATEGORIES:Family
TEL;TYPE=VOICE,HOME;PREF=1;VALUE=text:021 511 81 18
ADR;TYPE=HOME:;;Sédeilles;;1554;Switzerland
ADR;TYPE=home:;;Sédeilles;;1554;Switzerland
END:VCARD
BEGIN:VCARD
VERSION:3.0
@ -1478,7 +1479,7 @@ BDAY;VALUE=text:2/26/1971
GENDER:female
ORG:Crown Auto Parts;
TITLE:Material moving occupation
EMAIL;TYPE=HOME,INTERNET,pref:GalRobledoPrieto@cuvox.de
EMAIL;TYPE=HOME,pref:GalRobledoPrieto@cuvox.de
CATEGORIES:Cousins
TEL;TYPE=VOICE,HOME;VALUE=text:05.93.86.47.32
ADR;TYPE=HOME:;;BAIE-MAHAULT;GD;97122;France