summaryrefslogtreecommitdiffstats
path: root/src/components/ContactsList/ContactsListItem.vue
blob: b45d3ddc8eff640dbf79d4ad55fad8b4bb444f09 (plain)
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
<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 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 {
			deleteTimeout: null
		}
	},
	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 {
				let 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.photo})`
			}
			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.deleteTimeout = setTimeout(() => {
				this.$store.dispatch('deleteContact', { contact: this.contact })
				this.$emit('deleted', this.index)
			}, 7000)
		},

		cancelDeletion() {
			clearTimeout(this.deleteTimeout)
			this.deleteTimeout = null
		},

		/**
		 * 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>