Move to $lib

This commit is contained in:
Brieuc Dubois 2024-01-05 01:14:54 +01:00
parent b3167c2a2f
commit b13d88375b
38 changed files with 229 additions and 85 deletions

View File

@ -1,21 +0,0 @@
<script lang="ts">
import type { Card } from '../../../stores/interfaces';
import projectTags from '../../../stores/projectTags';
import ModalTag from './modal_tag.svelte';
import ModalNewTag from './modal_tag/modal_new_tag.svelte';
export let card: Card;
</script>
<table>
{#if card.tags}
{#each Object.values($projectTags) as projectTag}
<ModalTag
tagValue={card.tags.find((t) => t.tag_id === projectTag.id)}
bind:projectTag
{card}
/>
{/each}
{/if}
<ModalNewTag projectId={card.project_id} />
</table>

View File

@ -0,0 +1,103 @@
import type { Card, TagValue } from '../stores/interfaces';
import api, { processError } from '../utils/api';
import status from '../utils/status';
export async function newCardApi(projectId: number, tags: TagValue[]): Promise<Card> {
const response = await api.post(`/v1/cards`, {
project_id: projectId,
title: 'Untitled',
content: ''
});
if (response.status !== status.Created) {
processError(response, 'Failed to create card');
return Promise.reject();
}
const id: number = response.data.id;
const consistant_tags = [];
for (const tag of tags) {
if ((tag.option_id === -1 && tag.value == '') || tag.tag_id === -1) continue;
await createCardTagApi(id, tag.tag_id, tag.option_id, tag.value);
consistant_tags.push({ ...tag, card_id: id });
}
return {
id: id,
project_id: projectId,
title: 'Untitled',
content: '',
tags: consistant_tags
};
}
export async function updateCardApi(card: Card): Promise<boolean> {
const response = await api.put(`/v1/cards/${card.id}`, {
project_id: card.project_id,
title: card.title,
content: card.content
});
if (response.status !== status.NoContent) {
processError(response, 'Failed to update card');
return false;
}
return true;
}
export async function deleteCardApi(cardID: number): Promise<void> {
const response = await api.delete(`/v1/cards/${cardID}`);
if (response.status !== status.NoContent) {
processError(response, 'Failed to delete card');
return Promise.reject();
}
}
export async function createCardTagApi(
cardId: number,
tagId: number,
optionId: number | null,
value: string | null
): Promise<boolean> {
const response = await api.post(`/v1/cards/${cardId}/tags/${tagId}`, {
option_id: optionId,
value: value
});
if (response.status !== status.Created) {
processError(response, 'Failed to create card tag');
return false;
}
return true;
}
export async function deleteCardTagApi(cardID: number, tagID: number): Promise<void> {
const response = await api.delete(`/v1/cards/${cardID}/tags/${tagID}`);
if (response.status !== status.NoContent) {
processError(response, 'Failed to delete tag');
return Promise.reject();
}
}
export async function updateCardTagApi(
cardID: number,
tagID: number,
option_id: number | null,
value: string | null
): Promise<void> {
const response = await api.put(`/v1/cards/${cardID}/tags/${tagID}`, {
option_id: option_id == -1 ? null : option_id,
value: value == '' ? null : value
});
if (response.status !== status.NoContent) {
processError(response, 'Failed to update card tag');
return Promise.reject();
}
}

View File

@ -0,0 +1,25 @@
import { parseCards, type Card, type Project } from '$lib/stores/interfaces';
import api, { processError } from '$lib/utils/api';
import status from '$lib/utils/status';
export async function getProjectAPI(projectId: number): Promise<Project> {
const response = await api.get(`/v1/projects/${projectId}`);
if (response.status !== status.OK) {
processError(response, 'Failed to fetch project');
return Promise.reject();
}
return response.data;
}
export async function getProjectCardsAPI(projectId: number): Promise<Card[]> {
const response = await api.get(`/v1/projects/${projectId}/cards`);
if (response.status !== status.OK) {
processError(response, 'Failed to fetch cards');
return Promise.reject();
}
return parseCards(response.data);
}

View File

@ -0,0 +1,17 @@
import type { MeTag, TagOption } from '$lib/stores/interfaces';
import api, { processError } from '$lib/utils/api';
import status from '$lib/utils/status';
export async function updateTagAPI(option: TagOption): Promise<boolean> {
const response =
option.value === ''
? await api.delete(`/v1/tags/${option.tag_id}/options/${option.id}`)
: await api.put(`/v1/tags/${option.tag_id}/options/${option.id}`, option);
if (response.status !== status.NoContent) {
processError(response, 'Failed to update tag option');
return false;
}
return true;
}

View File

Before

Width:  |  Height:  |  Size: 271 B

After

Width:  |  Height:  |  Size: 271 B

View File

Before

Width:  |  Height:  |  Size: 217 B

After

Width:  |  Height:  |  Size: 217 B

View File

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 260 B

View File

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 632 B

View File

Before

Width:  |  Height:  |  Size: 469 B

After

Width:  |  Height:  |  Size: 469 B

View File

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 752 B

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { Card } from '../../../stores/interfaces'; import type { Card } from '$lib/stores/interfaces';
import projectTags from '../../../stores/projectTags'; import project_tags from '$lib/stores/project_tags';
import { currentModalCard, currentDraggedCard } from '../../../stores/smallStore'; import { currentDraggedCard, currentModalCard } from '$lib/stores/smallStore';
import ModalCard from './modal_card.svelte'; import ModalCard from './modal_card.svelte';
export let card: Card; export let card: Card;
@ -12,11 +12,11 @@
tabindex="0" tabindex="0"
draggable={true} draggable={true}
on:dragstart={() => currentDraggedCard.set(card)} on:dragstart={() => currentDraggedCard.set(card)}
on:click={() => ($currentModalCard = card.id)} on:click={() => currentModalCard.set(card.id)}
role="button" role="button"
on:keydown={(e) => { on:keydown={(e) => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
$currentModalCard = card.id; currentModalCard.set(card.id);
} }
}} }}
> >
@ -25,9 +25,9 @@
<div class="tags"> <div class="tags">
{#each card.tags as tag} {#each card.tags as tag}
{#if tag.option_id} {#if tag.option_id}
{#if $projectTags[tag.tag_id]} {#if $project_tags[tag.tag_id]}
<span class="tag" style="border: 1px solid #333" <span class="tag" style="border: 1px solid #333"
>{$projectTags[tag.tag_id]?.options.find((o) => o.id == tag.option_id)?.value}</span >{$project_tags[tag.tag_id]?.options.find((o) => o.id == tag.option_id)?.value}</span
> >
{/if} {/if}
{:else if tag.value} {:else if tag.value}

View File

@ -45,7 +45,7 @@
</div> </div>
</div> </div>
<div class="tags"> <div class="tags">
<ModalTags bind:card /> <ModalTags {card} />
</div> </div>
<div class="body"> <div class="body">
<textarea <textarea

View File

@ -11,6 +11,6 @@
{#if projectTag} {#if projectTag}
<tr> <tr>
<ModalTagTitle {projectTag} /> <ModalTagTitle {projectTag} />
<ModalTagValue {projectTag} bind:tagValue {card} /> <ModalTagValue {projectTag} {tagValue} {card} />
</tr> </tr>
{/if} {/if}

View File

@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import { tick } from 'svelte'; import { tick } from 'svelte';
import AddIcon from '../../../icons/addIcon.svelte';
import Menu from '../../../utils/menu.svelte';
import ModalTagTypes from './modal_tag_types.svelte'; import ModalTagTypes from './modal_tag_types.svelte';
import projectTags from '../../../../stores/projectTags'; import { toastAlert } from '$lib/utils/toasts';
import { toastAlert } from '../../../../utils/toasts'; import project_tags from '$lib/stores/project_tags';
import AddIcon from '$lib/components/icons/addIcon.svelte';
import Menu from '$lib/components/utils/menu.svelte';
export let projectId: number; export let projectId: number;
@ -27,7 +27,7 @@
toastAlert('Failed to create tag', `ProjectId is ${projectId}`); toastAlert('Failed to create tag', `ProjectId is ${projectId}`);
return; return;
} }
await projectTags.add(projectId, title, typeId); await project_tags.add(projectId, title, typeId);
isOpen = false; isOpen = false;
} }
</script> </script>

View File

@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import { tick } from 'svelte'; import { tick } from 'svelte';
import type { MeTag } from '../../../../stores/interfaces';
import Menu from '../../../utils/menu.svelte';
import projectTags from '../../../../stores/projectTags';
import { toastAlert } from '../../../../utils/toasts';
import ModalTagTypes from './modal_tag_types.svelte'; import ModalTagTypes from './modal_tag_types.svelte';
import type { MeTag } from '$lib/stores/interfaces';
import { toastAlert } from '$lib/utils/toasts';
import project_tags from '$lib/stores/project_tags';
import Menu from '$lib/components/utils/menu.svelte';
export let projectTag: MeTag; export let projectTag: MeTag;
@ -28,7 +28,7 @@
return; return;
} }
await projectTags.update(projectTag); await project_tags.update(projectTag);
lastTitle = projectTag.title; lastTitle = projectTag.title;
} }
@ -71,7 +71,7 @@
onChoice={async (id) => { onChoice={async (id) => {
projectTag.type = id; projectTag.type = id;
await projectTags.update(projectTag); await project_tags.update(projectTag);
}} }}
/> />
{#if askConfirm} {#if askConfirm}
@ -80,7 +80,7 @@
<div> <div>
<button <button
on:click={() => { on:click={() => {
projectTags.delete(projectTag.id); project_tags.delete(projectTag.id);
isMenuOpen = false; isMenuOpen = false;
}}>✓</button }}>✓</button
> >

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { getTagTypeFromId, tagTypes } from '../../../../utils/tagTypes'; import Menu from '$lib/components/utils/menu.svelte';
import Menu from '../../../utils/menu.svelte'; import { getTagTypeFromId, tagTypes } from '$lib/utils/tagTypes';
export let type: number; export let type: number;
export let isTagMenuOpen: boolean = false; export let isTagMenuOpen: boolean = false;

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Card, MeTag, TagValue } from '../../../../stores/interfaces'; import type { MeTag, TagValue, Card } from '$lib/stores/interfaces';
import { getTagTypeFromId } from '../../../../utils/tagTypes'; import { getTagTypeFromId } from '$lib/utils/tagTypes';
import SelectTags from './select_tags.svelte'; import SelectTags from './select_tags.svelte';
export let projectTag: MeTag; export let projectTag: MeTag;
@ -13,7 +13,7 @@
{#if tagType} {#if tagType}
<td> <td>
{#if tagType?.hasOptions} {#if tagType?.hasOptions}
<SelectTags multiple={false} {projectTag} {card} bind:tagValue /> <SelectTags multiple={false} {projectTag} {card} {tagValue} />
{:else if !tagType?.hasOptions} {:else if !tagType?.hasOptions}
<input /> <input />
{/if} {/if}

View File

@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import { updateCardTagApi } from '../../../../api/cards'; import { updateCardTagApi } from '$lib/api/cards';
import type { Card, MeTag, TagOption, TagValue } from '../../../../stores/interfaces'; import TrashIcon from '$lib/components/icons/trashIcon.svelte';
import projectTags from '../../../../stores/projectTags'; import Menu from '$lib/components/utils/menu.svelte';
import { cards } from '../../../../stores/smallStore'; import type { Card, MeTag, TagValue } from '$lib/stores/interfaces';
import api, { processError } from '../../../../utils/api'; import project_tags from '$lib/stores/project_tags';
import status from '../../../../utils/status'; import { cards } from '$lib/stores/smallStore';
import TrashIcon from '../../../icons/trashIcon.svelte'; import api, { processError } from '$lib/utils/api';
import Menu from '../../../utils/menu.svelte'; import status from '$lib/utils/status';
export const multiple: boolean = false; export const multiple: boolean = false;
export let card: Card; export let card: Card;
@ -81,7 +81,7 @@
function createOption() { function createOption() {
if (!newOption) return; if (!newOption) return;
projectTags.addOption(projectTag.id, newOption); project_tags.addOption(projectTag.id, newOption);
newOption = ''; newOption = '';
} }
</script> </script>
@ -127,7 +127,7 @@
<span class="value">{option.value}</span> <span class="value">{option.value}</span>
<button <button
on:click|stopPropagation={() => { on:click|stopPropagation={() => {
projectTags.deleteOption(projectTag.id, option.id); project_tags.deleteOption(projectTag.id, option.id);
}}><TrashIcon size={16} /></button }}><TrashIcon size={16} /></button
> >
</div> </div>

View File

@ -0,0 +1,17 @@
<script lang="ts">
import type { Card } from '$lib/stores/interfaces';
import ModalTag from './modal_tag.svelte';
import ModalNewTag from './modal_tag/modal_new_tag.svelte';
import ProjectTags from '$lib/stores/project_tags';
export let card: Card;
</script>
<table>
{#if card.tags}
{#each Object.values($ProjectTags) as projectTag}
<ModalTag tagValue={card.tags.find((t) => t.tag_id === projectTag.id)} {projectTag} {card} />
{/each}
{/if}
<ModalNewTag projectId={card.project_id} />
</table>

View File

@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import type { Card, TagValue } from '../../stores/interfaces';
import { cards, currentDraggedCard } from '../../stores/smallStore';
import CardC from './card/card.svelte'; import CardC from './card/card.svelte';
import AddIcon from '../icons/addIcon.svelte'; import AddIcon from '../icons/addIcon.svelte';
import projectTags from '../../stores/projectTags';
import { updateTagAPI as updateTagOptionAPI } from '../../api/tags'; import { updateTagAPI as updateTagOptionAPI } from '../../api/tags';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import { createCardTagApi, deleteCardTagApi, updateCardTagApi } from '../../api/cards'; import { createCardTagApi, deleteCardTagApi, updateCardTagApi } from '../../api/cards';
import type { Card, TagValue } from '../../stores/interfaces';
import projectTags from '../../stores/project_tags';
import { cards, currentDraggedCard } from '../../stores/smallStore';
export let projectId: number; export let projectId: number;
export let optionId: number | null = null; export let optionId: number | null = null;

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { Project, TagValue, View } from '../../stores/interfaces'; import type { Project, TagValue, View } from '../../stores/interfaces';
import { cards, currentView, views } from '../../stores/smallStore'; import { cards, currentView, views } from '../../stores/smallStore';
import projectTags from '../../stores/projectTags'; import projectTags from '../../stores/project_tags';
import GroupMenu from './card/header/menus/group_menu.svelte'; import GroupMenu from './card/header/menus/group_menu.svelte';
import SortMenu from './card/header/menus/sort_menu.svelte'; import SortMenu from './card/header/menus/sort_menu.svelte';

View File

@ -1,9 +1,9 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import Column from './column.svelte'; import Column from './column.svelte';
import type { Project, View } from '../../stores/interfaces'; import type { Project, View } from '$lib/stores/interfaces';
import projectTags from '../../stores/projectTags'; import projectTags from '$lib/stores/project_tags';
import { cards, currentView, views } from '../../stores/smallStore'; import { cards, currentView } from '$lib/stores/smallStore';
import Header from './header.svelte'; import Header from './header.svelte';
export let project: Project; export let project: Project;

View File

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import api, { processError } from '$lib/utils/api';
import status from '$lib/utils/status';
import type { Project } from '../../stores/interfaces'; import type { Project } from '../../stores/interfaces';
import api, { processError } from '../../utils/api';
import status from '../../utils/status';
export let project: Project; export let project: Project;
export let deleteProject: (project: Project) => void; export let deleteProject: (project: Project) => void;

View File

@ -1,13 +1,12 @@
<script lang="ts"> <script lang="ts">
import { onMount, tick } from 'svelte'; import { onMount } from 'svelte';
import api, { processError } from '../utils/api';
import type { Project, View } from '../stores/interfaces'; import type { Project, View } from '../stores/interfaces';
import { currentView, views } from '../stores/smallStore'; import { currentView, views } from '../stores/smallStore';
import ViewIcon from './icons/viewIcon.svelte'; import ViewIcon from './icons/viewIcon.svelte';
import projectTags from '../stores/projectTags';
import EditIcon from './icons/editIcon.svelte'; import EditIcon from './icons/editIcon.svelte';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import MenuOpener from './icons/menu_opener.svelte'; import MenuOpener from './icons/menu_opener.svelte';
import projectTags from '../stores/project_tags';
export let project: Project; export let project: Project;

View File

@ -1,7 +1,7 @@
import { get, writable } from 'svelte/store'; import { get, writable } from 'svelte/store';
import type { MeTag, TagOption } from './interfaces'; import type { MeTag, TagOption } from './interfaces';
import api, { processError } from '../utils/api'; import api, { processError } from '$lib/utils/api';
import status from '../utils/status'; import status from '$lib/utils/status';
import { cards } from './smallStore'; import { cards } from './smallStore';
const { subscribe, set, update } = writable({} as { [key: number]: MeTag }); const { subscribe, set, update } = writable({} as { [key: number]: MeTag });

View File

@ -1,9 +1,9 @@
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import { parseCards, type Card, type View, type TagValue } from './interfaces'; import { parseCards, type Card, type View, type TagValue } from './interfaces';
import { deleteCardApi, newCardApi, updateCardApi } from '../api/cards'; import api, { processError } from '$lib/utils/api';
import { getProjectCardsAPI } from '../api/projects'; import status from '$lib/utils/status';
import api, { processError } from '../utils/api'; import { getProjectCardsAPI } from '$lib/api/projects';
import status from '../utils/status'; import { deleteCardApi, newCardApi, updateCardApi } from '$lib/api/cards';
export const currentView = (() => { export const currentView = (() => {
const { subscribe, set, update } = writable(null as View | null); const { subscribe, set, update } = writable(null as View | null);
@ -82,7 +82,11 @@ export const views = (() => {
return true; return true;
}; };
const add = async (projectId: number, title: string, primaryTagId: number | null): Promise<View> => { const add = async (
projectId: number,
title: string,
primaryTagId: number | null
): Promise<View> => {
const response = await api.post(`/v1/views`, { const response = await api.post(`/v1/views`, {
title, title,
project_id: projectId, project_id: projectId,

View File

@ -1,7 +1,7 @@
import axios, { Axios, type AxiosResponse } from 'axios'; import axios, { Axios, type AxiosResponse } from 'axios';
import { backend } from '../stores/config';
import { toastAlert } from './toasts'; import { toastAlert } from './toasts';
import { setupCache } from 'axios-cache-interceptor'; import { setupCache } from 'axios-cache-interceptor';
import { backend } from '$lib/stores/config';
export default setupCache( export default setupCache(
new Axios({ new Axios({

View File

@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import { SvelteToast } from '@zerodevx/svelte-toast'; import { SvelteToast } from '@zerodevx/svelte-toast';
import type { Project } from '../stores/interfaces'; import type { Project } from '../lib/stores/interfaces';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import api, { processError } from '../utils/api'; import api, { processError } from '../lib/utils/api';
import SelectProject from '../components/projects/selectProject.svelte'; import SelectProject from '../lib/components/projects/selectProject.svelte';
import { toastAlert } from '../utils/toasts'; import { toastAlert } from '../lib/utils/toasts';
let projects: Project[]; let projects: Project[];

View File

@ -2,10 +2,10 @@
import { page } from '$app/stores'; import { page } from '$app/stores';
import { SvelteToast } from '@zerodevx/svelte-toast'; import { SvelteToast } from '@zerodevx/svelte-toast';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { getProjectAPI } from '../../api/projects'; import { getProjectAPI } from '$lib/api/projects';
import { type Project as P } from '../../stores/interfaces'; import { type Project as P } from '$lib/stores/interfaces';
import Sidebar from '../../components/sidebar.svelte'; import Sidebar from '$lib/components/sidebar.svelte';
import Project from '../../components/project/project.svelte'; import Project from '$lib/components/project/project.svelte';
let projectId: number = +$page.params.project; let projectId: number = +$page.params.project;