Fix columns & cards

This commit is contained in:
Brieuc Dubois 2024-01-09 01:25:53 +01:00
parent fb70658f23
commit 5fa653f401
6 changed files with 130 additions and 69 deletions

View File

@ -1,9 +1,8 @@
<script lang="ts">
import currentDraggedCard from '$lib/stores/currentDraggedCard';
import currentModalCard from '$lib/stores/currentModalCard';
import project_tags from '$lib/stores/projectTags';
import type Card from '$lib/types/Card';
import ModalCard from './ModalCard.svelte';
// import ModalCard from './ModalCard.svelte';
export let card: Card;
</script>
@ -21,25 +20,21 @@
}
}}
>
<div class="title">{card.title}</div>
{#if card.tags}
<div class="title">{card.id} - {card.title}</div>
<div class="tags">
{#each card.tags as tag}
{#if tag.option_id}
{#if $project_tags[tag.tag_id]}
<span class="tag" style="border: 1px solid #333">
{$project_tags[tag.tag_id]?.options.find((o) => o.id == tag.option_id)?.value}</span
{#each card.cardTags as tag}
{#if tag.option}
<span class="tag" style="border: 1px solid #333"
>{tag.projectTag.id}: {tag.option.id} ({tag.option.value})</span
>
{/if}
{:else if tag.value}
<span class="tag" style="border: 1px solid #333">{tag.value}</span>
{/if}
{/each}
</div>
{/if}
</div>
<ModalCard bind:card />
<!-- <ModalCard bind:card /> -->
<style lang="less">
.card {

View File

@ -1,39 +1,43 @@
<script lang="ts">
import Card from '$lib/types/Card';
import Card, { cards } from '$lib/types/Card';
import CardComponent from '../card/Card.svelte';
import AddIcon from '../icons/AddIcon.svelte';
import type TagOption from '$lib/types/TagOption';
import type ProjectTag from '$lib/types/ProjectTag';
import type Project from '$lib/types/Project';
import currentDraggedCard from '$lib/stores/currentDraggedCard';
export let project: Project;
export let option: TagOption | null = null;
export let primaryTag: ProjectTag | null = null;
export let title: string;
export let columnCards: Card[] = [];
let lastTitle = title;
let newOptionValue = option?.value || `No ${primaryTag?.title}`;
// async function onDrop(e: DragEvent) {
// e.preventDefault();
// if (!$currentDraggedCard || !$currentDraggedCard.cardTags) return;
async function onDrop(e: DragEvent) {
e.preventDefault();
if (!primaryTag || !$currentDraggedCard || !$currentDraggedCard.cardTags) return;
// $currentDraggedCard;
const currentCardTag =
$currentDraggedCard.cardTags.find((tag) => tag.projectTag === primaryTag) || null;
const currentOption = currentCardTag?.option || null;
// for (let tag of $currentDraggedCard.cardTags) {
// if (tag.projectTag !== primaryTag) continue;
// if (tag.option == option) return;
if (currentOption === option) return;
// if (!tag.option && !tag.value) await tag.delete();
// else if (tag.option && optionId)
// await createCardTagApi(tag.card_id, tag.tag_id, tag.option_id, tag.value);
// else await updateCardTagApi(tag.card_id, tag.tag_id, optionId, tag.value);
if (!currentOption && option) {
await $currentDraggedCard.addTag(primaryTag, option, null);
} else if (currentOption && !option) {
if (!currentCardTag) return;
await $currentDraggedCard.removeTag(currentCardTag);
} else if (currentOption && option) {
if (!currentCardTag) return;
await $currentDraggedCard.updateTag(currentCardTag, option, null);
}
// tag.option_id = optionId;
// cards.reload();
// }
// currentDraggedCard.set(null);
// }
currentDraggedCard.set(null);
cards.reload();
}
async function addCard() {
const card = await Card.create(project);
@ -43,33 +47,30 @@
if (!option) return;
await card.addTag(primaryTag, option, null);
cards.reload();
}
</script>
<!-- on:drop={onDrop} -->
<div
class="column"
role="listbox"
tabindex="-1"
on:drop={onDrop}
on:dragover={(e) => {
e.preventDefault();
}}
>
<header>
<input
bind:value={title}
bind:value={newOptionValue}
type="text"
on:blur={async () => {
if (lastTitle === title) return;
if (!option || !primaryTag) return;
// option;
// await updateTagOptionAPI({
// id: optionId,
// tag_id: primary_tag_id,
// value: title
// });
// lastTitle = title;
// cards.reload();
if (newOptionValue === option.value) return;
await option.setValue(newOptionValue);
newOptionValue = option.value;
}}
disabled={option === null}
/>

View File

@ -6,21 +6,22 @@
import Header from './Header.svelte';
export let project: Project;
$: allCards = $cards;
</script>
{#if project}
<section>
{#if $currentView}
<Header {project} />
{#if $cards}
{#if $cards && allCards}
<div class="grid">
{#if $currentView.primaryTag}
{#each $currentView.primaryTag.options as option}
<Column
{option}
primaryTag={$currentView.primaryTag}
title={option.value}
columnCards={$cards
columnCards={allCards
.filter((c) => c.cardTags.map((t) => t.option).includes(option))
.sort((a, b) => {
if (!$currentView?.sortTag) return 0;
@ -43,15 +44,14 @@
{/if}
<Column
primaryTag={$currentView.primaryTag}
title={$currentView.primaryTag ? `No ${$currentView.title}` : 'No groups'}
columnCards={$currentView.primaryTag != null
? (() => {
const primaryTag = $currentView.primaryTag;
return $cards.filter(
return allCards.filter(
(c) => !c.cardTags.map((t) => t.projectTag).includes(primaryTag)
);
})()
: $cards}
: allCards}
{project}
/>
</div>

View File

@ -6,7 +6,14 @@ import { toastAlert } from '$lib/utils/toasts';
import type TagOption from './TagOption';
import type ProjectTag from './ProjectTag';
export const cards = writable([] as Card[]);
const { subscribe, set, update } = writable([] as Card[]);
export const cards = {
subscribe,
set,
update,
reload: () => update((cards) => cards)
};
export default class Card {
private _id: number;
@ -90,16 +97,35 @@ export default class Card {
if (!cardTag) return false;
this._cardTags.push(cardTag);
this._cardTags = [...this._cardTags, cardTag];
return true;
}
async removeTag(cardTag: CardTag): Promise<boolean> {
const res = await cardTag.delete();
if (!res) return false;
this._cardTags = this._cardTags.filter((ct) => ct !== cardTag);
return true;
}
async updateTag(
cardTag: CardTag,
tagOption: TagOption | null,
value: string | null
): Promise<boolean> {
return await cardTag.update(tagOption, value);
}
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 {
if (json === null) {
toastAlert('Failed to parse card: json is null');
return null;
}

View File

@ -1,4 +1,5 @@
import cardsTagsApi from '$lib/api/cardsTagsApi';
import { toastAlert } from '$lib/utils/toasts';
import Card from './Card';
import ProjectTag from './ProjectTag';
import TagOption from './TagOption';
@ -21,16 +22,16 @@ export default class CardTag {
this._value = value;
}
get card(): number {
return this.card;
get card(): Card {
return this._card;
}
get projectTag(): ProjectTag {
return this.projectTag;
return this._projectTag;
}
get option(): TagOption | null {
return this.option;
return this._option;
}
get value(): string | null {
@ -43,31 +44,58 @@ export default class CardTag {
option: TagOption | null,
value: string | null
): Promise<CardTag | null> {
const id = await cardsTagsApi.create(card.id, tag.id, option ? option.id : null, value);
const res = await cardsTagsApi.create(card.id, tag.id, option ? option.id : null, value);
if (!id) return null;
if (!res) return null;
return new CardTag(card, tag, option, value);
}
async delete() {
async delete(): Promise<boolean> {
return cardsTagsApi.delete(this._card.id, this._projectTag.id);
}
async update(option: TagOption | null, value: string | null): Promise<boolean> {
const res = await cardsTagsApi.update(
this._card.id,
this._projectTag.id,
option ? option.id : null,
value
);
if (!res) return false;
this._option = option;
this._value = value;
return true;
}
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 {
if (!json) return null;
if (!json) {
toastAlert('Failed to parse card tag: json is null');
return null;
}
if (!card) card = Card.fromId(json.card_id);
if (!card) return null;
if (!card) {
toastAlert('Failed to parse card tag: card is null');
return null;
}
const tag = ProjectTag.fromId(json.tag_id);
if (!tag) return null;
if (!tag) {
toastAlert('Failed to parse card tag: tag is null');
return null;
}
const option = tag.options.find((option) => option.id === json.option_id);
if (!option) return null;
if (!option) {
toastAlert('Failed to parse card tag: option is null');
return null;
}
return new CardTag(card, tag, option, json.value);
}

View File

@ -1,3 +1,4 @@
import tagsOptions from '$lib/api/tagsOptions';
import ProjectTag from './ProjectTag';
export default class TagOption {
@ -23,6 +24,16 @@ export default class TagOption {
return this._value;
}
async setValue(value: string): Promise<boolean> {
const res = await tagsOptions.update(this._id, this.projectTag.id, value);
if (!res) return false;
this._value = value;
return res;
}
static parse(json: any): TagOption | null;
static parse(json: any, projectTag: ProjectTag | null | undefined): TagOption | null;