Skip to content

Commit

Permalink
feat(NcListItemIcon): Allow to highlight search queries using the ema…
Browse files Browse the repository at this point in the history
…il notation

Like `J. Doe <[email protected]>`

Signed-off-by: Ferdinand Thiessen <[email protected]>
  • Loading branch information
susnux committed Oct 17, 2023
1 parent 66f81d0 commit f28493b
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 2 deletions.
16 changes: 14 additions & 2 deletions src/components/NcListItemIcon/NcListItemIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,11 @@ It might be used for list rendering or within the multiselect for example
<div class="option__details">
<NcHighlight class="option__lineone"
:text="name"
:search="search" />
:search="searchParts[0]" />
<NcHighlight v-if="isValidSubname && isSizeBigEnough"
class="option__linetwo"
:text="subname"
:search="search" />
:search="searchParts[1]" />
<span v-else-if="hasStatus">
<span>{{ userStatus.icon }}</span>
<span>{{ userStatus.message }}</span>
Expand Down Expand Up @@ -314,6 +314,18 @@ export default {
'--margin': this.margin + 'px',
}
},
/**
* Seperates the search property into two parts, the first one is the search part on the name, the second on the subname.
* @return {[string, string]}
*/
searchParts() {
// Match the email notation like "Jane <[email protected]>" with the email address as matching group
const EMAIL_NOTATION = /^([^<]*)<([^>]+)>?$/
const match = this.search.match(EMAIL_NOTATION)
return this.isNoUser || !match ? [this.search, this.search] : [match[1].trim(), match[2]]
},
},
beforeMount() {
Expand Down
104 changes: 104 additions & 0 deletions tests/unit/components/NcListItemIcon/list-item-icon.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* @copyright Copyright (c) 2023 Ferdinand Thiessen <[email protected]>
*
* @author Ferdinand Thiessen <[email protected]>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

import { shallowMount } from '@vue/test-utils'
import NcListItemIcon from '../../../../src/components/NcListItemIcon/NcListItemIcon.vue'

describe('NcListItemIcon', () => {
it('highlights the search query', async () => {
const wrapper = shallowMount(NcListItemIcon, {
propsData: {
name: 'J. Doe',
subname: '[email protected]',
search: 'doe',
},
})

const highlights = wrapper.findAllComponents({ name: 'NcHighlight' })
expect(highlights).toHaveLength(2)
expect(highlights.at(0).props('text')).toBe('J. Doe')
expect(highlights.at(0).props('search')).toBe('doe')
expect(highlights.at(1).props('text')).toBe('[email protected]')
expect(highlights.at(1).props('search')).toBe('doe')
})

it('highlights the email notation query', async () => {
const wrapper = shallowMount(NcListItemIcon, {
propsData: {
name: 'J. Doe',
subname: '[email protected]',
search: 'Manager <[email protected]>',
},
})

const highlights = wrapper.findAllComponents({ name: 'NcHighlight' })
expect(highlights).toHaveLength(2)
expect(highlights.at(0).props('search')).toBe('Manager')
expect(highlights.at(1).props('search')).toBe('[email protected]')
})

it('highlights the email notation query even if only partly typed', async () => {
const wrapper = shallowMount(NcListItemIcon, {
propsData: {
name: 'J. Doe',
subname: '[email protected]',
search: 'Manager <privacy',
},
})

const highlights = wrapper.findAllComponents({ name: 'NcHighlight' })
expect(highlights).toHaveLength(2)
expect(highlights.at(0).props('search')).toBe('Manager')
expect(highlights.at(1).props('search')).toBe('privacy')
})

it('does not highlight the email notation query when missing email', async () => {
const wrapper = shallowMount(NcListItemIcon, {
propsData: {
name: 'J. Doe',
subname: '[email protected]',
search: 'Doe <',
},
})

const highlights = wrapper.findAllComponents({ name: 'NcHighlight' })
expect(highlights).toHaveLength(2)
expect(highlights.at(0).props('search')).toBe('Doe <')
expect(highlights.at(1).props('search')).toBe('Doe <')
})

it('does not highlight the email notation query when no user', async () => {
const wrapper = shallowMount(NcListItemIcon, {
propsData: {
name: 'J. Doe',
subname: '[email protected]',
search: 'Doe <[email protected]>',
isNoUser: true,
},
})

const highlights = wrapper.findAllComponents({ name: 'NcHighlight' })
expect(highlights).toHaveLength(2)
expect(highlights.at(0).props('search')).toBe('Doe <[email protected]>')
expect(highlights.at(1).props('search')).toBe('Doe <[email protected]>')
})
})

0 comments on commit f28493b

Please sign in to comment.