Frontend logic for filters
This commit is contained in:
parent
bb479c45ef
commit
c725d5154e
|
@ -0,0 +1,62 @@
|
|||
import api, { processError } from '$lib/utils/api';
|
||||
import status from '$lib/utils/status';
|
||||
|
||||
async function create(
|
||||
viewId: number,
|
||||
projectTagId: number,
|
||||
filterType: number,
|
||||
tagOptionId: number
|
||||
): Promise<number | null> {
|
||||
const response = await api.post(`/v1/filters`, {
|
||||
view_id: viewId,
|
||||
tag_id: projectTagId,
|
||||
filter_type: filterType,
|
||||
option_id: tagOptionId
|
||||
});
|
||||
|
||||
if (response.status !== status.Created) {
|
||||
processError(response, 'Failed to create filter');
|
||||
return null;
|
||||
}
|
||||
|
||||
return response.data.id;
|
||||
}
|
||||
|
||||
async function update(
|
||||
filterId: number,
|
||||
viewId: number,
|
||||
projectTagId: number,
|
||||
filterType: number,
|
||||
tagOptionId: number
|
||||
): Promise<boolean> {
|
||||
const response = await api.put(`/v1/filters/${filterId}`, {
|
||||
view_id: viewId,
|
||||
tag_id: projectTagId,
|
||||
filter_type: filterType,
|
||||
option_id: tagOptionId
|
||||
});
|
||||
|
||||
if (response.status !== status.NoContent) {
|
||||
processError(response, 'Failed to update filter');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async function delete_(filterId: number): Promise<boolean> {
|
||||
const response = await api.delete(`/v1/filters/${filterId}`);
|
||||
|
||||
if (response.status !== status.NoContent) {
|
||||
processError(response, 'Failed to delete filter');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default {
|
||||
create,
|
||||
update,
|
||||
delete: delete_
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
import Filter from '$lib/types/Filter';
|
||||
import type Project from '$lib/types/Project';
|
||||
import type View from '$lib/types/View';
|
||||
import api, { processError } from '$lib/utils/api';
|
||||
import status from '$lib/utils/status';
|
||||
|
||||
|
@ -53,8 +53,20 @@ async function delete_(viewId: number): Promise<boolean> {
|
|||
return true;
|
||||
}
|
||||
|
||||
async function getFilters(viewId: number): Promise<Filter[]> {
|
||||
const response = await api.get(`/v1/views/${viewId}/filters`);
|
||||
|
||||
if (response.status !== status.OK) {
|
||||
processError(response, 'Failed to get view filters');
|
||||
return [];
|
||||
}
|
||||
|
||||
return Filter.parseAll(response.data);
|
||||
}
|
||||
|
||||
export default {
|
||||
create,
|
||||
update,
|
||||
delete: delete_
|
||||
delete: delete_,
|
||||
getFilters
|
||||
};
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
import { writable } from 'svelte/store';
|
||||
import View from './View';
|
||||
import ProjectTag from './ProjectTag';
|
||||
import TagOption from './TagOption';
|
||||
import { toastAlert } from '$lib/utils/toasts';
|
||||
import filtersApi from '$lib/api/filtersApi';
|
||||
|
||||
export default class Filter {
|
||||
private _id: number;
|
||||
private _view: View;
|
||||
private _projectTag: ProjectTag;
|
||||
private _filterType: number;
|
||||
private _tagOption: TagOption;
|
||||
|
||||
private constructor(
|
||||
id: number,
|
||||
view: View,
|
||||
projectTag: ProjectTag,
|
||||
filterType: number,
|
||||
tagOption: TagOption
|
||||
) {
|
||||
this._id = id;
|
||||
this._view = view;
|
||||
this._projectTag = projectTag;
|
||||
this._filterType = filterType;
|
||||
this._tagOption = tagOption;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get view(): View {
|
||||
return this._view;
|
||||
}
|
||||
|
||||
get projectTag(): ProjectTag {
|
||||
return this._projectTag;
|
||||
}
|
||||
|
||||
get filterType(): number {
|
||||
return this._filterType;
|
||||
}
|
||||
|
||||
get tagOption(): TagOption {
|
||||
return this._tagOption;
|
||||
}
|
||||
|
||||
static async create(
|
||||
view: View,
|
||||
projectTag: ProjectTag,
|
||||
filterType: number,
|
||||
tagOption: TagOption
|
||||
): Promise<Filter | null> {
|
||||
const id = await filtersApi.create(view.id, projectTag.id, filterType, tagOption.id);
|
||||
if (!id) return null;
|
||||
|
||||
return new Filter(id, view, projectTag, filterType, tagOption);
|
||||
}
|
||||
|
||||
async delete(): Promise<boolean> {
|
||||
return await filtersApi.delete(this.id);
|
||||
}
|
||||
|
||||
static parseAll(json: any): Filter[];
|
||||
static parseAll(json: any, view: View | null): Filter[];
|
||||
|
||||
static parseAll(json: any[], view?: View | null): Filter[] {
|
||||
if (!json) return [];
|
||||
|
||||
const filters: Filter[] = [];
|
||||
|
||||
for (const filter of json) {
|
||||
const parsed = Filter.parse(filter, view);
|
||||
if (parsed) filters.push(parsed);
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
static parse(json: any): Filter | null;
|
||||
static parse(json: any, view: View | null | undefined): Filter | null;
|
||||
|
||||
static parse(json: any, view?: View | null | undefined): Filter | null {
|
||||
if (!json) {
|
||||
toastAlert('Failed to parse filter: json is null');
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!view) view = View.fromId(json.view_id);
|
||||
if (!view) {
|
||||
toastAlert('Failed to parse filter: view not found');
|
||||
return null;
|
||||
}
|
||||
|
||||
const projectTag = ProjectTag.fromId(json.tag_id);
|
||||
if (!projectTag) {
|
||||
toastAlert('Failed to parse filter: projectTag not found');
|
||||
return null;
|
||||
}
|
||||
|
||||
const tagOption = projectTag.options.find((option) => option.id === json.option_id);
|
||||
if (!tagOption) {
|
||||
toastAlert('Failed to parse filter: tagOption not found');
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Filter(json.id, view, projectTag, json.filter_type, tagOption);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
import { writable } from 'svelte/store';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import Project from './Project';
|
||||
import ProjectTag from './ProjectTag';
|
||||
import viewsApi from '$lib/api/viewsApi';
|
||||
import { toastAlert } from '$lib/utils/toasts';
|
||||
import Filter from './Filter';
|
||||
import type TagOption from './TagOption';
|
||||
|
||||
export const views = writable([] as View[]);
|
||||
|
||||
|
@ -14,6 +16,7 @@ export default class View {
|
|||
private _title: string;
|
||||
private _sortTag: ProjectTag | null;
|
||||
private _sortDirection: number | null;
|
||||
private _filters: Filter[];
|
||||
|
||||
private constructor(
|
||||
id: number,
|
||||
|
@ -22,7 +25,8 @@ export default class View {
|
|||
secondaryTag: ProjectTag | null,
|
||||
title: string,
|
||||
sortTag: ProjectTag | null,
|
||||
sortDirection: number | null
|
||||
sortDirection: number | null,
|
||||
filters: Filter[]
|
||||
) {
|
||||
this._id = id;
|
||||
this._project = project;
|
||||
|
@ -31,6 +35,7 @@ export default class View {
|
|||
this._title = title;
|
||||
this._sortTag = sortTag;
|
||||
this._sortDirection = sortDirection;
|
||||
this._filters = filters;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
|
@ -61,6 +66,16 @@ export default class View {
|
|||
return this._sortDirection;
|
||||
}
|
||||
|
||||
static fromId(id: number): View | null {
|
||||
for (const view of get(views)) {
|
||||
if (view.id === id) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async setPrimaryTag(projectTag: ProjectTag): Promise<boolean> {
|
||||
const response = await viewsApi.update(
|
||||
this.id,
|
||||
|
@ -103,7 +118,7 @@ export default class View {
|
|||
|
||||
if (!id) return null;
|
||||
|
||||
const view = new View(id, project, null, null, 'New view', null, null);
|
||||
const view = new View(id, project, null, null, 'New view', null, null, []);
|
||||
|
||||
views.update((views) => [...views, view]);
|
||||
|
||||
|
@ -137,6 +152,23 @@ export default class View {
|
|||
return true;
|
||||
}
|
||||
|
||||
async addFilter(projectTag: ProjectTag, filterType: number, option: TagOption): Promise<boolean> {
|
||||
const filter = await Filter.create(this, projectTag, filterType, option);
|
||||
if (!filter) return false;
|
||||
|
||||
this._filters = [...this._filters, filter];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async removeFilter(filter: Filter): Promise<boolean> {
|
||||
if (!(await filter.delete())) return false;
|
||||
|
||||
this._filters = this._filters.filter((f) => f.id !== filter.id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static parse(json: any): View | null;
|
||||
static parse(json: any, project: Project | null | undefined): View | null;
|
||||
|
||||
|
@ -163,9 +195,12 @@ export default class View {
|
|||
secondaryTag,
|
||||
json.title,
|
||||
sortTag,
|
||||
json.sort_direction
|
||||
json.sort_direction,
|
||||
[]
|
||||
);
|
||||
|
||||
view._filters = Filter.parseAll(json.filters, view);
|
||||
|
||||
views.update((views) => {
|
||||
if (!views.find((view) => view.id === json.id)) {
|
||||
return [...views, view];
|
||||
|
|
Loading…
Reference in New Issue