Group button

This commit is contained in:
Brieuc Dubois 2024-01-02 00:42:33 +01:00
parent e8ec7919d9
commit 5bc43aaba2
5 changed files with 137 additions and 29 deletions

View File

@ -5,6 +5,7 @@
<link rel="icon" href="/img/favicon.png" /> <link rel="icon" href="/img/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="/css/global.css" /> <link rel="stylesheet" type="text/css" href="/css/global.css" />
<title>Focus.</title>
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover">

View File

@ -0,0 +1,56 @@
<script lang="ts">
export let isOpen = false;
export let choices: { id: number; value: string }[] = [];
export let onChoice = (id: number) => {};
export let currentChoice: number = -1;
</script>
{#if isOpen}
<div class="menu">
{#each choices as choice}
<div
class="menu-item"
on:click={() => onChoice(choice.id)}
role="button"
tabindex="0"
on:keypress={(e) => {
if (e.key === 'Enter') {
onChoice(choice.id);
}
}}
>
<span>{choice.value}</span>
{#if currentChoice === choice.id}
<span class="mark"></span>
{/if}
</div>
{/each}
</div>
{/if}
<style lang="less">
.menu {
position: absolute;
display: flex;
flex-direction: column;
background-color: #222;
border: 1px solid #666;
padding: 10px 0;
.menu-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 5px 20px;
&:hover {
cursor: pointer;
background-color: #333;
}
}
.mark {
margin-left: 20px;
}
}
</style>

View File

@ -1,10 +1,13 @@
<script lang="ts"> <script lang="ts">
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import type { Project, TagValue } from '../../stores/interfaces'; import type { Project, TagValue, View } from '../../stores/interfaces';
import { cards } from '../../stores/smallStore'; import { cards, currentView } from '../../stores/smallStore';
import projectTags from '../../stores/projectTags'; import projectTags from '../../stores/projectTags';
import GroupMenu from './groupMenu.svelte';
export let project: Project; export let project: Project;
export let currentTagId: number;
let groupMenuOpen = false;
function getEmptyTags(): TagValue[] { function getEmptyTags(): TagValue[] {
const tags: TagValue[] = []; const tags: TagValue[] = [];
@ -18,16 +21,41 @@
} }
return tags; return tags;
} }
async function setGroup(id: number): Promise<boolean> {
if ($currentView == null) return false;
return await currentView.update({
...$currentView,
primary_tag_id: id
});
}
</script> </script>
<header> <header>
<h2>{project.title}</h2> <h2>{project.title}</h2>
<nav> <nav>
<span>Group</span> <div>
<span>Sub-group</span> <button
<span>Filter</span> on:click={() => (groupMenuOpen = !groupMenuOpen)}
<span>Sort</span> class:defined={$currentView?.primary_tag_id}>Group</button
<button on:click={async () => cards.add(project.id, getEmptyTags())}>New</button> >
<GroupMenu
isOpen={groupMenuOpen}
choices={Object.values($projectTags).map((tag) => ({ id: tag.id, value: tag.title }))}
onChoice={async (id) => {
if (!(await setGroup(id))) return;
groupMenuOpen = false;
}}
currentChoice={currentTagId}
/>
</div>
<div>
<button class:disabled={true}>Sub-group</button>
</div>
<button>Filter</button>
<button>Sort</button>
<button id="newButton" on:click={async () => cards.add(project.id, getEmptyTags())}>New</button>
</nav> </nav>
</header> </header>
@ -45,32 +73,34 @@
} }
nav { nav {
* { display: flex;
cursor: pointer; flex-direction: row;
} align-items: center;
span {
margin-right: 10px;
color: #aaa;
padding: 5px 10px;
border-radius: 7px;
&:hover {
// background-color: #fff2;
}
}
button { button {
background: #324067; cursor: pointer;
color: inherit; color: #aaa;
padding: 5px 10px;
margin-left: 10px;
border-radius: 7px;
border: none; border: none;
border-radius: 10px; background-color: transparent;
padding: 10px 20px;
font-size: inherit; font-size: inherit;
&:hover { &.defined {
// background-color: #3a4a77; color: #6481cc;
} }
&.disabled {
color: #555;
cursor: not-allowed;
}
}
#newButton {
background: #324067;
border-radius: 10px;
padding: 10px 20px;
} }
} }
</style> </style>

View File

@ -25,8 +25,8 @@
{#if project} {#if project}
<section> <section>
<Header {project} />
{#if view && $projectTags[view.primary_tag_id] && $cards} {#if view && $projectTags[view.primary_tag_id] && $cards}
<Header {project} currentTagId={view.primary_tag_id} />
<div class="grid"> <div class="grid">
{#each $projectTags[view.primary_tag_id].options as option} {#each $projectTags[view.primary_tag_id].options as option}
<Column <Column

View File

@ -2,8 +2,29 @@ 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 } from '../api/cards'; import { deleteCardApi, newCardApi } from '../api/cards';
import { getProjectCardsAPI } from '../api/projects'; import { getProjectCardsAPI } from '../api/projects';
import api, { processError } from '../utils/api';
import status from '../utils/status';
export const currentView = writable(null as View | null); export const currentView = (() => {
const { subscribe, set, update } = writable(null as View | null);
return {
subscribe,
set,
update: async (view: View): Promise<boolean> => {
const response = await api.put(`/v1/views/${view.id}`, view);
if (response.status !== status.NoContent) {
processError(response, 'Failed to update view');
return false;
}
set(view);
return true;
}
};
})();
export const currentModalCard = writable(-1); export const currentModalCard = writable(-1);