Skip to content

Commit

Permalink
Correctly filter tasks in challenges and remove filters where unhelpf…
Browse files Browse the repository at this point in the history
…ul (HabitRPG#12522)

* Correctly filter tasks in challenges and remove filters where unhelpful

* update isDue property on the client as soon as challenges are created or edited

* change method of update for task on receiving data

* try different assign method

* fix lint

* fix issue with data reactivity

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
  • Loading branch information
kirsty-tortoise and paglias committed Sep 7, 2020
1 parent 362677a commit 1b25d30
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 39 deletions.
22 changes: 11 additions & 11 deletions website/client/src/components/tasks/column.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
>
{{ badgeCount }}
</div>
<div class="filters d-flex justify-content-end">
<div
v-if="typeFilters.length > 1"
class="filters d-flex justify-content-end"
>
<div
v-for="filter in typeFilters"
:key="filter"
Expand Down Expand Up @@ -353,6 +356,7 @@ import {
getTypeLabel,
getFilterLabels,
getActiveFilter,
sortAndFilterTasks,
} from '@/libs/store/helpers/filterTasks';
import habitIcon from '@/assets/svg/habit.svg';
Expand Down Expand Up @@ -433,7 +437,7 @@ export default {
type: this.type,
filterType: this.activeFilter.label,
})
: this.filterByLabel(this.taskListOverride, this.activeFilter.label);
: this.filterByLabel(this.taskListOverride, this.type, this.activeFilter.label);
const taggedList = this.filterByTagList(filteredTaskList, this.selectedTags);
const searchedList = this.filterBySearchText(taggedList, this.searchText);
Expand Down Expand Up @@ -500,7 +504,7 @@ export default {
// Set Task Column Label
this.typeLabel = getTypeLabel(this.type);
// Get Category Filter Labels
this.typeFilters = getFilterLabels(this.type);
this.typeFilters = getFilterLabels(this.type, this.challenge);
// Set default filter for task column
this.activateFilter(this.type);
},
Expand Down Expand Up @@ -637,7 +641,7 @@ export default {
filter = 'due'; // eslint-disable-line no-param-reassign
}
this.activeFilter = getActiveFilter(type, filter);
this.activeFilter = getActiveFilter(type, filter, this.challenge);
},
setColumnBackgroundVisibility () {
this.$nextTick(() => {
Expand Down Expand Up @@ -665,14 +669,10 @@ export default {
}
});
},
filterByLabel (taskList, filter) {
filterByLabel (taskList, type, filter) {
if (!taskList) return [];
return taskList.filter(task => {
if (filter === 'complete2') return task.completed;
if (filter === 'due') return task.isDue;
if (filter === 'notDue') return !task.isDue;
return !task.completed;
});
const selectedFilter = getActiveFilter(type, filter, this.challenge);
return sortAndFilterTasks(taskList, selectedFilter);
},
filterByTagList (taskList, tagList = []) {
let filteredTaskList = taskList;
Expand Down
56 changes: 51 additions & 5 deletions website/client/src/libs/store/helpers/filterTasks.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { shouldDo } from '@/../../common/script/cron';
import sortBy from 'lodash/sortBy';

// Task filter data
// @TODO find a way to include user preferences w.r.t sort and defaults
Expand All @@ -15,8 +15,8 @@ const taskFilters = {
label: 'dailies',
filters: [
{ label: 'all', filterFn: () => true, default: true },
{ label: 'due', filterFn: userPrefs => t => !t.completed && shouldDo(new Date(), t, userPrefs) },
{ label: 'notDue', filterFn: userPrefs => t => t.completed || !shouldDo(new Date(), t, userPrefs) },
{ label: 'due', filterFn: t => !t.completed && t.isDue },
{ label: 'notDue', filterFn: t => t.completed || !t.isDue },
],
},
todo: {
Expand All @@ -37,6 +37,34 @@ const taskFilters = {
},
};

const challengeFilters = {
habit: {
label: 'habits',
filters: [
{ label: 'all', filterFn: () => true, default: true },
],
},
daily: {
label: 'dailies',
filters: [
{ label: 'all', filterFn: () => true, default: true },
],
},
todo: {
label: 'todos',
filters: [
{ label: 'all', filterFn: () => true, default: true }, // active
{ label: 'scheduled', filterFn: t => t.date, sort: t => t.date },
],
},
reward: {
label: 'rewards',
filters: [
{ label: 'all', filterFn: () => true, default: true },
],
},
};

function typeLabel (filterList) {
return type => filterList[type].label;
}
Expand All @@ -53,7 +81,12 @@ function filterLabel (filterList) {
};
}

export const getFilterLabels = filterLabel(taskFilters);
export function getFilterLabels (type, isChallenge) {
if (isChallenge) {
return filterLabel(challengeFilters)(type);
}
return filterLabel(taskFilters)(type);
}

function activeFilter (filterList) {
return (type, filterType = '') => {
Expand All @@ -65,4 +98,17 @@ function activeFilter (filterList) {
};
}

export const getActiveFilter = activeFilter(taskFilters);
export function getActiveFilter (type, filterType, isChallenge) {
if (isChallenge) {
return activeFilter(challengeFilters)(type, filterType);
}
return activeFilter(taskFilters)(type, filterType);
}

export function sortAndFilterTasks (tasks, selectedFilter) {
let sortedTasks = tasks.filter(selectedFilter.filterFn);
if (selectedFilter.sort) {
sortedTasks = sortBy(sortedTasks, selectedFilter.sort);
}
return sortedTasks;
}
8 changes: 6 additions & 2 deletions website/client/src/store/actions/tasks.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios from 'axios';
import Vue from 'vue';
import compact from 'lodash/compact';
import omit from 'lodash/omit';
import { loadAsyncResource } from '@/libs/asyncResource';
Expand Down Expand Up @@ -103,8 +104,11 @@ export async function create (store, createdTask) {
const data = Array.isArray(response.data.data) ? response.data.data : [response.data.data];

data.forEach(taskRes => {
const taskData = store.state.tasks.data[`${taskRes.type}s`].find(t => t._id === taskRes._id);
Object.assign(taskData, taskRes);
const tasksArr = store.state.tasks.data[`${taskRes.type}s`];
const taskDataIndex = tasksArr.findIndex(t => t._id === taskRes._id);
if (taskDataIndex !== -1) {
Vue.set(tasksArr, taskDataIndex, { ...tasksArr[taskDataIndex], ...taskRes });
}
});
}

Expand Down
25 changes: 4 additions & 21 deletions website/client/src/store/getters/tasks.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import sortBy from 'lodash/sortBy';
import { shouldDo } from '@/../../common/script/cron';

// Library / Utility function
import { orderSingleTypeTasks } from '@/libs/store/helpers/orderTasks';
import { getActiveFilter } from '@/libs/store/helpers/filterTasks';
import { getActiveFilter, sortAndFilterTasks } from '@/libs/store/helpers/filterTasks';


// Return all the tags belonging to an user task
Expand Down Expand Up @@ -232,30 +231,14 @@ export function getFilteredTaskList ({ state, getters }) {
// check if task list has been passed as override props
// assumption: type will always be passed as param
let requestedTasks = getters['tasks:getUnfilteredTaskList'](type);

const userPreferences = state.user.data.preferences;
const selectedFilter = getActiveFilter(type, filterType);
const taskOrderForType = state.user.data.tasksOrder[type];

// order tasks based on user set task order
// Still needs unit test for this..
if (requestedTasks.length > 0 && ['scheduled', 'due'].indexOf(filterType.label) === -1) {
if (requestedTasks.length > 0 && !selectedFilter.sort) {
requestedTasks = orderSingleTypeTasks(requestedTasks, taskOrderForType);
}

let selectedFilter = getActiveFilter(type, filterType);
// Pass user preferences to the filter function which uses currying
if (type === 'daily' && (filterType === 'due' || filterType === 'notDue')) {
selectedFilter = {
...selectedFilter,
filterFn: selectedFilter.filterFn(userPreferences),
};
}

requestedTasks = requestedTasks.filter(selectedFilter.filterFn);
if (selectedFilter.sort) {
requestedTasks = sortBy(requestedTasks, selectedFilter.sort);
}

return requestedTasks;
return sortAndFilterTasks(requestedTasks, selectedFilter);
};
}

0 comments on commit 1b25d30

Please sign in to comment.