Added external link support

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
John Molakvoæ (skjnldsv) 2018-11-13 17:33:46 +01:00
parent 91d6491633
commit bbc3d8e130
No known key found for this signature in database
GPG Key ID: 60C25B8C072916CF
8 changed files with 99 additions and 38 deletions

View File

@ -52,8 +52,8 @@
width: 100%;
height: 100%;
&:hover,
a:active,
a:focus {
&:active,
&:focus {
opacity: .7;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}

2
img/phone.svg Normal file
View File

@ -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>

After

Width:  |  Height:  |  Size: 714 B

View File

@ -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" />

View File

@ -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
}
},

View File

@ -146,7 +146,7 @@ const properties = {
tel: {
multiple: true,
readableName: t('contacts', 'Phone'),
icon: 'icon-comment',
icon: 'icon-phone',
default: true,
defaultValue: {
value: '',

View File

@ -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)