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{
|
||||
"object": "cardtag",
|
||||
"object": "cardTag",
|
||||
"action": "create",
|
||||
"card_id": cardID,
|
||||
"data": cardtag,
|
||||
"X-Request-Source": source,
|
||||
});
|
||||
|
@ -172,9 +173,10 @@ func DeleteCardTag(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
publish(fiber.Map{
|
||||
"object": "cardtag",
|
||||
"object": "cardTag",
|
||||
"action": "delete",
|
||||
"id": cardID,
|
||||
"card_id": cardID,
|
||||
"tag_id": tagID,
|
||||
"X-Request-Source": source,
|
||||
});
|
||||
|
||||
|
@ -272,7 +274,7 @@ func UpdateCardTag(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
publish(fiber.Map{
|
||||
"object": "cardtag",
|
||||
"object": "cardTag",
|
||||
"action": "update",
|
||||
"card_id": cardID,
|
||||
"tag_id": tagID,
|
||||
|
|
|
@ -48,7 +48,7 @@ func CreateTag(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
publish(fiber.Map{
|
||||
"object": "tag",
|
||||
"object": "projectTag",
|
||||
"action": "create",
|
||||
"data": tag,
|
||||
"X-Request-Source": source,
|
||||
|
@ -106,7 +106,7 @@ func DeleteTag(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
publish(fiber.Map{
|
||||
"object": "tag",
|
||||
"object": "projectTag",
|
||||
"action": "delete",
|
||||
"id": id,
|
||||
"X-Request-Source": source,
|
||||
|
@ -149,7 +149,7 @@ func UpdateTag(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
publish(fiber.Map{
|
||||
"object": "tag",
|
||||
"object": "projectTag",
|
||||
"action": "update",
|
||||
"id": id,
|
||||
"changes": tag,
|
||||
|
@ -202,7 +202,7 @@ func CreateTagOption(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
publish(fiber.Map{
|
||||
"object": "tagoption",
|
||||
"object": "tagOption",
|
||||
"action": "create",
|
||||
"data": option,
|
||||
"X-Request-Source": source,
|
||||
|
@ -284,7 +284,7 @@ func DeleteTagOption(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
publish(fiber.Map{
|
||||
"object": "tagoption",
|
||||
"object": "tagOption",
|
||||
"action": "delete",
|
||||
"tag_id": tagID,
|
||||
"option_id": optionID,
|
||||
|
@ -344,7 +344,7 @@ func UpdateTagOption(c *fiber.Ctx) error {
|
|||
}
|
||||
|
||||
publish(fiber.Map{
|
||||
"object": "tagoption",
|
||||
"object": "tagOption",
|
||||
"action": "update",
|
||||
"tag_id": tagID,
|
||||
"option_id": optionID,
|
||||
|
|
|
@ -152,7 +152,7 @@ export default class Card {
|
|||
return true;
|
||||
}
|
||||
|
||||
updateFromDict(dict: any) {
|
||||
parseUpdate(dict: any) {
|
||||
if (dict.project_id && dict.project_id !== this._project.id) {
|
||||
this._project = Project.fromId(dict.project_id) as Project;
|
||||
}
|
||||
|
@ -160,6 +160,31 @@ export default class Card {
|
|||
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, project: Project | null | undefined): Card | null;
|
||||
|
||||
|
|
|
@ -71,6 +71,35 @@ export default class CardTag {
|
|||
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, card: Card | null | undefined): CardTag | null;
|
||||
|
||||
|
|
|
@ -65,10 +65,14 @@ export default class Project {
|
|||
return true;
|
||||
}
|
||||
|
||||
updateFromDict(dict: any) {
|
||||
parseUpdate(dict: any) {
|
||||
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 {
|
||||
if (!json) return null;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Card, { cards } from '$lib/types/Card';
|
||||
import CardTag from '$lib/types/CardTag';
|
||||
import Project, { projects } from '$lib/types/Project';
|
||||
import ProjectTag, { projectTags } from '$lib/types/ProjectTag';
|
||||
import View, { views } from '$lib/types/View';
|
||||
|
@ -78,77 +79,99 @@ export default class WebSocketManager {
|
|||
}
|
||||
|
||||
function applyMessage(data: any) {
|
||||
switch (data.object) {
|
||||
case 'project':
|
||||
applyProject(data);
|
||||
break;
|
||||
case 'card':
|
||||
applyCard(data);
|
||||
break;
|
||||
case 'view':
|
||||
applyView(data);
|
||||
break;
|
||||
case 'projectTag':
|
||||
applyProjectTag(data);
|
||||
break;
|
||||
default:
|
||||
console.log('Unknown object:', data);
|
||||
console.debug('WebSocket message:', data);
|
||||
if (!data.object) {
|
||||
toastWarning('Failed to parse WebSocket message: missing object');
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
switch (data.action) {
|
||||
case 'create':
|
||||
if (data.action === 'create') {
|
||||
Project.parse(data.data);
|
||||
case 'update':
|
||||
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;
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
switch (data.action) {
|
||||
case 'create':
|
||||
if (data.action === 'create') {
|
||||
Card.parse(data.data);
|
||||
break;
|
||||
case 'update':
|
||||
get(cards)
|
||||
.find((c) => c.id === data.id)
|
||||
?.updateFromDict(data.changes);
|
||||
return;
|
||||
}
|
||||
if (data.action === 'delete') {
|
||||
Card.parseDelete(data.id);
|
||||
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();
|
||||
break;
|
||||
case 'delete':
|
||||
cards.set(get(cards).filter((c) => c.id !== data.id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function applyView(data: any) {
|
||||
switch (data.action) {
|
||||
case 'create':
|
||||
case 'update':
|
||||
View.parse(data.value);
|
||||
break;
|
||||
case 'delete':
|
||||
views.set(get(views).filter((v) => v.id !== data.id));
|
||||
break;
|
||||
}
|
||||
function applyCardTag(data: any) {
|
||||
const card = Card.fromId(data.card_id);
|
||||
if (!card) {
|
||||
toastWarning('Failed to parse card tag update: card not found');
|
||||
return;
|
||||
}
|
||||
|
||||
function applyProjectTag(data: any) {
|
||||
switch (data.action) {
|
||||
case 'create':
|
||||
case 'update':
|
||||
ProjectTag.parse(data.value);
|
||||
break;
|
||||
case 'delete':
|
||||
projectTags.set(get(projectTags).filter((t) => t.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 applyView(data: any) {}
|
||||
|
||||
function applyProjectTag(data: any) {}
|
||||
|
||||
function applyFilter(data: any) {}
|
||||
|
|
Loading…
Reference in New Issue