working on tagging system
This commit is contained in:
@@ -11,17 +11,17 @@
|
||||
|
||||
let { id } = $props();
|
||||
|
||||
let dragged = null;
|
||||
let error = $state(null);
|
||||
let highlight = $state({});
|
||||
let project = $state(null);
|
||||
let ready = $state(false);
|
||||
let router = useTinyRouter();
|
||||
let states = $state(null);
|
||||
let tasks = $state({});
|
||||
let highlight = $state({});
|
||||
let users = {};
|
||||
|
||||
let columns = $derived(states?Object.keys(states).length+1:1);
|
||||
let dragged = null;
|
||||
let users = {};
|
||||
let ready = $state(false);
|
||||
|
||||
async function create(name,user_id,state){
|
||||
var url = api('task/add');
|
||||
@@ -51,11 +51,39 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function drop(user_id,state){
|
||||
let task = dragged;
|
||||
dragged = null;
|
||||
highlight = {};
|
||||
if (task.assignee == user_id && task.status.code == state) return; // no change
|
||||
let patch = {members:{},status:+state}
|
||||
patch.members[user_id] = 'ASSIGNEE';
|
||||
|
||||
const url = api(`task/${task.id}`);
|
||||
const resp = await fetch(url,{
|
||||
credentials: 'include',
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(patch)
|
||||
});
|
||||
if (resp.ok){
|
||||
delete tasks[task.assignee][task.status.code][task.id]
|
||||
if (!tasks[user_id]) tasks[user_id] = {}
|
||||
if (!tasks[user_id][state]) tasks[user_id][state] = {}
|
||||
tasks[user_id][state][task.id] = task;
|
||||
task.assignee = user_id;
|
||||
task.status = {code:state,name:states[state]};
|
||||
error = null;
|
||||
} else {
|
||||
error = await resp.text();
|
||||
}
|
||||
}
|
||||
|
||||
async function load(){
|
||||
await loadProject();
|
||||
await loadStates();
|
||||
await loadTasks({project_id:+id,parent_task_id:0});
|
||||
ready = true;
|
||||
loadTags();
|
||||
}
|
||||
|
||||
async function loadProject(){
|
||||
@@ -85,6 +113,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTag(task){
|
||||
const url = api(`tags/task/${task.id}`);
|
||||
const resp = await fetch(url,{credentials:'include'});
|
||||
if (resp.ok) {
|
||||
const tags = await resp.json();
|
||||
if (tags.length) task.tags = tags.sort();
|
||||
}
|
||||
}
|
||||
|
||||
function loadTags(){
|
||||
for (let uid of Object.keys(tasks)){
|
||||
for (let state of Object.keys(tasks[uid])){
|
||||
for (let tid of Object.keys(tasks[uid][state])){
|
||||
const task = tasks[uid][state][tid];
|
||||
loadTag(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTasks(selector){
|
||||
const url = api('task/list');
|
||||
selector.show_closed = true;
|
||||
@@ -118,32 +166,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function drop(user_id,state){
|
||||
let task = dragged;
|
||||
dragged = null;
|
||||
highlight = {};
|
||||
if (task.assignee == user_id && task.status.code == state) return; // no change
|
||||
let patch = {members:{},status:+state}
|
||||
patch.members[user_id] = 'ASSIGNEE';
|
||||
|
||||
const url = api(`task/${task.id}`);
|
||||
const resp = await fetch(url,{
|
||||
credentials: 'include',
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify(patch)
|
||||
});
|
||||
if (resp.ok){
|
||||
delete tasks[task.assignee][task.status.code][task.id]
|
||||
if (!tasks[user_id]) tasks[user_id] = {}
|
||||
if (!tasks[user_id][state]) tasks[user_id][state] = {}
|
||||
tasks[user_id][state][task.id] = task;
|
||||
task.assignee = user_id;
|
||||
task.status = {code:state,name:states[state]};
|
||||
error = null;
|
||||
} else {
|
||||
error = await resp.text();
|
||||
}
|
||||
}
|
||||
|
||||
function hover(ev,user_id,state){
|
||||
ev.preventDefault();
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
({task.estimated_time} h)
|
||||
</span>
|
||||
{/if}
|
||||
{#if task.tags}
|
||||
<span class="tags">
|
||||
{task.tags.join(' ')}
|
||||
</span>
|
||||
{/if}
|
||||
{#if task.due_date}
|
||||
<span class="due_date">
|
||||
{#if task.start_date}
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
async function loadTags(){
|
||||
const url = api(`tags/${module}/${id}`);
|
||||
async function loadTags(entityId){
|
||||
const url = api(`tags/${module}/${entityId}`);
|
||||
const resp = await fetch(url,{credentials:'include'});
|
||||
if (resp.ok) {
|
||||
tags = await resp.json();
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
onMount(loadTags);
|
||||
$effect(() => loadTags(id));
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -290,7 +290,7 @@
|
||||
{t('tags')}
|
||||
</th>
|
||||
<td class="tags">
|
||||
<TagList module="task", {id} user_list={Object.keys(task.members).map(id => +id)} />
|
||||
<TagList module="task" {id} user_list={Object.keys(task.members).map(id => +id)} />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -45,6 +45,7 @@ footer {
|
||||
}
|
||||
nav {
|
||||
position: sticky;
|
||||
z-index: 100;
|
||||
top: 0;
|
||||
background: #26220c;
|
||||
padding: 5px;
|
||||
@@ -184,6 +185,19 @@ textarea{
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.kanban .tags {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
font-size: 0.5em;
|
||||
}
|
||||
.kanban .user,
|
||||
.kanban .head {
|
||||
position: sticky;
|
||||
top: 50px;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.project th,
|
||||
.task th{
|
||||
text-align: right;
|
||||
|
||||
Reference in New Issue
Block a user