Add card from columns
This commit is contained in:
parent
e7b34fc1b4
commit
fb70658f23
|
@ -1,65 +1,56 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import cards from '$lib/stores/cards';
|
import Card from '$lib/types/Card';
|
||||||
import currentDraggedCard from '$lib/stores/currentDraggedCard';
|
|
||||||
import type Card from '$lib/types/Card';
|
|
||||||
import type TagValue from '$lib/types/TagValue';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
import projectTags from '../../stores/projectTags';
|
|
||||||
import CardComponent from '../card/Card.svelte';
|
import CardComponent from '../card/Card.svelte';
|
||||||
import AddIcon from '../icons/AddIcon.svelte';
|
import AddIcon from '../icons/AddIcon.svelte';
|
||||||
import { import } from { createCardTagApi, deleteCardTagApi, updateCardTagApi };
|
import type TagOption from '$lib/types/TagOption';
|
||||||
|
import type ProjectTag from '$lib/types/ProjectTag';
|
||||||
|
import type Project from '$lib/types/Project';
|
||||||
|
|
||||||
export let projectId: number;
|
export let project: Project;
|
||||||
export let optionId: number | null = null;
|
export let option: TagOption | null = null;
|
||||||
export let primary_tag_id: number | null = null;
|
export let primaryTag: ProjectTag | null = null;
|
||||||
export let title: string;
|
export let title: string;
|
||||||
export let columnCards: Card[] = [];
|
export let columnCards: Card[] = [];
|
||||||
|
|
||||||
let lastTitle = title;
|
let lastTitle = title;
|
||||||
|
|
||||||
async function onDrop(e: DragEvent) {
|
// async function onDrop(e: DragEvent) {
|
||||||
e.preventDefault();
|
// e.preventDefault();
|
||||||
if (!$currentDraggedCard || !$currentDraggedCard.tags) return;
|
// if (!$currentDraggedCard || !$currentDraggedCard.cardTags) return;
|
||||||
for (let tag of $currentDraggedCard.tags) {
|
|
||||||
if (tag.tag_id !== primary_tag_id) continue;
|
|
||||||
if (tag.option_id == optionId) return;
|
|
||||||
|
|
||||||
try {
|
// $currentDraggedCard;
|
||||||
if (tag.option_id && optionId) await deleteCardTagApi(tag.card_id, tag.tag_id);
|
|
||||||
else if (tag.option_id && 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);
|
|
||||||
|
|
||||||
tag.option_id = optionId;
|
// for (let tag of $currentDraggedCard.cardTags) {
|
||||||
cards.reload();
|
// if (tag.projectTag !== primaryTag) continue;
|
||||||
} catch (e) {}
|
// if (tag.option == option) return;
|
||||||
break;
|
|
||||||
}
|
// if (!tag.option && !tag.value) await tag.delete();
|
||||||
currentDraggedCard.set(null);
|
// 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);
|
||||||
|
|
||||||
|
// tag.option_id = optionId;
|
||||||
|
// cards.reload();
|
||||||
|
// }
|
||||||
|
// currentDraggedCard.set(null);
|
||||||
|
// }
|
||||||
|
|
||||||
async function addCard() {
|
async function addCard() {
|
||||||
const tags: TagValue[] = [];
|
const card = await Card.create(project);
|
||||||
for (let tag of Object.values(get(projectTags))) {
|
|
||||||
if (tag.id === primary_tag_id) {
|
|
||||||
tags.push({
|
|
||||||
card_id: -1,
|
|
||||||
tag_id: tag.id,
|
|
||||||
option_id: optionId,
|
|
||||||
value: null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await cards.add(projectId, tags);
|
if (!card) return;
|
||||||
|
if (!primaryTag) return;
|
||||||
|
if (!option) return;
|
||||||
|
|
||||||
|
await card.addTag(primaryTag, option, null);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- on:drop={onDrop} -->
|
||||||
<div
|
<div
|
||||||
class="column"
|
class="column"
|
||||||
role="listbox"
|
role="listbox"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
on:drop={onDrop}
|
|
||||||
on:dragover={(e) => {
|
on:dragover={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
|
@ -70,16 +61,17 @@
|
||||||
type="text"
|
type="text"
|
||||||
on:blur={async () => {
|
on:blur={async () => {
|
||||||
if (lastTitle === title) return;
|
if (lastTitle === title) return;
|
||||||
if (!optionId || !primary_tag_id) return;
|
if (!option || !primaryTag) return;
|
||||||
await updateTagOptionAPI({
|
// option;
|
||||||
id: optionId,
|
// await updateTagOptionAPI({
|
||||||
tag_id: primary_tag_id,
|
// id: optionId,
|
||||||
value: title
|
// tag_id: primary_tag_id,
|
||||||
});
|
// value: title
|
||||||
lastTitle = title;
|
// });
|
||||||
cards.reload();
|
// lastTitle = title;
|
||||||
|
// cards.reload();
|
||||||
}}
|
}}
|
||||||
disabled={optionId === null}
|
disabled={option === null}
|
||||||
/>
|
/>
|
||||||
<span>
|
<span>
|
||||||
<span>{columnCards.length}</span>
|
<span>{columnCards.length}</span>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import currentView from '$lib/stores/currentView';
|
import currentView from '$lib/stores/currentView';
|
||||||
|
import { cards } from '$lib/types/Card';
|
||||||
import type Project from '$lib/types/Project';
|
import type Project from '$lib/types/Project';
|
||||||
|
import Column from './Column.svelte';
|
||||||
import Header from './Header.svelte';
|
import Header from './Header.svelte';
|
||||||
|
|
||||||
export let project: Project;
|
export let project: Project;
|
||||||
|
@ -12,44 +14,45 @@
|
||||||
<Header {project} />
|
<Header {project} />
|
||||||
{#if $cards}
|
{#if $cards}
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
{#if view.primary_tag_id}
|
{#if $currentView.primaryTag}
|
||||||
{#each $projectTags[view.primary_tag_id].options as option}
|
{#each $currentView.primaryTag.options as option}
|
||||||
<Column
|
<Column
|
||||||
optionId={option.id}
|
{option}
|
||||||
primary_tag_id={view.primary_tag_id}
|
primaryTag={$currentView.primaryTag}
|
||||||
title={option.value}
|
title={option.value}
|
||||||
columnCards={$cards
|
columnCards={$cards
|
||||||
.filter((c) => c.tags.map((t) => t.option_id).includes(option.id))
|
.filter((c) => c.cardTags.map((t) => t.option).includes(option))
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
if (!view?.sort_tag_id) return 0;
|
if (!$currentView?.sortTag) return 0;
|
||||||
const aTag = a.tags.find((t) => t.tag_id === view?.sort_tag_id);
|
const aTag = a.cardTags.find((t) => t.projectTag === $currentView?.sortTag);
|
||||||
const bTag = b.tags.find((t) => t.tag_id === view?.sort_tag_id);
|
const bTag = b.cardTags.find((t) => t.projectTag === $currentView?.sortTag);
|
||||||
|
|
||||||
if (!aTag) return -(view?.sort_direction || 1);
|
if (!aTag) return -($currentView?.sortDirection || 1);
|
||||||
if (!bTag) return view?.sort_direction || 1;
|
if (!bTag) return $currentView?.sortDirection || 1;
|
||||||
|
|
||||||
const aValue = aTag.value || aTag.option_id || 0;
|
const aValue = aTag.value || aTag.option?.value || '';
|
||||||
const bValue = bTag.value || bTag.option_id || 0;
|
const bValue = bTag.value || bTag.option?.value || '';
|
||||||
|
|
||||||
return aValue < bValue
|
return aValue < bValue
|
||||||
? view?.sort_direction || 1
|
? $currentView?.sortDirection || 1
|
||||||
: -(view?.sort_direction || 1);
|
: -($currentView?.sortDirection || 1);
|
||||||
})}
|
})}
|
||||||
projectId={project.id}
|
{project}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
<Column
|
<Column
|
||||||
primary_tag_id={view.primary_tag_id}
|
primaryTag={$currentView.primaryTag}
|
||||||
title={view.primary_tag_id
|
title={$currentView.primaryTag ? `No ${$currentView.title}` : 'No groups'}
|
||||||
? `No ${$projectTags[view.primary_tag_id].title}`
|
columnCards={$currentView.primaryTag != null
|
||||||
: 'No groups'}
|
? (() => {
|
||||||
columnCards={view.primary_tag_id
|
const primaryTag = $currentView.primaryTag;
|
||||||
? $cards.filter(
|
return $cards.filter(
|
||||||
(c) => !c.tags.map((t) => t.tag_id).includes(view?.primary_tag_id || -2)
|
(c) => !c.cardTags.map((t) => t.projectTag).includes(primaryTag)
|
||||||
)
|
);
|
||||||
|
})()
|
||||||
: $cards}
|
: $cards}
|
||||||
projectId={project.id}
|
{project}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { get, writable } from 'svelte/store';
|
||||||
import CardTag from './CardTag';
|
import CardTag from './CardTag';
|
||||||
import Project from './Project';
|
import Project from './Project';
|
||||||
import { toastAlert } from '$lib/utils/toasts';
|
import { toastAlert } from '$lib/utils/toasts';
|
||||||
|
import type TagOption from './TagOption';
|
||||||
|
import type ProjectTag from './ProjectTag';
|
||||||
|
|
||||||
export const cards = writable([] as Card[]);
|
export const cards = writable([] as Card[]);
|
||||||
|
|
||||||
|
@ -11,20 +13,20 @@ export default class Card {
|
||||||
private _project: Project;
|
private _project: Project;
|
||||||
private _title: string;
|
private _title: string;
|
||||||
private _content: string;
|
private _content: string;
|
||||||
private _tags: CardTag[];
|
private _cardTags: CardTag[];
|
||||||
|
|
||||||
private constructor(
|
private constructor(
|
||||||
id: number,
|
id: number,
|
||||||
project: Project,
|
project: Project,
|
||||||
title: string,
|
title: string,
|
||||||
content: string,
|
content: string,
|
||||||
tags: CardTag[]
|
cardTags: CardTag[]
|
||||||
) {
|
) {
|
||||||
this._id = id;
|
this._id = id;
|
||||||
this._project = project;
|
this._project = project;
|
||||||
this._title = title;
|
this._title = title;
|
||||||
this._content = content;
|
this._content = content;
|
||||||
this._tags = tags;
|
this._cardTags = cardTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
get id(): number {
|
get id(): number {
|
||||||
|
@ -43,8 +45,8 @@ export default class Card {
|
||||||
return this._content;
|
return this._content;
|
||||||
}
|
}
|
||||||
|
|
||||||
get tags(): CardTag[] {
|
get cardTags(): CardTag[] {
|
||||||
return this._tags;
|
return this._cardTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromId(id: number): Card | null {
|
static fromId(id: number): Card | null {
|
||||||
|
@ -79,6 +81,20 @@ export default class Card {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addTag(
|
||||||
|
projectTag: ProjectTag,
|
||||||
|
tagOption: TagOption | null,
|
||||||
|
value: string | null
|
||||||
|
): Promise<boolean> {
|
||||||
|
const cardTag = await CardTag.create(this, projectTag, tagOption, value);
|
||||||
|
|
||||||
|
if (!cardTag) return false;
|
||||||
|
|
||||||
|
this._cardTags.push(cardTag);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -95,7 +111,7 @@ export default class Card {
|
||||||
|
|
||||||
const card = new Card(json.id, project, json.title, json.content, []);
|
const card = new Card(json.id, project, json.title, json.content, []);
|
||||||
|
|
||||||
card._tags = CardTag.parseAll(json.tags, card);
|
card._cardTags = CardTag.parseAll(json.tags, card);
|
||||||
|
|
||||||
cards.update((cards) => {
|
cards.update((cards) => {
|
||||||
if (!cards.find((c) => c.id === card.id)) {
|
if (!cards.find((c) => c.id === card.id)) {
|
||||||
|
|
|
@ -5,13 +5,18 @@ import TagOption from './TagOption';
|
||||||
|
|
||||||
export default class CardTag {
|
export default class CardTag {
|
||||||
private _card: Card;
|
private _card: Card;
|
||||||
private _tag: ProjectTag;
|
private _projectTag: ProjectTag;
|
||||||
private _option: TagOption | null;
|
private _option: TagOption | null;
|
||||||
private _value: string | null;
|
private _value: string | null;
|
||||||
|
|
||||||
private constructor(card: Card, tag: ProjectTag, option: TagOption | null, value: string | null) {
|
private constructor(
|
||||||
|
card: Card,
|
||||||
|
projectTag: ProjectTag,
|
||||||
|
option: TagOption | null,
|
||||||
|
value: string | null
|
||||||
|
) {
|
||||||
this._card = card;
|
this._card = card;
|
||||||
this._tag = tag;
|
this._projectTag = projectTag;
|
||||||
this._option = option;
|
this._option = option;
|
||||||
this._value = value;
|
this._value = value;
|
||||||
}
|
}
|
||||||
|
@ -20,11 +25,11 @@ export default class CardTag {
|
||||||
return this.card;
|
return this.card;
|
||||||
}
|
}
|
||||||
|
|
||||||
get tag(): number {
|
get projectTag(): ProjectTag {
|
||||||
return this.tag;
|
return this.projectTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
get option(): number | null {
|
get option(): TagOption | null {
|
||||||
return this.option;
|
return this.option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +51,7 @@ export default class CardTag {
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete() {
|
async delete() {
|
||||||
return cardsTagsApi.delete(this._card.id, this._tag.id);
|
return cardsTagsApi.delete(this._card.id, this._projectTag.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static parse(json: any): CardTag | null;
|
static parse(json: any): CardTag | null;
|
||||||
|
|
|
@ -15,7 +15,7 @@ export default class TagOption {
|
||||||
return this._id;
|
return this._id;
|
||||||
}
|
}
|
||||||
|
|
||||||
get tagId(): ProjectTag {
|
get projectTag(): ProjectTag {
|
||||||
return this._projectTag;
|
return this._projectTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue