|
|
|
|
@ -4,8 +4,10 @@
@@ -4,8 +4,10 @@
|
|
|
|
|
|
|
|
|
|
import { api } from '../../urls.svelte.js'; |
|
|
|
|
import { t } from '../../translations.svelte.js'; |
|
|
|
|
import { user } from '../../user.svelte.js'; |
|
|
|
|
|
|
|
|
|
import Card from './KanbanCard.svelte'; |
|
|
|
|
import LineEditor from '../../Components/LineEditor.svelte'; |
|
|
|
|
|
|
|
|
|
let { id } = $props(); |
|
|
|
|
|
|
|
|
|
@ -21,6 +23,34 @@
@@ -21,6 +23,34 @@
|
|
|
|
|
let users = {}; |
|
|
|
|
let ready = $state(false); |
|
|
|
|
|
|
|
|
|
async function create(name,user_id,state){ |
|
|
|
|
var url = api('task/add'); |
|
|
|
|
let task = { |
|
|
|
|
description: '', |
|
|
|
|
members : {}, |
|
|
|
|
name: name, |
|
|
|
|
project_id: +id, |
|
|
|
|
status : { code : +state} |
|
|
|
|
} |
|
|
|
|
task.members[user_id] = { permission: { name : 'ASSIGNEE' }}; |
|
|
|
|
task.members[user.id] = { permission: { name : 'OWNER' }}; |
|
|
|
|
const resp = await fetch(url,{ |
|
|
|
|
credentials:'include', |
|
|
|
|
method:'POST', |
|
|
|
|
body: JSON.stringify(task) |
|
|
|
|
}); |
|
|
|
|
if (resp.ok) { |
|
|
|
|
task = await resp.json(); |
|
|
|
|
task.assignee = user_id; |
|
|
|
|
if (!tasks[user_id]) tasks[user_id] = {}; |
|
|
|
|
if (!tasks[user_id][state]) tasks[user_id][state] = {}; |
|
|
|
|
tasks[user_id][state][task.id] = task; |
|
|
|
|
error = null; |
|
|
|
|
} else { |
|
|
|
|
error = await resp.text(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function load(){ |
|
|
|
|
await loadProject(); |
|
|
|
|
await loadStates(); |
|
|
|
|
@ -88,13 +118,13 @@
@@ -88,13 +118,13 @@
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function drop(user,state){ |
|
|
|
|
async function drop(user_id,state){ |
|
|
|
|
let task = dragged; |
|
|
|
|
dragged = null; |
|
|
|
|
highlight = {}; |
|
|
|
|
if (task.assignee == user && task.status.code == state) return; // no change |
|
|
|
|
if (task.assignee == user_id && task.status.code == state) return; // no change |
|
|
|
|
let patch = {members:{},status:+state} |
|
|
|
|
patch.members[user] = 'ASSIGNEE'; |
|
|
|
|
patch.members[user_id] = 'ASSIGNEE'; |
|
|
|
|
|
|
|
|
|
const url = api(`task/${task.id}`); |
|
|
|
|
const resp = await fetch(url,{ |
|
|
|
|
@ -104,10 +134,10 @@
@@ -104,10 +134,10 @@
|
|
|
|
|
}); |
|
|
|
|
if (resp.ok){ |
|
|
|
|
delete tasks[task.assignee][task.status.code][task.id] |
|
|
|
|
if (!tasks[user]) tasks[user] = {} |
|
|
|
|
if (!tasks[user][state]) tasks[user][state] = {} |
|
|
|
|
tasks[user][state][task.id] = task; |
|
|
|
|
task.assignee = user; |
|
|
|
|
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 { |
|
|
|
|
@ -115,9 +145,9 @@
@@ -115,9 +145,9 @@
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function hover(ev,user,state){ |
|
|
|
|
function hover(ev,user_id,state){ |
|
|
|
|
ev.preventDefault(); |
|
|
|
|
highlight = {user:user,state:state}; |
|
|
|
|
highlight = {user:user_id,state:state}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onMount(load); |
|
|
|
|
@ -142,11 +172,14 @@
@@ -142,11 +172,14 @@
|
|
|
|
|
<div class="user">{users[uid]}</div> |
|
|
|
|
{#each Object.entries(states) as [state,name]} |
|
|
|
|
<div class={[state, highlight.user == uid && highlight.state == state ? 'highlight':'']} ondragover={ev => hover(ev,uid,state)} ondrop={ev => drop(uid,state)} > |
|
|
|
|
{#if stateList[state]} |
|
|
|
|
{#each Object.values(stateList[state]).sort((a,b) => a.name.localeCompare(b.name)) as task} |
|
|
|
|
<Card onclick={() => router.navigate(`/task/${task.id}/view`)} ondragstart={ev => dragged=task} {task} /> |
|
|
|
|
{/each} |
|
|
|
|
{/if} |
|
|
|
|
{#if stateList[state]} |
|
|
|
|
{#each Object.values(stateList[state]).sort((a,b) => a.name.localeCompare(b.name)) as task} |
|
|
|
|
<Card onclick={() => router.navigate(`/task/${task.id}/view`)} ondragstart={ev => dragged=task} {task} /> |
|
|
|
|
{/each} |
|
|
|
|
{/if} |
|
|
|
|
<div class="add_task"> |
|
|
|
|
<LineEditor value={t('add_task')} editable={true} onSet={(name) => create(name,uid,state)}/> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
{/each} |
|
|
|
|
{/each} |
|
|
|
|
|