mirror of https://github.com/nextcloud/contacts
Added external link support
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
parent
91d6491633
commit
bbc3d8e130
|
@ -52,8 +52,8 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
&:hover,
|
||||
a:active,
|
||||
a:focus {
|
||||
&:active,
|
||||
&:focus {
|
||||
opacity: .7;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 |
|
@ -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" />
|
||||
|
|
|
@ -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
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ const properties = {
|
|||
tel: {
|
||||
multiple: true,
|
||||
readableName: t('contacts', 'Phone'),
|
||||
icon: 'icon-comment',
|
||||
icon: 'icon-phone',
|
||||
default: true,
|
||||
defaultValue: {
|
||||
value: '',
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue