<!--
  - SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
  - SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
	<NcHeaderMenu id="contactsmenu"
		class="contactsmenu"
		:aria-label="t('core', 'Search contacts')"
		@open="handleOpen">
		<template #trigger>
			<Contacts class="contactsmenu__trigger-icon" :size="20" />
		</template>
		<div class="contactsmenu__menu">
			<div class="contactsmenu__menu__input-wrapper">
				<NcTextField id="contactsmenu__menu__search"
					ref="contactsMenuInput"
					:value.sync="searchTerm"
					trailing-button-icon="close"
					:label="t('core', 'Search contacts')"
					:trailing-button-label="t('core','Reset search')"
					:show-trailing-button="searchTerm !== ''"
					:placeholder="t('core', 'Search contacts …')"
					class="contactsmenu__menu__search"
					@input="onInputDebounced"
					@trailing-button-click="onReset" />
			</div>
			<NcEmptyContent v-if="error" :name="t('core', 'Could not load your contacts')">
				<template #icon>
					<Magnify />
				</template>
			</NcEmptyContent>
			<NcEmptyContent v-else-if="loadingText" :name="loadingText">
				<template #icon>
					<NcLoadingIcon />
				</template>
			</NcEmptyContent>
			<NcEmptyContent v-else-if="contacts.length === 0" :name="t('core', 'No contacts found')">
				<template #icon>
					<Magnify />
				</template>
			</NcEmptyContent>
			<div v-else class="contactsmenu__menu__content">
				<div id="contactsmenu-contacts">
					<ul>
						<Contact v-for="contact in contacts" :key="contact.id" :contact="contact" />
					</ul>
				</div>
				<div v-if="contactsAppEnabled" class="contactsmenu__menu__content__footer">
					<NcButton type="tertiary" :href="contactsAppURL">
						{{ t('core', 'Show all contacts') }}
					</NcButton>
				</div>
				<div v-else-if="canInstallApp" class="contactsmenu__menu__content__footer">
					<NcButton type="tertiary" :href="contactsAppMgmtURL">
						{{ t('core', 'Install the Contacts app') }}
					</NcButton>
				</div>
			</div>
		</div>
	</NcHeaderMenu>
</template>

<script>
import axios from '@nextcloud/axios'
import Contacts from 'vue-material-design-icons/Contacts.vue'
import debounce from 'debounce'
import { getCurrentUser } from '@nextcloud/auth'
import { generateUrl } from '@nextcloud/router'
import Magnify from 'vue-material-design-icons/Magnify.vue'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import NcHeaderMenu from '@nextcloud/vue/dist/Components/NcHeaderMenu.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import { translate as t } from '@nextcloud/l10n'

import Contact from '../components/ContactsMenu/Contact.vue'
import logger from '../logger.js'
import Nextcloud from '../mixins/Nextcloud.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'

export default {
	name: 'ContactsMenu',

	components: {
		Contact,
		Contacts,
		Magnify,
		NcButton,
		NcEmptyContent,
		NcHeaderMenu,
		NcLoadingIcon,
		NcTextField,
	},

	mixins: [Nextcloud],

	data() {
		const user = getCurrentUser()
		return {
			contactsAppEnabled: false,
			contactsAppURL: generateUrl('/apps/contacts'),
			contactsAppMgmtURL: generateUrl('/settings/apps/social/contacts'),
			canInstallApp: user.isAdmin,
			contacts: [],
			loadingText: undefined,
			error: false,
			searchTerm: '',
		}
	},

	methods: {
		async handleOpen() {
			await this.getContacts('')
		},
		async getContacts(searchTerm) {
			if (searchTerm === '') {
				this.loadingText = t('core', 'Loading your contacts …')
			} else {
				this.loadingText = t('core', 'Looking for {term} …', {
					term: searchTerm,
				})
			}

			// Let the user try a different query if the previous one failed
			this.error = false

			try {
				const { data: { contacts, contactsAppEnabled } } = await axios.post(generateUrl('/contactsmenu/contacts'), {
					filter: searchTerm,
				})
				this.contacts = contacts
				this.contactsAppEnabled = contactsAppEnabled
				this.loadingText = undefined
			} catch (error) {
				logger.error('could not load contacts', {
					error,
					searchTerm,
				})
				this.error = true
			}
		},
		onInputDebounced: debounce(function() {
			this.getContacts(this.searchTerm)
		}, 500),

		/**
		 * Reset the search state
		 */
		onReset() {
			this.searchTerm = ''
			this.contacts = []
			this.focusInput()
		},

		/**
		 * Focus the search input on next tick
		 */
		focusInput() {
			this.$nextTick(() => {
				this.$refs.contactsMenuInput.focus()
				this.$refs.contactsMenuInput.select()
			})
		},

	},
}
</script>

<style lang="scss" scoped>
.contactsmenu {
	overflow-y: hidden;

	&__trigger-icon {
		color: var(--color-background-plain-text) !important;
	}

	&__menu {
		display: flex;
		flex-direction: column;
		overflow: hidden;
		height: calc(50px * 6 + 2px + 26px);
		max-height: inherit;

		label[for="contactsmenu__menu__search"] {
			font-weight: bold;
			font-size: 19px;
			margin-inline-start: 13px;
		}

		&__input-wrapper {
			padding: 10px;
			z-index: 2;
			top: 0;
		}

		&__search {
			width: 100%;
			height: 34px;
			margin-top: 0!important;
		}

		&__content {
			overflow-y: auto;
			margin-top: 10px;
			flex: 1 1 auto;

			&__footer {
				display: flex;
				flex-direction: column;
				align-items: center;
			}
		}

		a {
			&:focus-visible {
				box-shadow: inset 0 0 0 2px var(--color-main-text) !important; // override rule in core/css/headers.scss #header a:focus-visible
			}
		}
	}

	:deep(.empty-content) {
		margin: 0 !important;
	}
}
</style>
c1b8c6f54779742f3'>tree</a><a href='/sonarqube.git/commit/sonar-duplications/pom.xml?id=346073fd910bd820e95c497c1b8c6f54779742f3'>commit</a><a href='/sonarqube.git/diff/sonar-duplications/pom.xml?id=346073fd910bd820e95c497c1b8c6f54779742f3'>diff</a><a href='/sonarqube.git/stats/sonar-duplications/pom.xml'>stats</a></td><td class='form'><form class='right' method='get' action='/sonarqube.git/log/sonar-duplications/pom.xml'>
<input type='hidden' name='id' value='346073fd910bd820e95c497c1b8c6f54779742f3'/><select name='qt'>
<option value='grep'>log msg</option>
<option value='author'>author</option>
<option value='committer'>committer</option>
<option value='range'>range</option>
</select>
<input class='txt' type='search' size='10' name='q' value=''/>
<input type='submit' value='search'/>
</form>
</td></tr></table>
<div class='path'>path: <a href='/sonarqube.git/tree/?id=346073fd910bd820e95c497c1b8c6f54779742f3'>root</a>/<a href='/sonarqube.git/tree/sonar-duplications?id=346073fd910bd820e95c497c1b8c6f54779742f3'>sonar-duplications</a>/<a href='/sonarqube.git/tree/sonar-duplications/pom.xml?id=346073fd910bd820e95c497c1b8c6f54779742f3'>pom.xml</a></div><div class='content'>blob: 9e6ec34f5b6a64f524eab124464e851a0ffcaa70 (<a href='/sonarqube.git/plain/sonar-duplications/pom.xml?id=346073fd910bd820e95c497c1b8c6f54779742f3'>plain</a>)
<table summary='blob content' class='blob'>
<tr><td class='linenumbers'><pre><a id='n1' href='#n1'>1</a>
<a id='n2' href='#n2'>2</a>
<a id='n3' href='#n3'>3</a>
<a id='n4' href='#n4'>4</a>
<a id='n5' href='#n5'>5</a>
<a id='n6' href='#n6'>6</a>
<a id='n7' href='#n7'>7</a>
<a id='n8' href='#n8'>8</a>
<a id='n9' href='#n9'>9</a>
<a id='n10' href='#n10'>10</a>
<a id='n11' href='#n11'>11</a>
<a id='n12' href='#n12'>12</a>
<a id='n13' href='#n13'>13</a>
<a id='n14' href='#n14'>14</a>
<a id='n15' href='#n15'>15</a>
<a id='n16' href='#n16'>16</a>
<a id='n17' href='#n17'>17</a>
<a id='n18' href='#n18'>18</a>
<a id='n19' href='#n19'>19</a>
<a id='n20' href='#n20'>20</a>
<a id='n21' href='#n21'>21</a>
<a id='n22' href='#n22'>22</a>
<a id='n23' href='#n23'>23</a>
<a id='n24' href='#n24'>24</a>
<a id='n25' href='#n25'>25</a>
<a id='n26' href='#n26'>26</a>
<a id='n27' href='#n27'>27</a>
<a id='n28' href='#n28'>28</a>
<a id='n29' href='#n29'>29</a>
<a id='n30' href='#n30'>30</a>
<a id='n31' href='#n31'>31</a>
<a id='n32' href='#n32'>32</a>
<a id='n33' href='#n33'>33</a>
<a id='n34' href='#n34'>34</a>
<a id='n35' href='#n35'>35</a>
<a id='n36' href='#n36'>36</a>
<a id='n37' href='#n37'>37</a>
<a id='n38' href='#n38'>38</a>
<a id='n39' href='#n39'>39</a>
<a id='n40' href='#n40'>40</a>
<a id='n41' href='#n41'>41</a>
<a id='n42' href='#n42'>42</a>
<a id='n43' href='#n43'>43</a>
<a id='n44' href='#n44'>44</a>
<a id='n45' href='#n45'>45</a>
<a id='n46' href='#n46'>46</a>
<a id='n47' href='#n47'>47</a>
<a id='n48' href='#n48'>48</a>
<a id='n49' href='#n49'>49</a>
<a id='n50' href='#n50'>50</a>
<a id='n51' href='#n51'>51</a>
<a id='n52' href='#n52'>52</a>
<a id='n53' href='#n53'>53</a>
<a id='n54' href='#n54'>54</a>
<a id='n55' href='#n55'>55</a>
<a id='n56' href='#n56'>56</a>
<a id='n57' href='#n57'>57</a>
<a id='n58' href='#n58'>58</a>
<a id='n59' href='#n59'>59</a>
<a id='n60' href='#n60'>60</a>
<a id='n61' href='#n61'>61</a>
<a id='n62' href='#n62'>62</a>
<a id='n63' href='#n63'>63</a>
<a id='n64' href='#n64'>64</a>
<a id='n65' href='#n65'>65</a>
<a id='n66' href='#n66'>66</a>
<a id='n67' href='#n67'>67</a>
<a id='n68' href='#n68'>68</a>
<a id='n69' href='#n69'>69</a>
<a id='n70' href='#n70'>70</a>
<a id='n71' href='#n71'>71</a>
<a id='n72' href='#n72'>72</a>
<a id='n73' href='#n73'>73</a>
<a id='n74' href='#n74'>74</a>
<a id='n75' href='#n75'>75</a>
<a id='n76' href='#n76'>76</a>
<a id='n77' href='#n77'>77</a>
<a id='n78' href='#n78'>78</a>
<a id='n79' href='#n79'>79</a>
</pre></td>
<td class='lines'><pre><code>