Real-time sync for projects, cards & cardstags
This commit is contained in:
parent
1991f26322
commit
2fd7134b68
|
@ -78,8 +78,9 @@ func CreateCardTag(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "cardtag",
|
"object": "cardTag",
|
||||||
"action": "create",
|
"action": "create",
|
||||||
|
"card_id": cardID,
|
||||||
"data": cardtag,
|
"data": cardtag,
|
||||||
"X-Request-Source": source,
|
"X-Request-Source": source,
|
||||||
});
|
});
|
||||||
|
@ -172,9 +173,10 @@ func DeleteCardTag(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "cardtag",
|
"object": "cardTag",
|
||||||
"action": "delete",
|
"action": "delete",
|
||||||
"id": cardID,
|
"card_id": cardID,
|
||||||
|
"tag_id": tagID,
|
||||||
"X-Request-Source": source,
|
"X-Request-Source": source,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -272,7 +274,7 @@ func UpdateCardTag(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "cardtag",
|
"object": "cardTag",
|
||||||
"action": "update",
|
"action": "update",
|
||||||
"card_id": cardID,
|
"card_id": cardID,
|
||||||
"tag_id": tagID,
|
"tag_id": tagID,
|
||||||
|
|
|
@ -48,7 +48,7 @@ func CreateTag(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "tag",
|
"object": "projectTag",
|
||||||
"action": "create",
|
"action": "create",
|
||||||
"data": tag,
|
"data": tag,
|
||||||
"X-Request-Source": source,
|
"X-Request-Source": source,
|
||||||
|
@ -106,7 +106,7 @@ func DeleteTag(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "tag",
|
"object": "projectTag",
|
||||||
"action": "delete",
|
"action": "delete",
|
||||||
"id": id,
|
"id": id,
|
||||||
"X-Request-Source": source,
|
"X-Request-Source": source,
|
||||||
|
@ -149,7 +149,7 @@ func UpdateTag(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "tag",
|
"object": "projectTag",
|
||||||
"action": "update",
|
"action": "update",
|
||||||
"id": id,
|
"id": id,
|
||||||
"changes": tag,
|
"changes": tag,
|
||||||
|
@ -202,7 +202,7 @@ func CreateTagOption(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "tagoption",
|
"object": "tagOption",
|
||||||
"action": "create",
|
"action": "create",
|
||||||
"data": option,
|
"data": option,
|
||||||
"X-Request-Source": source,
|
"X-Request-Source": source,
|
||||||
|
@ -284,7 +284,7 @@ func DeleteTagOption(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "tagoption",
|
"object": "tagOption",
|
||||||
"action": "delete",
|
"action": "delete",
|
||||||
"tag_id": tagID,
|
"tag_id": tagID,
|
||||||
"option_id": optionID,
|
"option_id": optionID,
|
||||||
|
@ -344,7 +344,7 @@ func UpdateTagOption(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
publish(fiber.Map{
|
publish(fiber.Map{
|
||||||
"object": "tagoption",
|
"object": "tagOption",
|
||||||
"action": "update",
|
"action": "update",
|
||||||
"tag_id": tagID,
|
"tag_id": tagID,
|
||||||
"option_id": optionID,
|
"option_id": optionID,
|
||||||
|
|
|
@ -152,7 +152,7 @@ export default class Card {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFromDict(dict: any) {
|
parseUpdate(dict: any) {
|
||||||
if (dict.project_id && dict.project_id !== this._project.id) {
|
if (dict.project_id && dict.project_id !== this._project.id) {
|
||||||
this._project = Project.fromId(dict.project_id) as Project;
|
this._project = Project.fromId(dict.project_id) as Project;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +160,31 @@ export default class Card {
|
||||||
if (dict.content) this._content = dict.content;
|
if (dict.content) this._content = dict.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static parseDelete(id: any) {
|
||||||
|
cards.update((cards) => cards.filter((c) => c.id !== id));
|
||||||
|
}
|
||||||
|
|
||||||
|
parseTag(dict: any) {
|
||||||
|
const cardTag = CardTag.parse(dict, this);
|
||||||
|
if (!cardTag) return;
|
||||||
|
|
||||||
|
this._cardTags = [...this._cardTags, cardTag];
|
||||||
|
}
|
||||||
|
|
||||||
|
parseTagUpdate(dict: any) {
|
||||||
|
const cardTag = this._cardTags.find((ct) => ct.projectTag.id === dict.tag_id);
|
||||||
|
if (!cardTag) {
|
||||||
|
toastAlert('Failed to parse card tag update: card tag not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cardTag.parseUpdate(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseTagDelete(id: any) {
|
||||||
|
this._cardTags = this._cardTags.filter((ct) => ct.projectTag.id !== id);
|
||||||
|
}
|
||||||
|
|
||||||
static parse(json: any): Card | null;
|
static parse(json: any): Card | null;
|
||||||
static parse(json: any, project: Project | null | undefined): Card | null;
|
static parse(json: any, project: Project | null | undefined): Card | null;
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,35 @@ export default class CardTag {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseUpdate(dict: any) {
|
||||||
|
if (dict.card_id && dict.card_id !== this._card.id) {
|
||||||
|
toastAlert('Failed to parse card tag update: card id mismatch');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict.tag_id && dict.tag_id !== this._projectTag.id) {
|
||||||
|
toastAlert('Failed to parse card tag update: projectTag id mismatch');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict.option_id) {
|
||||||
|
const option = this._projectTag.options.find((option) => option.id === dict.option_id);
|
||||||
|
if (!option) {
|
||||||
|
toastAlert('Failed to parse card tag update: option not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._option = option;
|
||||||
|
} else if (this._option) {
|
||||||
|
this._option = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict.value) {
|
||||||
|
this._value = dict.value;
|
||||||
|
} else if (this._value) {
|
||||||
|
this._value = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static parse(json: any): CardTag | null;
|
static parse(json: any): CardTag | null;
|
||||||
static parse(json: any, card: Card | null | undefined): CardTag | null;
|
static parse(json: any, card: Card | null | undefined): CardTag | null;
|
||||||
|
|
||||||
|
|
|
@ -65,10 +65,14 @@ export default class Project {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFromDict(dict: any) {
|
parseUpdate(dict: any) {
|
||||||
if (dict.title) this._title = dict.title;
|
if (dict.title) this._title = dict.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static parseDelete(id: any) {
|
||||||
|
projects.update((projects) => projects.filter((project) => project.id !== id));
|
||||||
|
}
|
||||||
|
|
||||||
static parse(json: any): Project | null {
|
static parse(json: any): Project | null {
|
||||||
if (!json) return null;
|
if (!json) return null;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
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';
|
||||||
|
@ -78,77 +79,99 @@ export default class WebSocketManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyMessage(data: any) {
|
function applyMessage(data: any) {
|
||||||
switch (data.object) {
|
console.debug('WebSocket message:', data);
|
||||||
case 'project':
|
if (!data.object) {
|
||||||
applyProject(data);
|
toastWarning('Failed to parse WebSocket message: missing object');
|
||||||
break;
|
return;
|
||||||
case 'card':
|
|
||||||
applyCard(data);
|
|
||||||
break;
|
|
||||||
case 'view':
|
|
||||||
applyView(data);
|
|
||||||
break;
|
|
||||||
case 'projectTag':
|
|
||||||
applyProjectTag(data);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log('Unknown object:', data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!data.action) {
|
||||||
|
toastWarning('Failed to parse WebSocket message: missing action');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.object === 'project') applyProject(data);
|
||||||
|
else if (data.object === 'cardTag') applyCardTag(data);
|
||||||
|
else if (data.object === 'card') applyCard(data);
|
||||||
|
else if (data.object === 'view') applyView(data);
|
||||||
|
else if (data.object === 'projectTag') applyProjectTag(data);
|
||||||
|
else if (data.object === 'filter') applyFilter(data);
|
||||||
|
else toastWarning('Failed to parse WebSocket message: unknown object');
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyProject(data: any) {
|
function applyProject(data: any) {
|
||||||
switch (data.action) {
|
if (data.action === 'create') {
|
||||||
case 'create':
|
|
||||||
Project.parse(data.data);
|
Project.parse(data.data);
|
||||||
case 'update':
|
return;
|
||||||
get(projects)
|
|
||||||
.find((p) => p.id === data.id)
|
|
||||||
?.updateFromDict(data.changes);
|
|
||||||
projects.reload();
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
projects.set(get(projects).filter((p) => p.id !== data.id));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if (data.action === 'delete') {
|
||||||
|
Project.parseDelete(data.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const project = Project.fromId(data.id);
|
||||||
|
if (!project) {
|
||||||
|
toastWarning('Failed to parse project update: project not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.action !== 'update') {
|
||||||
|
toastWarning('Failed to parse project update: unknown action');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
project.parseUpdate(data.changes);
|
||||||
|
projects.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyCard(data: any) {
|
function applyCard(data: any) {
|
||||||
switch (data.action) {
|
if (data.action === 'create') {
|
||||||
case 'create':
|
|
||||||
Card.parse(data.data);
|
Card.parse(data.data);
|
||||||
break;
|
return;
|
||||||
case 'update':
|
}
|
||||||
get(cards)
|
if (data.action === 'delete') {
|
||||||
.find((c) => c.id === data.id)
|
Card.parseDelete(data.id);
|
||||||
?.updateFromDict(data.changes);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const card = Card.fromId(data.id);
|
||||||
|
if (!card) {
|
||||||
|
toastWarning('Failed to parse card update: card not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.action !== 'update') {
|
||||||
|
toastWarning('Failed to parse card update: unknown action');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
card.parseUpdate(data.changes);
|
||||||
cards.reload();
|
cards.reload();
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
cards.set(get(cards).filter((c) => c.id !== data.id));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyView(data: any) {
|
function applyCardTag(data: any) {
|
||||||
switch (data.action) {
|
const card = Card.fromId(data.card_id);
|
||||||
case 'create':
|
if (!card) {
|
||||||
case 'update':
|
toastWarning('Failed to parse card tag update: card not found');
|
||||||
View.parse(data.value);
|
return;
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
views.set(get(views).filter((v) => v.id !== data.id));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.action === 'create') {
|
||||||
|
card.parseTag(data.data);
|
||||||
|
} else if (data.action === 'update') {
|
||||||
|
card.parseTagUpdate(data.changes);
|
||||||
|
} else if (data.action === 'delete') {
|
||||||
|
card.parseTagDelete(data.tag_id);
|
||||||
|
} else {
|
||||||
|
toastWarning('Failed to parse card tag update: unknown action');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cards.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyProjectTag(data: any) {
|
function applyView(data: any) {}
|
||||||
switch (data.action) {
|
|
||||||
case 'create':
|
function applyProjectTag(data: any) {}
|
||||||
case 'update':
|
|
||||||
ProjectTag.parse(data.value);
|
function applyFilter(data: any) {}
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
projectTags.set(get(projectTags).filter((t) => t.id !== data.id));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue