implemented adding required tasks to task
This commit is contained in:
@@ -53,7 +53,7 @@
|
||||
</tr>
|
||||
{/each}
|
||||
<tr>
|
||||
<td>{t('add_member')}</td>
|
||||
<td>{t('add_object',{object:t('member')})}</td>
|
||||
<td>
|
||||
<Autocomplete {getCandidates} {onSelect} />
|
||||
</td>
|
||||
|
||||
110
frontend/src/routes/task/RequiredTasks.svelte
Normal file
110
frontend/src/routes/task/RequiredTasks.svelte
Normal file
@@ -0,0 +1,110 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { useTinyRouter } from 'svelte-tiny-router';
|
||||
|
||||
import { api } from '../../urls.svelte';
|
||||
import { t } from '../../translations.svelte';
|
||||
|
||||
let { task = null } = $props();
|
||||
|
||||
let candidates = $state({});
|
||||
let error = $state(null);
|
||||
let key = $state(null);
|
||||
let requiredTasks = $state({});
|
||||
let router = useTinyRouter();
|
||||
let sortedTasks = $derived(Object.values(candidates).sort((a, b) => a.name.localeCompare(b.name)));
|
||||
let timer = null;
|
||||
|
||||
async function add(new_task_id){
|
||||
let url = api(`task/${new_task_id}`);
|
||||
let resp = await fetch(url,{ credentials : 'include' });
|
||||
if (resp.ok){
|
||||
error = null;
|
||||
let newTask = await resp.json();
|
||||
if (newTask.project_id != task.project_id){
|
||||
alert('prject mismatch!');
|
||||
return;
|
||||
}
|
||||
task.required_tasks_ids.push(new_task_id);
|
||||
requiredTasks[new_task_id] = newTask;
|
||||
url = api(`task/${task.id}`);
|
||||
resp = await fetch(url,{
|
||||
credentials : 'include',
|
||||
method : 'PATCH',
|
||||
body : JSON.stringify({required_tasks_ids:task.required_tasks_ids})
|
||||
});
|
||||
delete candidates[new_task_id];
|
||||
}
|
||||
if (!resp.ok) {
|
||||
error = await resp.text();
|
||||
}
|
||||
}
|
||||
|
||||
async function doSearch(){
|
||||
if (!key.trim()) {
|
||||
candidates = {};
|
||||
return;
|
||||
}
|
||||
const data = { key : key, project_id : task?.project_id };
|
||||
const url = api('task/search');
|
||||
const res = await fetch(url,{
|
||||
credentials : 'include',
|
||||
method : 'POST',
|
||||
body : JSON.stringify(data)
|
||||
});
|
||||
if (res.ok) {
|
||||
error = null;
|
||||
candidates = await res.json();
|
||||
for (var taskId of Object.keys(requiredTasks)) delete candidates[taskId];
|
||||
delete candidates[task.id];
|
||||
} else {
|
||||
error = await res.text();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTasks(){
|
||||
if (!task || !task.required_tasks_ids || !task.required_tasks_ids.length) return;
|
||||
const url = api('task/list');
|
||||
const res = await fetch(url,{
|
||||
credentials : 'include',
|
||||
method : 'POST',
|
||||
body : JSON.stringify({ids:task.required_tasks_ids})
|
||||
});
|
||||
if (res.ok){
|
||||
error = null;
|
||||
requiredTasks = await res.json();
|
||||
} else {
|
||||
error = await res.text();
|
||||
}
|
||||
}
|
||||
|
||||
function oninput(){
|
||||
if (timer) clearTimeout(timer);
|
||||
timer = setTimeout(doSearch,1000);
|
||||
}
|
||||
|
||||
function openTask(e){
|
||||
e.preventDefault();
|
||||
let href = e.target.getAttribute('href');
|
||||
if (href) router.navigate(href);
|
||||
return false;
|
||||
}
|
||||
|
||||
onMount(loadTasks);
|
||||
</script>
|
||||
|
||||
{#if requiredTasks}
|
||||
<ul class="required task list">
|
||||
{#each Object.values(requiredTasks) as task}
|
||||
<li class="task" >
|
||||
<a href="/task/{task.id}/view" onclick={openTask} >{task.name}</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{t('add_object',{object:t('task')})}: <input type="text" bind:value={key} {oninput} />
|
||||
<div class="candidate task list">
|
||||
{#each sortedTasks as task}
|
||||
<div class="task" onclick={e => add(task.id)}>{task.name}</div>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -12,6 +12,7 @@
|
||||
import PermissionEditor from '../../Components/PermissionEditor.svelte';
|
||||
import Notes from '../notes/RelatedNotes.svelte';
|
||||
import StateSelector from '../../Components/StateSelector.svelte';
|
||||
import RequiredTasks from './RequiredTasks.svelte';
|
||||
import TagList from '../tags/TagList.svelte';
|
||||
import TaskList from './TaskList.svelte';
|
||||
|
||||
@@ -301,6 +302,14 @@
|
||||
<input type="number" bind:value={task.estimated_time} onchange={() => update({estimated_time:task.estimated_time})} /> h
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
{t('depends_on')}
|
||||
</th>
|
||||
<td>
|
||||
<RequiredTasks {task} />
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
<tr>
|
||||
<th>
|
||||
|
||||
Reference in New Issue
Block a user