Skip to content

Commit

Permalink
Merge pull request #2658 from SebieF/feature/sort-by-tags
Browse files Browse the repository at this point in the history
[Feature] Enable sorting by tags
  • Loading branch information
raimund-schluessler authored Sep 22, 2024
2 parents 63264ec + 93f1f60 commit d3dd45c
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/components/SortorderDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import OrderAlphabeticalAscending from 'vue-material-design-icons/OrderAlphabeti
import Pencil from 'vue-material-design-icons/Pencil.vue'
import Plus from 'vue-material-design-icons/Plus.vue'
import Star from 'vue-material-design-icons/Star.vue'
import TagMultiple from 'vue-material-design-icons/TagMultiple.vue'
import { mapGetters } from 'vuex'
Expand All @@ -94,6 +95,7 @@ export default {
Pencil,
Plus,
Star,
TagMultiple
},
directives: {
Tooltip,
Expand Down Expand Up @@ -150,6 +152,12 @@ export default {
text: t('tasks', 'Alphabetically'),
hint: t('tasks', 'Sort by summary and priority.'),
},
{
id: 'tags',
icon: 'TagMultiple',
text: t('tasks', 'Tags'),
hint: t('tasks', 'Sort by tags.'),
},
{
id: 'manual',
icon: 'AnimationOutline',
Expand Down
2 changes: 1 addition & 1 deletion src/models/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ export default class Task {
/**
* Set the tags
*
* @param {string} newTags The tags
* * @param {string[]} newTags The new tags to set
* @memberof Task
*/
set tags(newTags) {
Expand Down
27 changes: 27 additions & 0 deletions src/store/storeHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ function sort(tasks, sortOrder, sortDirection) {
comparators = [sortByDeletedAt]
break
}
case 'tags': {
comparators = [sortByPinned, sortByTags, sortAlphabetically]
break
}
case 'manual': {
comparators = [sortBySortOrder]
break
Expand Down Expand Up @@ -415,6 +419,29 @@ function sortByDate(taskA, taskB, date) {
return taskA[date + 'Moment'].diff(taskB[date + 'Moment'])
}

/**
* Comparator to compare two tasks by tags in ascending order
*
* @param {Task} taskA The first task
* @param {Task} taskB The second task
* @return {number}
*/
function sortByTags(taskA, taskB) {
const tagsA = taskA.tags.sort()
const tagsB = taskB.tags.sort()

// Compare each tag in order
for (let i = 0; i < Math.min(tagsA.length, tagsB.length); i++) {
const comparison = tagsA[i].toLowerCase().localeCompare(tagsB[i].toLowerCase())
if (comparison !== 0) {
return comparison
}
}

// If all compared tags are equal, shorter tag list comes first
return tagsA.length - tagsB.length
}

/**
* Comparator to compare two tasks by sort order in ascending order
*
Expand Down
20 changes: 20 additions & 0 deletions tests/javascript/unit/store/storeHelper.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ describe('storeHelper - sort', () => {
const receivedTasks = sort(clonedTasks, 'due', 1)
expect(receivedTasks).toEqual(expectedTasks)
})

it('Tests descending sort by tags', () => {
const clonedTasks = tasks.slice(0)

clonedTasks[0].tags = ['B', 'C']
clonedTasks[1].tags = ['A', 'D']
clonedTasks[2].tags = []
clonedTasks[3].tags = ['B']

const expectedOrder = [clonedTasks[2], clonedTasks[1], clonedTasks[3], clonedTasks[0]]
const receivedTasks = sort(clonedTasks.slice(), 'tags', 0)

expect(receivedTasks).toEqual(expectedOrder)
expect(receivedTasks[0].tags).toHaveLength(0)
expect(receivedTasks[1].tags[0]).toBe('A')
expect(receivedTasks[2].tags[0]).toBe('B')
expect(receivedTasks[3].tags[0]).toBe('B')
expect(receivedTasks[3].tags[1]).toBe('C')
expect(receivedTasks[3].tags).toHaveLength(2)
})
})

describe('storeHelper - parseString', () => {
Expand Down

0 comments on commit d3dd45c

Please sign in to comment.