summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2018-11-13 17:33:46 +0100
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2018-11-13 17:44:02 +0100
commitbbc3d8e130bda3d17ad8de310a94c01c4531134c (patch)
tree99928de259217361e3359ce08f8cdb1362886dc0
parent91d64916333490b70c636a5a25627e8d6b39db5d (diff)
Added external link support
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
-rw-r--r--css/ContactDetailsAvatar.scss4
-rw-r--r--css/Properties/Properties.scss82
-rw-r--r--css/icons.scss4
-rw-r--r--img/phone.svg2
-rw-r--r--src/components/ContactDetails.vue4
-rw-r--r--src/components/Properties/PropertyText.vue37
-rw-r--r--src/models/rfcProps.js2
-rw-r--r--src/views/Contacts.vue2
8 files changed, 99 insertions, 38 deletions
diff --git a/css/ContactDetailsAvatar.scss b/css/ContactDetailsAvatar.scss
index 95a7cf1a..34920f37 100644
--- a/css/ContactDetailsAvatar.scss
+++ b/css/ContactDetailsAvatar.scss
@@ -52,8 +52,8 @@
width: 100%;
height: 100%;
&:hover,
- a:active,
- a:focus {
+ &:active,
+ &:focus {
opacity: .7;
}
}
diff --git a/css/Properties/Properties.scss b/css/Properties/Properties.scss
index 817627c8..d27ee5f8 100644
--- a/css/Properties/Properties.scss
+++ b/css/Properties/Properties.scss
@@ -35,37 +35,12 @@
&--addressbooks &__delete {
display: none !important;
}
-
- &__delete {
- position: absolute;
- top: 0;
- right: 0;
- width: $grid-height-unit;
- height: $grid-height-unit;
- margin: 0;
- border: 0;
- background-color: transparent;
- opacity: .5;
- display: none;
- &:hover,
- a:active,
- a:focus {
- opacity: .7;
- }
- }
-
- &:hover &__delete,
- a:active &__delete,
- a:focus &__delete {
- display: block;
- }
-
+
// property row
&__row {
display: flex;
align-items: center;
padding-right: 44px;
- // height: $grid-height-unit;
position: relative;
}
@@ -129,7 +104,7 @@
}
}
- // property value within row, after label
+ // Property value within row, after label
&__value {
flex: 1 1;
@@ -143,5 +118,58 @@
&:read-only {
border-color: var(--color-border-dark);
}
+ input&--with-ext {
+ // ext icon width + 8px padding
+ padding-right: 24px;
+ &:hover,
+ &:focus,
+ &:active {
+ ~ .property__ext,
+ ~ .property__delete {
+ opacity: .5;
+ }
+ }
+ }
+ }
+
+ // show ext & delete button on full row hover
+ &:hover &__ext,
+ &:hover &__delete {
+ opacity: .5;
+ }
+
+ // External link (tel, mailto, http, ftp...)
+ &__ext {
+ position: absolute;
+ // property row rightPadding + 8px;
+ right: 52px;
+ opacity: 0;
+ &:hover,
+ &:focus,
+ &:active {
+ opacity: .7;
+ // still show the delete button for keyboard accessibility
+ ~ .property__delete {
+ opacity: .7;
+ }
+ }
+ }
+
+ // Delete property button
+ &__delete {
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: $grid-height-unit;
+ height: $grid-height-unit;
+ margin: 0;
+ border: 0;
+ background-color: transparent;
+ opacity: 0;
+ &:hover,
+ &:active,
+ &:focus {
+ opacity: .7;
+ }
}
}
diff --git a/css/icons.scss b/css/icons.scss
index 00f390e9..5549a162 100644
--- a/css/icons.scss
+++ b/css/icons.scss
@@ -28,6 +28,10 @@
@include icon-color('address-book', 'contacts', $color-black, 1);
}
+.icon-phone {
+ @include icon-color('phone', 'contacts', $color-black, 1);
+}
+
.icon-eye-white {
@include icon-color('eye', 'contacts', $color-white, 1);
}
diff --git a/img/phone.svg b/img/phone.svg
new file mode 100644
index 00000000..8ced1725
--- /dev/null
+++ b/img/phone.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="16" height="16" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1600 1240q0 27-10 70.5t-21 68.5q-21 50-122 106-94 51-186 51-27 0-53-3.5t-57.5-12.5-47-14.5-55.5-20.5-49-18q-98-35-175-83-127-79-264-216t-216-264q-48-77-83-175-3-9-18-49t-20.5-55.5-14.5-47-12.5-57.5-3.5-53q0-92 51-186 56-101 106-122 25-11 68.5-21t70.5-10q14 0 21 3 18 6 53 76 11 19 30 54t35 63.5 31 53.5q3 4 17.5 25t21.5 35.5 7 28.5q0 20-28.5 50t-62 55-62 53-28.5 46q0 9 5 22.5t8.5 20.5 14 24 11.5 19q76 137 174 235t235 174q2 1 19 11.5t24 14 20.5 8.5 22.5 5q18 0 46-28.5t53-62 55-62 50-28.5q14 0 28.5 7t35.5 21.5 25 17.5q25 15 53.5 31t63.5 35 54 30q70 35 76 53 3 7 3 21z"/></svg> \ No newline at end of file
diff --git a/src/components/ContactDetails.vue b/src/components/ContactDetails.vue
index 05a4d483..dd4cb3ca 100644
--- a/src/components/ContactDetails.vue
+++ b/src/components/ContactDetails.vue
@@ -97,7 +97,7 @@
<!-- properties iteration -->
<!-- using contact.key in the key and index as key to avoid conflicts between similar data and exact key -->
- <contact-property v-for="(property, index) in sortedProperties" :key="index+contact.key" :index="index"
+ <contact-property v-for="(property, index) in sortedProperties" :key="`${index}-${contact.key}-${property.name}`" :index="index"
:sorted-properties="sortedProperties" :property="property" :contact="contact"
@updatedcontact="updateContact" />
@@ -106,7 +106,7 @@
we are hijacking this... (this is supposed to be used with a ICAL.property, but to avoid code
duplication, we created a fake propModel and property with our own options here) -->
<property-select :prop-model="addressbookModel" :value.sync="addressbook" :is-first-property="true"
- :is-last-property="true" :property="{}" class="property--addressbooks" />
+ :is-last-property="true" :property="{}" class="property--addressbooks property--last" />
<!-- new property select -->
<add-new-prop v-if="!isReadOnly" :contact="contact" />
diff --git a/src/components/Properties/PropertyText.vue b/src/components/Properties/PropertyText.vue
index 7c9fd99e..fa5ac71a 100644
--- a/src/components/Properties/PropertyText.vue
+++ b/src/components/Properties/PropertyText.vue
@@ -39,10 +39,6 @@
<!-- no options, empty space -->
<div v-else class="property__label">{{ propModel.readableName }}</div>
- <!-- delete the prop -->
- <button v-if="!isReadOnly" :title="t('contacts', 'Delete')" class="property__delete icon-delete"
- @click="deleteProperty" />
-
<!-- textarea for note -->
<textarea v-if="propName === 'note'" id="textarea" ref="textarea"
v-model.trim="localValue" :type="type" :readonly="isReadOnly"
@@ -51,7 +47,16 @@
<!-- OR default to input -->
<input v-else v-model.trim="localValue" :type="type"
- :readonly="isReadOnly" class="property__value" @input="updateValue">
+ :readonly="isReadOnly" :class="{'property__value--with-ext': haveExtHandler}" class="property__value"
+ @input="updateValue">
+
+ <!-- external link -->
+ <a v-if="haveExtHandler" :href="externalHandler" class="property__ext icon-external"
+ target="_blank" />
+
+ <!-- delete the prop -->
+ <button v-if="!isReadOnly" :title="t('contacts', 'Delete')" class="property__delete icon-delete"
+ @click="deleteProperty" />
</div>
</div>
</template>
@@ -115,6 +120,28 @@ export default {
return 'url'
}
return 'text'
+ },
+ URLScheme() {
+ if (this.propName === 'tel') {
+ return 'tel:'
+ } else if (this.propName === 'email') {
+ return 'mailto:'
+ // if no scheme (roughly checking for the colon char)
+ } else if (this.propType === 'uri' && this.value.indexOf(':') === -1) {
+ return 'https://'
+ } else if (this.propType === 'uri') {
+ return '' // return empty, we already have a scheme in the value
+ }
+ return false
+ },
+ // format external link
+ externalHandler() {
+ if (this.URLScheme !== false) {
+ return `${this.URLScheme}${this.value}`
+ }
+ },
+ haveExtHandler() {
+ return this.externalHandler && this.value && this.value.length > 0
}
},
diff --git a/src/models/rfcProps.js b/src/models/rfcProps.js
index 8051c1a0..3f7efe53 100644
--- a/src/models/rfcProps.js
+++ b/src/models/rfcProps.js
@@ -146,7 +146,7 @@ const properties = {
tel: {
multiple: true,
readableName: t('contacts', 'Phone'),
- icon: 'icon-comment',
+ icon: 'icon-phone',
default: true,
defaultValue: {
value: '',
diff --git a/src/views/Contacts.vue b/src/views/Contacts.vue
index 14395b89..971e631b 100644
--- a/src/views/Contacts.vue
+++ b/src/views/Contacts.vue
@@ -108,7 +108,7 @@ export default {
importState() {
return this.$store.getters.getImportState
},
-
+
// first enabled addressbook of the list
defaultAddressbook() {
return this.addressbooks.find(addressbook => !addressbook.readOnly && addressbook.enabled)