-
Notifications
You must be signed in to change notification settings - Fork 173
/
ContactsListItem.vue
165 lines (155 loc) Β· 4.43 KB
/
ContactsListItem.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<template>
<transition name="delete-slide-left">
<div v-if="!deleteTimeout"
:id="id"
:class="{active: selectedContact === contact.key}"
tabindex="0"
class="app-content-list-item"
@click.prevent.stop="selectContact"
@keypress.enter.prevent.stop="selectContact">
<!-- keyboard accessibility will focus the input and not the label -->
<!--
<input ref="selected" :id="contact.key" type="checkbox"
class="app-content-list-item-checkbox checkbox" @keypress.enter.space.prevent.stop="toggleSelect">
<label :for="contact.key" @click.prevent.stop="toggleSelect" @keypress.enter.space.prevent.stop="toggleSelect" />
-->
<div :style="{ 'backgroundColor': colorAvatar }" class="app-content-list-item-icon">
{{ contact.displayName | firstLetter }}
<!-- try to fetch the avatar only if the contact exists on the server -->
<div v-if="hasPhoto" :style="{ 'backgroundImage': avatarUrl }" class="app-content-list-item-icon__avatar" />
</div>
<!-- contact data -->
<div class="app-content-list-item-line-one">
{{ contact.displayName }}
</div>
<div v-if="contact.email" class="app-content-list-item-line-two">
{{ contact.email }}
</div>
<!-- undo actions -->
<div v-if="!contact.addressbook.readOnly && !deleteTimeout"
class="icon-delete"
tabindex="0"
@click.prevent.stop="deleteContact"
@keypress.enter.prevent.stop="deleteContact" />
</div>
<!-- Deleted contact (pending) -->
<div v-else
:id="id"
key="deleted"
class="deleted app-content-list-item">
<div :style="{ backgroundColor: 'grey' }" class="app-content-list-item-icon">
{{ contact.displayName | firstLetter }}
<!-- try to fetch the avatar only if the contact exists on the server -->
<div v-if="hasPhoto" :style="{ 'backgroundImage': avatarUrl }" class="app-content-list-item-icon__avatar" />
</div>
<!-- contact data -->
<div class="app-content-list-item-line-one">
{{ contact.displayName }}
</div>
<div v-tooltip.auto="t('contacts', 'Deleting the contact in {countdown} seconds', { countdown })"
class="icon-history"
tabindex="0"
@click.prevent.stop="cancelDeletion"
@keypress.enter.prevent.stop="cancelDeletion" />
</div>
</transition>
</template>
<script>
export default {
name: 'ContactsListItem',
filters: {
firstLetter(value) {
return value.charAt(0)
},
},
props: {
index: {
type: Number,
required: true,
},
contact: {
type: Object,
required: true,
},
},
data() {
return {
deleteInterval: null,
deleteTimeout: null,
countdown: 7,
}
},
computed: {
selectedGroup() {
return this.$route.params.selectedGroup
},
selectedContact() {
return this.$route.params.selectedContact
},
// usable and valid html id for scrollTo
id() {
return window.btoa(this.contact.key).slice(0, -2)
},
hasPhoto() {
return this.contact.dav && (this.contact.dav.hasphoto || this.contact.photo)
},
/**
* avatar color based on server toRgb method and the displayName
* @returns {string} the color in css format
*/
colorAvatar() {
try {
const color = this.contact.uid.toRgb()
return `rgb(${color.r}, ${color.g}, ${color.b})`
} catch (e) {
return 'grey'
}
},
avatarUrl() {
if (this.contact.photo) {
return `url(${this.contact.photoUrl})`
}
return `url(${this.contact.url}?photo)`
},
},
methods: {
/**
* Checkbox management method
*/
toggleSelect() {
// toggle checkbox here because we stop the propagation to not trigger selectContact
// therefore the selectContact prevent the checkbox label+input propagation
this.$refs.selected.checked = !this.$refs.selected.checked
},
/**
* Dispatch contact deletion request
*/
deleteContact() {
this.deleteInterval = setInterval(() => {
this.countdown--
}, 1000)
this.deleteTimeout = setTimeout(() => {
this.$store.dispatch('deleteContact', { contact: this.contact })
this.$emit('deleted', this.index)
// reset
clearInterval(this.deleteInterval)
this.countdown = 7
}, 7000)
},
cancelDeletion() {
clearTimeout(this.deleteTimeout)
clearInterval(this.deleteInterval)
this.deleteTimeout = null
this.deleteInterval = null
this.countdown = 7
},
/**
* Select this contact within the list
*/
selectContact() {
// change url with router
this.$router.push({ name: 'contact', params: { selectedGroup: this.selectedGroup, selectedContact: this.contact.key } })
},
},
}
</script>