Fix columns & cards
This commit is contained in:
parent
fb70658f23
commit
5fa653f401
|
@ -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="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
|
||||
>
|
||||
{/if}
|
||||
{:else if tag.value}
|
||||
<span class="tag" style="border: 1px solid #333">{tag.value}</span>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<div class="title">{card.id} - {card.title}</div>
|
||||
<div class="tags">
|
||||
{#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
|
||||
>
|
||||
{:else if tag.value}
|
||||
<span class="tag" style="border: 1px solid #333">{tag.value}</span>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ModalCard bind:card />
|
||||
<!-- <ModalCard bind:card /> -->
|
||||
|
||||
<style lang="less">
|
||||
.card {
|
||||
|
|
|
@ -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}
|
||||
/>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue