Real-time sync for filters, projectTagOption, projectTag

This commit is contained in:
Brieuc Dubois 2024-01-23 15:31:06 +01:00
parent 74e191c94d
commit 77a0c33c18
5 changed files with 146 additions and 11 deletions

View File

@ -150,4 +150,20 @@ export default class Filter {
return new Filter(json.id, view, projectTag, json.filter_type, tagOption || null); return new Filter(json.id, view, projectTag, json.filter_type, tagOption || null);
} }
parseUpdate(changes: any) {
if (changes.tag_id) {
const projectTag = ProjectTag.fromId(changes.tag_id);
if (projectTag) this._projectTag = projectTag;
}
if (changes.filter_type) {
this._filterType = changes.filter_type;
}
if (changes.option_id) {
this._tagOption =
this.projectTag.options.find((option) => option.id === changes.option_id) || null;
}
}
} }

View File

@ -1,9 +1,9 @@
// import type TagOption from './TagOption'; // import type TagOption from './TagOption';
import { get, writable } from 'svelte/store';
import TagOption from './TagOption';
import Project from './Project';
import projectTagsApi from '$lib/api/projectTagsApi'; import projectTagsApi from '$lib/api/projectTagsApi';
import { get, writable } from 'svelte/store';
import Project from './Project';
import TagOption from './TagOption';
const { subscribe, update, set } = writable([] as ProjectTag[]); const { subscribe, update, set } = writable([] as ProjectTag[]);
@ -149,4 +149,37 @@ export default class ProjectTag {
return projectTags; return projectTags;
} }
static parseDelete(id: number) {
projectTags.update((projectTags) => projectTags.filter((projectTag) => projectTag.id !== id));
}
parseUpdate(json: any) {
if (!json) return;
if (json.title) this._title = json.title;
if (json.type) this._type = json.type;
}
parseOption(json: any) {
if (!json) return;
const option = TagOption.parse(json, this);
if (!option) return;
this._options = [...this._options, option];
}
parseOptionDelete(id: number) {
this._options = this._options.filter((option) => option.id !== id);
}
parseOptionUpdate(json: any) {
if (!json) return;
const option = this._options.find((option) => option.id === json.id);
if (!option) return;
option.parseUpdate(json);
}
} }

View File

@ -73,4 +73,8 @@ export default class TagOption {
return options; return options;
} }
parseUpdate(dict: any) {
if (dict.value) this._value = dict.value;
}
} }

View File

@ -1,11 +1,11 @@
import viewsApi from '$lib/api/viewsApi';
import currentView from '$lib/stores/currentView';
import { toastAlert } from '$lib/utils/toasts';
import { get, writable } from 'svelte/store'; import { get, writable } from 'svelte/store';
import Filter from './Filter';
import Project from './Project'; import Project from './Project';
import ProjectTag from './ProjectTag'; 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'; import type TagOption from './TagOption';
import currentView from '$lib/stores/currentView';
const { subscribe, set, update } = writable([] as View[]); const { subscribe, set, update } = writable([] as View[]);
@ -284,4 +284,24 @@ export default class View {
return views; return views;
} }
parseFilter(json: any) {
const filter = Filter.parse(json, this);
if (!filter) return;
this._filters = [...this._filters, filter];
}
parseFilterUpdate(json: any) {
const filter = this._filters.find((f) => f.id === json.id);
if (!filter) return;
filter.parseUpdate(json);
}
parseFilterDelete(id: number) {
this._filters = this._filters.filter((f) => f.id !== id);
}
} }

View File

@ -1,11 +1,9 @@
import Card, { cards } from '$lib/types/Card'; import Card, { cards } from '$lib/types/Card';
import CardTag from '$lib/types/CardTag';
import Project, { projects } from '$lib/types/Project'; import Project, { projects } from '$lib/types/Project';
import ProjectTag, { projectTags } from '$lib/types/ProjectTag'; import ProjectTag, { projectTags } from '$lib/types/ProjectTag';
import View, { views } from '$lib/types/View'; import View, { views } from '$lib/types/View';
import { getBackendWsUrl, hasPendingRequests, randomID } from '$lib/utils/api'; import { getBackendWsUrl, hasPendingRequests, randomID } from '$lib/utils/api';
import { toastAlert, toastWarning } from '$lib/utils/toasts'; import { toastAlert, toastWarning } from '$lib/utils/toasts';
import { get } from 'svelte/store';
export default class WebSocketManager { export default class WebSocketManager {
_socket: WebSocket | null; _socket: WebSocket | null;
@ -95,6 +93,7 @@ function applyMessage(data: any) {
else if (data.object === 'card') applyCard(data); else if (data.object === 'card') applyCard(data);
else if (data.object === 'view') applyView(data); else if (data.object === 'view') applyView(data);
else if (data.object === 'projectTag') applyProjectTag(data); else if (data.object === 'projectTag') applyProjectTag(data);
else if (data.object === 'tagOption') applyProjectTagOption(data);
else if (data.object === 'filter') applyFilter(data); else if (data.object === 'filter') applyFilter(data);
else toastWarning('Failed to parse WebSocket message: unknown object'); else toastWarning('Failed to parse WebSocket message: unknown object');
} }
@ -195,6 +194,69 @@ function applyView(data: any) {
views.reload(view); views.reload(view);
} }
function applyProjectTag(data: any) {} function applyProjectTag(data: any) {
if (data.action === 'create') {
ProjectTag.parse(data.data);
return;
}
if (data.action === 'delete') {
ProjectTag.parseDelete(data.id);
return;
}
function applyFilter(data: any) {} if (data.action !== 'update') {
toastWarning('Failed to parse project tag update: unknown action');
return;
}
const projectTag = ProjectTag.fromId(data.id);
if (!projectTag) {
toastWarning('Failed to parse project tag update: project tag not found');
return;
}
projectTag.parseUpdate(data.changes);
projectTags.reload();
}
function applyProjectTagOption(data: any) {
const projectTag = ProjectTag.fromId(data.project_tag_id);
if (!projectTag) {
toastWarning('Failed to parse project tag option update: project tag not found');
return;
}
if (data.action === 'create') {
projectTag.parseOption(data.data);
} else if (data.action === 'update') {
projectTag.parseOptionUpdate(data.changes);
} else if (data.action === 'delete') {
projectTag.parseOptionDelete(data.id);
} else {
toastWarning('Failed to parse project tag option update: unknown action');
return;
}
projectTags.reload();
}
function applyFilter(data: any) {
const view = View.fromId(data.view_id);
if (!view) {
toastWarning('Failed to parse filter update: view not found');
return;
}
if (data.action === 'create') {
view.parseFilter(data.data);
} else if (data.action === 'update') {
view.parseFilterUpdate(data.changes);
} else if (data.action === 'delete') {
view.parseFilterDelete(data.id);
} else {
toastWarning('Failed to parse filter update: unknown action');
return;
}
views.reload(view);
}