Revert "Task page : task filters (#9898)"

This reverts commit 9919faeed8.
This commit is contained in:
Matteo Pagliazzi
2018-02-22 12:28:24 +01:00
parent deaf7fee81
commit d5e4be85e9
9 changed files with 127 additions and 605 deletions

View File

@@ -1,127 +0,0 @@
// VueJS produces following warnings if the corresponding imports are not used
// [Vue warn]: You are using the runtime-only build of Vue where the template option is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
import Vue from 'vue/dist/vue';
import TaskColumn from 'client/components/tasks/column.vue';
describe('Task Column Component', () => {
let vm, Ctor, tasks;
describe('Task Filtering', () => {
beforeEach(() => {
Ctor = Vue.extend(TaskColumn);
vm = new Ctor({
propsData: {
type: 'habit',
},
}).$mount();
});
describe('by Tags', () => {
beforeEach(() => {
tasks = [
{ tags: [3, 4] },
{ tags: [2, 3] },
{ tags: [] },
{ tags: [1, 3] },
];
});
it('returns all tasks when given no tags', () => {
let returnedTasks = vm.filterByTagList(tasks);
expect(returnedTasks).to.have.lengthOf(tasks.length);
tasks.forEach((task, i) => {
expect(returnedTasks[i]).to.eq(task);
});
});
it('returns all tasks with given single tag', () => {
let returnedTasks = vm.filterByTagList(tasks, [3]);
expect(returnedTasks).to.have.lengthOf(3);
expect(returnedTasks[0]).to.eq(tasks[0]);
expect(returnedTasks[1]).to.eq(tasks[1]);
expect(returnedTasks[2]).to.eq(tasks[3]);
});
it('returns all tasks with given multiple tags', () => {
let returnedTasks = vm.filterByTagList(tasks, [2, 3]);
expect(returnedTasks).to.have.lengthOf(1);
expect(returnedTasks[0]).to.eq(tasks[1]);
});
});
describe('by Search Text', () => {
beforeEach(() => {
tasks = [
{
text: 'Hello world 1',
note: '',
checklist: [],
},
{
text: 'Hello world 2',
note: '',
checklist: [],
},
{
text: 'Generic Task Title',
note: '',
checklist: [
{ text: 'Check 1' },
{ text: 'Check 2' },
{ text: 'Check 3' },
],
},
{
text: 'Hello world 3',
note: 'Generic Task Note',
checklist: [
{ text: 'Checkitem 1' },
{ text: 'Checkitem 2' },
{ text: 'Checkitem 3' },
],
},
];
});
it('should return all tasks with empty search term', () => {
let returnedTasks = vm.filterBySearchText(tasks);
expect(returnedTasks).to.have.lengthOf(tasks.length);
tasks.forEach((task, i) => {
expect(returnedTasks[i]).to.eq(task);
});
});
it('should return tasks with search term in title /i', () => {
['Title', 'TITLE', 'title', 'tItLe'].forEach((term) => {
expect(vm.filterBySearchText(tasks, term)[0]).to.eq(tasks[2]);
});
});
it('should return tasks with search term in note /i', () => {
['Note', 'NOTE', 'note', 'nOtE'].forEach((term) => {
expect(vm.filterBySearchText(tasks, term)[0]).to.eq(tasks[3]);
});
});
it('should return tasks with search term in checklist title /i', () => {
['Check', 'CHECK', 'check', 'cHeCK'].forEach((term) => {
let returnedTasks = vm.filterBySearchText(tasks, term);
expect(returnedTasks[0]).to.eq(tasks[2]);
expect(returnedTasks[1]).to.eq(tasks[3]);
});
['Checkitem', 'CHECKITEM', 'checkitem', 'cHeCKiTEm'].forEach((term) => {
expect(vm.filterBySearchText(tasks, term)[0]).to.eq(tasks[3]);
});
});
});
afterEach(() => {
vm.$destroy();
});
});
});

View File

@@ -1,62 +0,0 @@
import {
getTypeLabel,
getFilterLabels,
getActiveFilter,
} from 'client/libs/store/helpers/filterTasks.js';
describe('Filter Category for Tasks', () => {
describe('getTypeLabel', () => {
it('should return correct task type labels', () => {
expect(getTypeLabel('habit')).to.eq('habits');
expect(getTypeLabel('daily')).to.eq('dailies');
expect(getTypeLabel('todo')).to.eq('todos');
expect(getTypeLabel('reward')).to.eq('rewards');
});
});
describe('getFilterLabels', () => {
let habit, daily, todo, reward;
beforeEach(() => {
habit = ['all', 'yellowred', 'greenblue'];
daily = ['all', 'due', 'notDue'];
todo = ['remaining', 'scheduled', 'complete2'];
reward = ['all', 'custom', 'wishlist'];
});
it('should return all task type filter labels by type', () => {
// habits
getFilterLabels('habit').forEach((item, i) => {
expect(item).to.eq(habit[i]);
});
// dailys
getFilterLabels('daily').forEach((item, i) => {
expect(item).to.eq(daily[i]);
});
// todos
getFilterLabels('todo').forEach((item, i) => {
expect(item).to.eq(todo[i]);
});
// rewards
getFilterLabels('reward').forEach((item, i) => {
expect(item).to.eq(reward[i]);
});
});
});
describe('getActiveFilter', () => {
it('should return single function by default', () => {
let activeFilter = getActiveFilter('habit');
expect(activeFilter).to.be.an('object');
expect(activeFilter).to.have.all.keys('label', 'filterFn', 'default');
expect(activeFilter.default).to.be.true;
});
it('should return single function for given filter type', () => {
let activeFilterLabel = 'yellowred';
let activeFilter = getActiveFilter('habit', activeFilterLabel);
expect(activeFilter).to.be.an('object');
expect(activeFilter).to.have.all.keys('label', 'filterFn');
expect(activeFilter.label).to.eq(activeFilterLabel);
});
});
});

View File

@@ -1,43 +0,0 @@
import {
orderSingleTypeTasks,
// orderMultipleTypeTasks,
} from 'client/libs/store/helpers/orderTasks.js';
import shuffle from 'lodash/shuffle';
describe('Task Order Helper Function', () => {
let tasks, shuffledTasks, taskOrderList;
beforeEach(() => {
taskOrderList = [1, 2, 3, 4];
tasks = [];
taskOrderList.forEach(i => tasks.push({ _id: i, id: i }));
shuffledTasks = shuffle(tasks);
});
it('should return tasks as is for no task order', () => {
expect(orderSingleTypeTasks(shuffledTasks)).to.eq(shuffledTasks);
});
it('should return tasks in expected order', () => {
let newOrderedTasks = orderSingleTypeTasks(shuffledTasks, taskOrderList);
newOrderedTasks.forEach((item, index) => {
expect(item).to.eq(tasks[index]);
});
});
it('should return new tasks at end of expected order', () => {
let newTaskIds = [10, 15, 20];
newTaskIds.forEach(i => tasks.push({ _id: i, id: i }));
shuffledTasks = shuffle(tasks);
let newOrderedTasks = orderSingleTypeTasks(shuffledTasks, taskOrderList);
// checking tasks with order
newOrderedTasks.slice(0, taskOrderList.length).forEach((item, index) => {
expect(item).to.eq(tasks[index]);
});
// check for new task ids
newOrderedTasks.slice(-3).forEach(item => {
expect(item.id).to.be.oneOf(newTaskIds);
});
});
});

View File

@@ -1,118 +0,0 @@
import generateStore from 'client/store';
describe('Store Getters for Tasks', () => {
let store, habits, dailys, todos, rewards;
beforeEach(() => {
store = generateStore();
// Get user preference data and user tasks order data
store.state.user.data = {
preferences: {},
tasksOrder: {
habits: [],
dailys: [],
todos: [],
rewards: [],
},
};
});
describe('Task List', () => {
beforeEach(() => {
habits = [
{ id: 1 },
{ id: 2 },
];
dailys = [
{ id: 3 },
{ id: 4 },
];
todos = [
{ id: 5 },
{ id: 6 },
];
rewards = [
{ id: 7 },
{ id: 8 },
];
store.state.tasks.data = {
habits,
dailys,
todos,
rewards,
};
});
it('should returns all tasks by task type', () => {
let returnedTasks = store.getters['tasks:getUnfilteredTaskList']('habit');
expect(returnedTasks).to.eq(habits);
returnedTasks = store.getters['tasks:getUnfilteredTaskList']('daily');
expect(returnedTasks).to.eq(dailys);
returnedTasks = store.getters['tasks:getUnfilteredTaskList']('todo');
expect(returnedTasks).to.eq(todos);
returnedTasks = store.getters['tasks:getUnfilteredTaskList']('reward');
expect(returnedTasks).to.eq(rewards);
});
});
// @TODO add task filter check for rewards and dailys
describe('Task Filters', () => {
beforeEach(() => {
habits = [
// weak habit
{ value: 0 },
// strong habit
{ value: 2 },
];
todos = [
// scheduled todos
{ completed: false, date: 'Mon, 15 Jan 2018 12:18:29 GMT' },
// completed todos
{ completed: true },
];
store.state.tasks.data = {
habits,
todos,
};
});
it('should return weak habits', () => {
let returnedTasks = store.getters['tasks:getFilteredTaskList']({
type: 'habit',
filterType: 'yellowred',
});
expect(returnedTasks[0]).to.eq(habits[0]);
});
it('should return strong habits', () => {
let returnedTasks = store.getters['tasks:getFilteredTaskList']({
type: 'habit',
filterType: 'greenblue',
});
expect(returnedTasks[0]).to.eq(habits[1]);
});
it('should return scheduled todos', () => {
let returnedTasks = store.getters['tasks:getFilteredTaskList']({
type: 'todo',
filterType: 'scheduled',
});
expect(returnedTasks[0]).to.eq(todos[0]);
});
it('should return completed todos', () => {
let returnedTasks = store.getters['tasks:getFilteredTaskList']({
type: 'todo',
filterType: 'complete2',
});
expect(returnedTasks[0]).to.eq(todos[1]);
});
});
});

View File

@@ -8,14 +8,14 @@
v-if='type === "reward"') v-if='type === "reward"')
.d-flex .d-flex
h2.tasks-column-title h2.tasks-column-title
| {{ $t(typeLabel) }} | {{ $t(types[type].label) }}
.badge.badge-pill.badge-purple.column-badge(v-if="badgeCount > 0") {{ badgeCount }} .badge.badge-pill.badge-purple.column-badge(v-if="badgeCount > 0") {{ badgeCount }}
.filters.d-flex.justify-content-end .filters.d-flex.justify-content-end
.filter.small-text( .filter.small-text(
v-for="filter in typeFilters", v-for="filter in types[type].filters",
:class="{active: activeFilter.label === filter}", :class="{active: activeFilters[type].label === filter.label}",
@click="activateFilter(type, filter)", @click="activateFilter(type, filter)",
) {{ $t(filter) }} ) {{ $t(filter.label) }}
.tasks-list(ref="tasksWrapper") .tasks-list(ref="tasksWrapper")
textarea.quick-add( textarea.quick-add(
:rows="quickAddRows", :rows="quickAddRows",
@@ -26,19 +26,19 @@
) )
transition(name="quick-add-tip-slide") transition(name="quick-add-tip-slide")
.quick-add-tip.small-text(v-show="quickAddFocused", v-html="$t('addMultipleTip')") .quick-add-tip.small-text(v-show="quickAddFocused", v-html="$t('addMultipleTip')")
clear-completed-todos(v-if="activeFilter.label === 'complete2'") clear-completed-todos(v-if="activeFilters[type].label === 'complete2'")
.column-background( .column-background(
v-if="isUser === true", v-if="isUser === true",
:class="{'initial-description': initialColumnDescription}", :class="{'initial-description': initialColumnDescription}",
ref="columnBackground", ref="columnBackground",
) )
.svg-icon(v-html="icons[type]", :class="`icon-${type}`", v-once) .svg-icon(v-html="icons[type]", :class="`icon-${type}`", v-once)
h3(v-once) {{$t('theseAreYourTasks', {taskType: $t(typeLabel)})}} h3(v-once) {{$t('theseAreYourTasks', {taskType: $t(types[type].label)})}}
.small-text {{$t(`${type}sDesc`)}} .small-text {{$t(`${type}sDesc`)}}
draggable.sortable-tasks( draggable.sortable-tasks(
ref="tasksList", ref="tasksList",
@update='sorted', @update='sorted',
:options='{disabled: activeFilter.label === "scheduled"}', :options='{disabled: activeFilters[type].label === "scheduled"}',
) )
task( task(
v-for="task in taskList", v-for="task in taskList",
@@ -245,10 +245,10 @@
<script> <script>
import Task from './task'; import Task from './task';
import ClearCompletedTodos from './clearCompletedTodos'; import ClearCompletedTodos from './clearCompletedTodos';
import sortBy from 'lodash/sortBy';
import throttle from 'lodash/throttle'; import throttle from 'lodash/throttle';
import isEmpty from 'lodash/isEmpty';
import buyMixin from 'client/mixins/buy'; import buyMixin from 'client/mixins/buy';
import { mapState, mapActions, mapGetters } from 'client/libs/store'; import { mapState, mapActions } from 'client/libs/store';
import shopItem from '../shops/shopItem'; import shopItem from '../shops/shopItem';
import BuyQuestModal from 'client/components/shops/quests/buyQuestModal.vue'; import BuyQuestModal from 'client/components/shops/quests/buyQuestModal.vue';
@@ -258,12 +258,6 @@ import inAppRewards from 'common/script/libs/inAppRewards';
import spells from 'common/script/content/spells'; import spells from 'common/script/content/spells';
import taskDefaults from 'common/script/libs/taskDefaults'; import taskDefaults from 'common/script/libs/taskDefaults';
import {
getTypeLabel,
getFilterLabels,
getActiveFilter,
} from 'client/libs/store/helpers/filterTasks.js';
import svgPin from 'assets/svg/pin.svg'; import svgPin from 'assets/svg/pin.svg';
import habitIcon from 'assets/svg/habit.svg'; import habitIcon from 'assets/svg/habit.svg';
import dailyIcon from 'assets/svg/daily.svg'; import dailyIcon from 'assets/svg/daily.svg';
@@ -282,6 +276,42 @@ export default {
}, },
props: ['type', 'isUser', 'searchText', 'selectedTags', 'taskListOverride', 'group'], // @TODO: maybe we should store the group on state? props: ['type', 'isUser', 'searchText', 'selectedTags', 'taskListOverride', 'group'], // @TODO: maybe we should store the group on state?
data () { data () {
// @TODO refactor this so that filter functions aren't in data
const types = Object.freeze({
habit: {
label: 'habits',
filters: [
{label: 'all', filter: () => true, default: true},
{label: 'yellowred', filter: t => t.value < 1}, // weak
{label: 'greenblue', filter: t => t.value >= 1}, // strong
],
},
daily: {
label: 'dailies',
filters: [
{label: 'all', filter: () => true, default: true},
{label: 'due', filter: t => !t.completed && shouldDo(new Date(), t, this.userPreferences)},
{label: 'notDue', filter: t => t.completed || !shouldDo(new Date(), t, this.userPreferences)},
],
},
todo: {
label: 'todos',
filters: [
{label: 'remaining', filter: t => !t.completed, default: true}, // active
{label: 'scheduled', filter: t => !t.completed && t.date, sort: t => t.date},
{label: 'complete2', filter: t => t.completed},
],
},
reward: {
label: 'rewards',
filters: [
{label: 'all', filter: () => true, default: true},
{label: 'custom', filter: () => true}, // all rewards made by the user
{label: 'wishlist', filter: () => false}, // not user tasks
],
},
});
const icons = Object.freeze({ const icons = Object.freeze({
habit: habitIcon, habit: habitIcon,
daily: dailyIcon, daily: dailyIcon,
@@ -290,15 +320,14 @@ export default {
pin: svgPin, pin: svgPin,
}); });
let typeLabel = ''; let activeFilters = {};
let typeFilters = []; for (let type in types) {
let activeFilter = {}; activeFilters[type] = types[type].filters.find(f => f.default === true);
}
return { return {
typeLabel, types,
typeFilters, activeFilters,
activeFilter,
icons, icons,
openedCompletedTodos: false, openedCompletedTodos: false,
@@ -310,38 +339,45 @@ export default {
selectedItemToBuy: {}, selectedItemToBuy: {},
}; };
}, },
created () {
// Set Task Column Label
this.typeLabel = getTypeLabel(this.type);
// Get Category Filter Labels
this.typeFilters = getFilterLabels(this.type);
// Set default filter for task column
this.activateFilter(this.type);
},
computed: { computed: {
...mapState({ ...mapState({
tasks: 'tasks.data',
user: 'user.data', user: 'user.data',
userPreferences: 'user.data.preferences',
}), }),
...mapGetters({ onUserPage () {
getFilteredTaskList: 'tasks:getFilteredTaskList', let onUserPage = Boolean(this.taskList.length) && (!this.taskListOverride || this.taskListOverride.length === 0);
getUnfilteredTaskList: 'tasks:getUnfilteredTaskList',
getUserPreferences: 'user:preferences', if (!onUserPage) {
getUserBuffs: 'user:buffs', this.activateFilter('daily', this.types.daily.filters[0]);
}), this.types.reward.filters = [];
}
return onUserPage;
},
taskList () { taskList () {
// @TODO: This should not default to user's tasks. It should require that you pass options in // @TODO: This should not default to user's tasks. It should require that you pass options in
const filter = this.activeFilters[this.type];
let filteredTaskList = isEmpty(this.taskListOverride) ? let taskList = this.tasks[`${this.type}s`];
this.getFilteredTaskList({ if (this.taskListOverride) taskList = this.taskListOverride;
type: this.type,
filterType: this.activeFilter.label,
}) :
this.taskListOverride;
let taggedList = this.filterByTagList(filteredTaskList, this.selectedTags); if (taskList.length > 0 && ['scheduled', 'due'].indexOf(filter.label) === -1) {
let searchedList = this.filterBySearchText(taggedList, this.searchText); let taskListSorted = this.$store.dispatch('tasks:order', [
taskList,
this.user.tasksOrder,
]);
return searchedList; taskList = taskListSorted[`${this.type}s`];
}
if (filter.sort) {
taskList = sortBy(taskList, filter.sort);
}
return taskList.filter(t => {
return this.filterTask(t);
});
}, },
inAppRewards () { inAppRewards () {
let watchRefresh = this.forceRefresh; // eslint-disable-line let watchRefresh = this.forceRefresh; // eslint-disable-line
@@ -357,7 +393,7 @@ export default {
}; };
for (let key in seasonalSkills) { for (let key in seasonalSkills) {
if (this.getUserBuffs(key)) { if (this.user.stats.buffs[key]) {
let debuff = seasonalSkills[key]; let debuff = seasonalSkills[key];
let item = Object.assign({}, spells.special[debuff]); let item = Object.assign({}, spells.special[debuff]);
item.text = item.text(); item.text = item.text();
@@ -370,7 +406,7 @@ export default {
return rewards; return rewards;
}, },
hasRewardsList () { hasRewardsList () {
return this.isUser === true && this.type === 'reward' && this.activeFilter.label !== 'custom'; return this.isUser === true && this.type === 'reward' && this.activeFilters[this.type].label !== 'custom';
}, },
initialColumnDescription () { initialColumnDescription () {
// Show the column description in the middle only if there are no elements (tasks or in app items) // Show the column description in the middle only if there are no elements (tasks or in app items)
@@ -378,12 +414,13 @@ export default {
if (this.inAppRewards && this.inAppRewards.length >= 0) return false; if (this.inAppRewards && this.inAppRewards.length >= 0) return false;
} }
return this.taskList.length === 0; return this.tasks[`${this.type}s`].length === 0;
}, },
dailyDueDefaultView () { dailyDueDefaultView () {
if (this.type === 'daily' && this.user.preferences.dailyDueDefaultView) { if (this.user.preferences.dailyDueDefaultView) {
this.activateFilter('daily', this.typeFilters[1]); this.activateFilter('daily', this.types.daily.filters[1]);
} }
return this.user.preferences.dailyDueDefaultView; return this.user.preferences.dailyDueDefaultView;
}, },
quickAddPlaceholder () { quickAddPlaceholder () {
@@ -394,14 +431,16 @@ export default {
// 0 means the badge will not be shown // 0 means the badge will not be shown
// It is shown for the all and due views of dailies // It is shown for the all and due views of dailies
// and for the active and scheduled views of todos. // and for the active and scheduled views of todos.
if (this.type === 'todo' && this.activeFilter.label !== 'complete2') { if (this.type === 'todo') {
return this.taskList.length; if (this.activeFilters.todo.label !== 'complete2') return this.taskList.length;
} else if (this.type === 'daily') { } else if (this.type === 'daily') {
if (this.activeFilter.label === 'due') { const activeFilter = this.activeFilters.daily.label;
if (activeFilter === 'due') {
return this.taskList.length; return this.taskList.length;
} else if (this.activeFilter.label === 'all') { } else if (activeFilter === 'all') {
return this.taskList.reduce((count, t) => { return this.taskList.reduce((count, t) => {
return !t.completed && shouldDo(new Date(), t, this.getUserPreferences) ? count + 1 : count; return !t.completed && shouldDo(new Date(), t, this.userPreferences) ? count + 1 : count;
}, 0); }, 0);
} }
} }
@@ -418,9 +457,7 @@ export default {
}, },
dailyDueDefaultView () { dailyDueDefaultView () {
if (!this.dailyDueDefaultView) return; if (!this.dailyDueDefaultView) return;
if (this.type === 'daily' && this.dailyDueDefaultView) { this.activateFilter('daily', this.types.daily.filters[1]);
this.activateFilter('daily', this.typeFilters[1]);
}
}, },
quickAddFocused (newValue) { quickAddFocused (newValue) {
if (newValue) this.quickAddRows = this.quickAddText.split('\n').length; if (newValue) this.quickAddRows = this.quickAddText.split('\n').length;
@@ -454,7 +491,7 @@ export default {
const filteredList = this.taskList; const filteredList = this.taskList;
const taskToMove = filteredList[data.oldIndex]; const taskToMove = filteredList[data.oldIndex];
const taskIdToMove = taskToMove._id; const taskIdToMove = taskToMove._id;
let originTasks = this.getUnfilteredTaskList(this.type); let originTasks = this.tasks[`${this.type}s`];
if (this.taskListOverride) originTasks = this.taskListOverride; if (this.taskListOverride) originTasks = this.taskListOverride;
// Server // Server
@@ -481,7 +518,7 @@ export default {
}, },
async moveTo (task, where) { // where is 'top' or 'bottom' async moveTo (task, where) { // where is 'top' or 'bottom'
const taskIdToMove = task._id; const taskIdToMove = task._id;
const list = this.getUnfilteredTaskList(this.type); const list = this.tasks[`${this.type}s`];
const oldPosition = list.findIndex(t => t._id === taskIdToMove); const oldPosition = list.findIndex(t => t._id === taskIdToMove);
const moved = list.splice(oldPosition, 1); const moved = list.splice(oldPosition, 1);
@@ -521,14 +558,12 @@ export default {
editTask (task) { editTask (task) {
this.$emit('editTask', task); this.$emit('editTask', task);
}, },
activateFilter (type, filter = '') { activateFilter (type, filter) {
// Needs a separate API call as this data may not reside in store if (type === 'todo' && filter.label === 'complete2') {
if (type === 'todo' && filter === 'complete2') {
this.loadCompletedTodos(); this.loadCompletedTodos();
} }
// this.activeFilters[type] = filter; this.activeFilters[type] = filter;
this.activeFilter = getActiveFilter(type, filter);
}, },
setColumnBackgroundVisibility () { setColumnBackgroundVisibility () {
this.$nextTick(() => { this.$nextTick(() => {
@@ -556,36 +591,35 @@ export default {
} }
}); });
}, },
filterByTagList (taskList, tagList = []) { filterTask (task) {
let filteredTaskList = taskList; // View
// fitler requested tasks by tags if (!this.activeFilters[task.type].filter(task)) return false;
if (!isEmpty(tagList)) {
filteredTaskList = taskList.filter( // Tags
task => tagList.every(tag => task.tags.indexOf(tag) !== -1) const selectedTags = this.selectedTags;
);
if (selectedTags && selectedTags.length > 0) {
const hasAllSelectedTag = selectedTags.every(tagId => {
return task.tags.indexOf(tagId) !== -1;
});
if (!hasAllSelectedTag) return false;
} }
return filteredTaskList;
}, // Text
filterBySearchText (taskList, searchText = '') { const searchText = this.searchText;
let filteredTaskList = taskList;
// filter requested tasks by search text if (!searchText) return true;
if (searchText) { if (task.text.toLowerCase().indexOf(searchText) !== -1) return true;
// to ensure broadest case insensitive search matching if (task.notes.toLowerCase().indexOf(searchText) !== -1) return true;
let searchTextLowerCase = searchText.toLowerCase();
filteredTaskList = taskList.filter( if (task.checklist && task.checklist.length) {
task => { const checklistItemIndex = task.checklist.findIndex(({text}) => {
// eslint rule disabled for block to allow nested binary expression return text.toLowerCase().indexOf(searchText) !== -1;
/* eslint-disable no-extra-parens */ });
return (
task.text.toLowerCase().indexOf(searchTextLowerCase) > -1 || return checklistItemIndex !== -1;
(task.note && task.note.toLowerCase().indexOf(searchTextLowerCase) > -1) ||
(task.checklist && task.checklist.length > 0 &&
task.checklist.some(checkItem => checkItem.text.toLowerCase().indexOf(searchTextLowerCase) > -1))
);
/* eslint-enable no-extra-parens */
});
} }
return filteredTaskList;
}, },
openBuyDialog (rewardItem) { openBuyDialog (rewardItem) {
if (rewardItem.locked) return; if (rewardItem.locked) return;

View File

@@ -1,68 +0,0 @@
import { shouldDo } from 'common/script/cron';
// Task filter data
// @TODO find a way to include user preferences w.r.t sort and defaults
const taskFilters = {
habit: {
label: 'habits',
filters: [
{ label: 'all', filterFn: () => true, default: true },
{ label: 'yellowred', filterFn: t => t.value < 1 }, // weak
{ label: 'greenblue', filterFn: t => t.value >= 1 }, // strong
],
},
daily: {
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) },
],
},
todo: {
label: 'todos',
filters: [
{ label: 'remaining', filterFn: t => !t.completed, default: true }, // active
{ label: 'scheduled', filterFn: t => !t.completed && t.date, sort: t => t.date },
{ label: 'complete2', filterFn: t => t.completed },
],
},
reward: {
label: 'rewards',
filters: [
{ label: 'all', filterFn: () => true, default: true },
{ label: 'custom', filterFn: () => true }, // all rewards made by the user
{ label: 'wishlist', filterFn: () => false }, // not user tasks
],
},
};
function typeLabel (filterList) {
return (type) => filterList[type].label;
}
export const getTypeLabel = typeLabel(taskFilters);
function filterLabel (filterList) {
return (type) => {
let filterListByType = filterList[type].filters;
let filterListOfLabels = new Array(filterListByType.length);
filterListByType.forEach(({ label }, i) => filterListOfLabels[i] = label);
return filterListOfLabels;
};
}
export const getFilterLabels = filterLabel(taskFilters);
function activeFilter (filterList) {
return (type, filterType = '') => {
let filterListByType = filterList[type].filters;
if (filterType) {
return filterListByType.find(f => f.label === filterType);
}
return filterListByType.find(f => f.default === true);
};
}
export const getActiveFilter = activeFilter(taskFilters);

View File

@@ -1,31 +0,0 @@
import compact from 'lodash/compact';
// sets task order for single task type only.
// Accepts task list and corresponding taskorder for its task type.
export function orderSingleTypeTasks (rawTasks, taskOrder) {
// if there is no predefined task order return task list as is.
if (!taskOrder) return rawTasks;
const orderedTasks = new Array(rawTasks.length);
const unorderedTasks = []; // What we want to add later
rawTasks.forEach((task, index) => {
const taskId = task._id;
const i = taskOrder[index] === taskId ? index : taskOrder.indexOf(taskId);
if (i === -1) {
unorderedTasks.push(task);
} else {
orderedTasks[i] = task;
}
});
return compact(orderedTasks).concat(unorderedTasks);
}
export function orderMultipleTypeTasks (rawTasks, tasksOrder) {
return {
habits: orderSingleTypeTasks(rawTasks.habits, tasksOrder.habits),
dailys: orderSingleTypeTasks(rawTasks.dailys, tasksOrder.dailys),
todos: orderSingleTypeTasks(rawTasks.todos, tasksOrder.todos),
rewards: orderSingleTypeTasks(rawTasks.rewards, tasksOrder.rewards),
};
}

View File

@@ -1,11 +1,5 @@
import { shouldDo } from 'common/script/cron'; import { shouldDo } from 'common/script/cron';
// Library / Utility function
import { orderSingleTypeTasks } from 'client/libs/store/helpers/orderTasks.js';
import { getActiveFilter } from 'client/libs/store/helpers/filterTasks.js';
import sortBy from 'lodash/sortBy';
// Return all the tags belonging to an user task // Return all the tags belonging to an user task
export function getTagsFor (store) { export function getTagsFor (store) {
return (task) => { return (task) => {
@@ -115,48 +109,3 @@ export function getTaskClasses (store) {
} }
}; };
} }
// Returns all list for given task type
export function getUnfilteredTaskList ({state}) {
return (type) => state.tasks.data[`${type}s`];
}
// Returns filtered, sorted, ordered, tag filtered, and search filtered task list
// @TODO: sort task list based on used preferences
export function getFilteredTaskList ({state, getters}) {
return ({
type,
filterType = '',
}) => {
// get requested tasks
// check if task list has been passed as override props
// assumption: type will always be passed as param
let requestedTasks = getters['tasks:getUnfilteredTaskList'](type);
let userPreferences = state.user.data.preferences;
let 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) {
requestedTasks = orderSingleTypeTasks(requestedTasks, taskOrderForType);
}
// filter requested tasks by filter type
let selectedFilter = getActiveFilter(type, filterType);
// @TODO find a way (probably thru currying) to implicitly pass user preference data to task filters
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;
};
}

View File

@@ -4,16 +4,4 @@ export function data (store) {
export function gems (store) { export function gems (store) {
return store.state.user.data.balance * 4; return store.state.user.data.balance * 4;
}
export function buffs (store) {
return (key) => store.state.user.data.stats.buffs[key];
}
export function preferences (store) {
return store.state.user.data.preferences;
}
export function tasksOrder (store) {
return (type) => store.state.user.tasksOrder[`${type}s`];
} }