Rudimentary searching
This commit is contained in:
@@ -56,12 +56,10 @@
|
||||
emit-value
|
||||
map-options
|
||||
input-debounce="250"
|
||||
@new-value="addTag"
|
||||
:options="skillTagOptions"
|
||||
option-label="name"
|
||||
option-value="$id"
|
||||
@filter="filterSkillTags"
|
||||
new-value-mode="add-unique"
|
||||
>
|
||||
</q-select>
|
||||
</div>
|
||||
@@ -159,7 +157,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, Ref } from 'vue';
|
||||
import { computed, reactive, ref, Ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useTaskStore, TASKSTATUS } from 'src/stores/task';
|
||||
import type { TaskTag, SkillTag, Task } from 'src/stores/task';
|
||||
@@ -194,24 +192,33 @@ const boatList = ref<Boat[]>(useBoatStore().boats);
|
||||
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
|
||||
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
|
||||
|
||||
function filterSkillTags(val: string, update: (cb: () => void) => void): void {
|
||||
return filterTags(skillTagOptions, taskStore.skillTags, val, update);
|
||||
}
|
||||
function filterTaskTags(val: string, update: (cb: () => void) => void): void {
|
||||
return filterTags(taskTagOptions, taskStore.taskTags, val, update);
|
||||
}
|
||||
function filterTasks(val: string, update: (cb: () => void) => void): void {
|
||||
if (val === '') {
|
||||
update(() => {
|
||||
tasks = taskStore.tasks;
|
||||
});
|
||||
return;
|
||||
}
|
||||
const filterSkillTags = computed(
|
||||
() =>
|
||||
(val: string, update: (cb: () => void) => void): void => {
|
||||
return filterTags(skillTagOptions, taskStore.skillTags, val, update);
|
||||
}
|
||||
);
|
||||
const filterTaskTags = computed(
|
||||
() =>
|
||||
(val: string, update: (cb: () => void) => void): void => {
|
||||
return filterTags(taskTagOptions, taskStore.taskTags, val, update);
|
||||
}
|
||||
);
|
||||
const filterTasks = computed(
|
||||
() =>
|
||||
(val: string, update: (cb: () => void) => void): void => {
|
||||
if (val === '') {
|
||||
update(() => {
|
||||
tasks = taskStore.tasks;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
update(() => {
|
||||
tasks = taskStore.filterTasksByTitle(val);
|
||||
});
|
||||
}
|
||||
update(() => {
|
||||
tasks = taskStore.filterTasksByTitle(val);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
function filterTags(
|
||||
optionVar: Ref<(SkillTag | TaskTag)[] | undefined>,
|
||||
@@ -233,9 +240,6 @@ function filterTags(
|
||||
});
|
||||
}
|
||||
|
||||
function addTag(tag: string) {
|
||||
return;
|
||||
}
|
||||
// Method to update the model in ISO 8601 format
|
||||
const updateDateISO = (value: string) => {
|
||||
modifiedTask.due_date = date.formatDate(value, 'YYYY-MM-DD');
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<q-table
|
||||
:rows="tasks"
|
||||
:columns="columns"
|
||||
:grid="$q.screen.xs"
|
||||
dense
|
||||
row-key="$id"
|
||||
flatten
|
||||
@@ -11,7 +12,7 @@
|
||||
selection="multiple"
|
||||
v-model:selected="selected"
|
||||
:filter="searchFilter"
|
||||
:filter-method="filterByTitle"
|
||||
:filter-method="filterRows"
|
||||
@row-click="onRowClick"
|
||||
>
|
||||
<template v-slot:top>
|
||||
@@ -30,7 +31,42 @@
|
||||
@click="deleteTasks"
|
||||
/>
|
||||
<q-space />
|
||||
<q-input flatten debounce="300" color="primary" v-model="searchFilter">
|
||||
<q-select
|
||||
style="width: 250px"
|
||||
multiple
|
||||
use-chips
|
||||
clearable
|
||||
label="Skills Filter"
|
||||
input-debounce="250"
|
||||
:options="skillTagOptions"
|
||||
v-model="searchFilter.skillTags"
|
||||
option-label="name"
|
||||
option-value="$id"
|
||||
>
|
||||
</q-select>
|
||||
<q-select
|
||||
style="width: 250px"
|
||||
multiple
|
||||
use-chips
|
||||
clearable
|
||||
label="Tag Filter"
|
||||
input-debounce="250"
|
||||
:options="taskTagOptions"
|
||||
v-model="searchFilter.taskTags"
|
||||
option-label="name"
|
||||
option-value="$id"
|
||||
>
|
||||
<template v-slot: prepend>
|
||||
<q-icon name="wrench"></q-icon>
|
||||
</template>
|
||||
</q-select>
|
||||
<q-space />
|
||||
<q-input
|
||||
flatten
|
||||
debounce="300"
|
||||
color="primary"
|
||||
v-model="searchFilter.title"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<q-icon name="search" />
|
||||
</template>
|
||||
@@ -75,8 +111,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, ref } from 'vue';
|
||||
import { useTaskStore, Task } from 'src/stores/task';
|
||||
import { computed, defineProps, ref } from 'vue';
|
||||
import { useTaskStore, Task, SkillTag, TaskTag } from 'src/stores/task';
|
||||
import { QTableProps, date, useQuasar } from 'quasar';
|
||||
import { useBoatStore } from 'src/stores/boat';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -129,7 +165,7 @@ const columns = <QTableProps['columns']>[
|
||||
label: 'Boat',
|
||||
field: (row) =>
|
||||
useBoatStore().boats.find((boat) => boat.$id === row.boat)?.name,
|
||||
sortable: false,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: 'volunteers',
|
||||
@@ -164,27 +200,45 @@ const columns = <QTableProps['columns']>[
|
||||
|
||||
const props = defineProps<{ tasks: Task[] }>();
|
||||
const taskStore = useTaskStore();
|
||||
const searchFilter = ref('');
|
||||
const $q = useQuasar();
|
||||
|
||||
const searchFilter = ref({
|
||||
title: '',
|
||||
skillTags: <SkillTag[]>[],
|
||||
taskTags: <TaskTag[]>[],
|
||||
});
|
||||
|
||||
const skillTagOptions = ref<SkillTag[]>(taskStore.skillTags);
|
||||
const taskTagOptions = ref<TaskTag[]>(taskStore.taskTags);
|
||||
|
||||
function onRowClick(evt: Event, row: Task) {
|
||||
console.log(row);
|
||||
router.push({ name: 'edit-task', params: { id: row.$id } });
|
||||
}
|
||||
|
||||
const filterByTitle = (
|
||||
rows: readonly Task[],
|
||||
terms: any,
|
||||
cols: any,
|
||||
cellValueFn: any
|
||||
) => {
|
||||
console.log(terms);
|
||||
return terms
|
||||
? rows.filter((row) =>
|
||||
row.title.toLowerCase().includes(terms.toLowerCase())
|
||||
)
|
||||
: rows;
|
||||
};
|
||||
// TODO: Implement server side search
|
||||
const filterRows = computed(
|
||||
() => (rows: readonly Task[], terms: any, cols: any, cellValueFn: any) => {
|
||||
let result = rows;
|
||||
result = rows.filter((row) =>
|
||||
terms.title
|
||||
? row.title.toLowerCase().includes(terms.title.toLowerCase())
|
||||
: true
|
||||
);
|
||||
result = result.filter((row) =>
|
||||
terms.skillTags.length > 0
|
||||
? row.required_skills.some((req_skill) =>
|
||||
terms.skillTags.map((t) => t.$id).includes(req_skill)
|
||||
)
|
||||
: true
|
||||
);
|
||||
result = result.filter((row) =>
|
||||
terms.taskTags.length > 0
|
||||
? row.tags.some((tag) => terms.taskTags.map((t) => t.$id).includes(tag))
|
||||
: true
|
||||
);
|
||||
return result;
|
||||
}
|
||||
);
|
||||
|
||||
function deleteTasks() {
|
||||
confirmDelete(selected.value);
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<template>
|
||||
<toolbar-component pageTitle="Tasks" />
|
||||
<q-page padding>
|
||||
<TaskListComponent v-if="$q.screen.lt.sm" :tasks="taskStore.tasks" />
|
||||
<TaskTableComponent v-else :tasks="taskStore.tasks" />
|
||||
<TaskTableComponent :tasks="taskStore.tasks" />
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTaskStore } from 'stores/task';
|
||||
import ToolbarComponent from 'src/components/ToolbarComponent.vue';
|
||||
import TaskListComponent from 'src/components/task/TaskListComponent.vue';
|
||||
import TaskTableComponent from 'src/components/task/TaskTableComponent.vue';
|
||||
|
||||
const taskStore = useTaskStore();
|
||||
|
||||
Reference in New Issue
Block a user