Compare commits
8 Commits
module/sto
...
feature/li
| Author | SHA1 | Date | |
|---|---|---|---|
| 146ea80e4e | |||
| 21759d1b12 | |||
| ba531a0ab1 | |||
| 7e02fe17e9 | |||
| 37e6ccd71a | |||
| 11c0983dac | |||
| daa25044a4 | |||
| c37df2ddec |
@@ -185,6 +185,10 @@
|
||||
highlight.archive = true;
|
||||
}
|
||||
|
||||
function is_custom(state){
|
||||
return [10,20,40,60,100].includes(state);
|
||||
}
|
||||
|
||||
function openTask(task_id){
|
||||
window.open(`/task/${task_id}/view`, '_blank').focus();
|
||||
}
|
||||
@@ -244,7 +248,7 @@
|
||||
{#each users as u}
|
||||
<div class="user">{u.name}</div>
|
||||
{#each Object.entries(project.allowed_states) as [state,name]}
|
||||
<div class={['state_'+state, highlight.user == u.id && highlight.state == state ? 'highlight':'']} ondragover={ev => hover(ev,u.id,state)} ondragleave={e => delete highlight.user} ondrop={ev => drop(u.id,state)} >
|
||||
<div class={['state_'+state, is_custom(state) ? '':'state_custom' ,highlight.user == u.id && highlight.state == state ? 'highlight':'']} ondragover={ev => hover(ev,u.id,state)} ondragleave={e => delete highlight.user} ondrop={ev => drop(u.id,state)} >
|
||||
{#each Object.values(tasks[u.id][state]).sort(byName) as task}
|
||||
{#if !filter || task.name.toLowerCase().includes(filter) || (task.tags && task.tags.filter(tag => tag.toLowerCase().includes(filter)).length)}
|
||||
<Card onclick={e => openTask(task.id)} ondragstart={ev => dragged=task} {task} tag_colors={project.tag_colors} />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { useTinyRouter } from 'svelte-tiny-router';
|
||||
|
||||
import { api } from '../../urls.svelte.js';
|
||||
import { api, get, patch } from '../../urls.svelte.js';
|
||||
import { error, yikes } from '../../warn.svelte';
|
||||
import { t } from '../../translations.svelte.js';
|
||||
|
||||
@@ -23,16 +23,10 @@
|
||||
const prj = projects[task.project_id];
|
||||
const stat = Object.keys(prj.allowed_states).find(k => prj.allowed_states[k] === state);
|
||||
const url = api(`task/${tid}`);
|
||||
const resp = await fetch(url,{
|
||||
credentials : 'include',
|
||||
method : 'PATCH',
|
||||
body : JSON.stringify({status:stat})
|
||||
});
|
||||
const resp = await patch(url,{status:stat});
|
||||
if (resp.ok){
|
||||
tasks[idx] = await resp.json();
|
||||
} else {
|
||||
error(resp);
|
||||
}
|
||||
} else error(resp);
|
||||
}
|
||||
|
||||
function abort(idx){
|
||||
@@ -66,17 +60,15 @@
|
||||
|
||||
async function loadProject(pid){
|
||||
const url = api(`project/${pid}`);
|
||||
const resp = await fetch(url,{credentials:'include'});
|
||||
const resp = await get(url);
|
||||
if (resp.ok){
|
||||
projects[pid] = await resp.json();
|
||||
} else {
|
||||
error(resp);
|
||||
}
|
||||
} else error(resp);
|
||||
}
|
||||
|
||||
async function load(){
|
||||
const url = api(`task?offset=${bounds.offset}&limit=${bounds.limit}`);
|
||||
const resp = await fetch(url,{credentials:'include'});
|
||||
const resp = await get(url);
|
||||
if (resp.ok){
|
||||
let newTasks = await resp.json();
|
||||
if (bounds.offset == 0) {
|
||||
@@ -93,9 +85,7 @@
|
||||
bounds.offset += bounds.limit;
|
||||
load();
|
||||
}
|
||||
} else {
|
||||
error(resp);
|
||||
}
|
||||
} else error(resp);
|
||||
}
|
||||
|
||||
function open(idx){
|
||||
@@ -139,13 +129,14 @@
|
||||
<th>{t('state')}</th>
|
||||
<th>{t('start_date')}</th>
|
||||
<th>{t('due_date')}</th>
|
||||
<th>{t('users')}</th>
|
||||
<th>{t('actions')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each tasks as task,idx}
|
||||
{#if task.status > 10 && task.status < 60 && !task.no_index && projects[task.project_id]?.status < 60 && !hidden[task.id] && filterApplies(task)}
|
||||
<tr>
|
||||
<tr title={task.description.source}>
|
||||
<td onclick={() => go('task',task.id)}>{task.name}</td>
|
||||
<td>
|
||||
<a href="#" onclick={() => go('project',task.project_id)}> {projects[task.project_id]?.name}</a>
|
||||
@@ -162,6 +153,16 @@
|
||||
<td>
|
||||
{task.due_date}
|
||||
</td>
|
||||
<td>
|
||||
<ul>
|
||||
{#each Object.values(task.members) as member}
|
||||
<li>
|
||||
{member.user.name}:
|
||||
{t('permission_'+member.permission.name.toLowerCase())}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</td>
|
||||
<td>
|
||||
<button class="symbol" onclick={() => edit(task.id)} title={t('edit')} ></button>
|
||||
<button class="symbol" onclick={() => postpone(idx)} title={t('postpone')} ></button>
|
||||
|
||||
@@ -199,12 +199,9 @@ public class TaskModule extends BaseHandler implements TaskService {
|
||||
} catch (NumberFormatException e) {
|
||||
throw invalidFieldException(LIMIT, "number");
|
||||
}
|
||||
Set<Long> projectIds = projectService().listUserProjects(user.id(), true).keySet();
|
||||
var list = taskDb.listUserTasks(user.id(), limit, offset, false).stream()
|
||||
.filter(task -> projectIds.contains(task.projectId())) // drop tasks assigned to project we are not member of
|
||||
.map(Task::toMap)
|
||||
.toList();
|
||||
return sendContent(ex, list);
|
||||
var tasks = taskDb.listUserTasks(user.id(), limit, offset, false);
|
||||
var mapped = loadMembers(tasks).stream().map(Task::toMap);
|
||||
return sendContent(ex, mapped);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -139,6 +139,10 @@ tr:hover .taglist .tag button {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.states .active{
|
||||
background: red;
|
||||
}
|
||||
|
||||
.taglist .tag{
|
||||
border-color: red;
|
||||
}
|
||||
@@ -186,8 +190,6 @@ tr:hover .taglist .tag button {
|
||||
border-color: 1px solid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.warn {
|
||||
background-color: yellow;
|
||||
color: black;
|
||||
@@ -201,6 +203,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p10 .name{
|
||||
color: #ffa736;
|
||||
}
|
||||
.kanban .state_custom .box.p10,
|
||||
.kanban .state_20 .box.p10,
|
||||
.kanban .state_40 .box.p10{
|
||||
border: 5px solid #ffa736;
|
||||
@@ -209,6 +212,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p20 .name{
|
||||
color: #ff8f00;
|
||||
}
|
||||
.kanban .state_custom .box.p20,
|
||||
.kanban .state_20 .box.p20,
|
||||
.kanban .state_40 .box.p20{
|
||||
border: 5px solid #ff8f00;
|
||||
@@ -217,6 +221,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p30 .name{
|
||||
color: #ff7b06;
|
||||
}
|
||||
.kanban .state_custom .box.p30,
|
||||
.kanban .state_20 .box.p30,
|
||||
.kanban .state_40 .box.p30{
|
||||
border: 5px solid #ff7b06;
|
||||
@@ -225,6 +230,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p40 .name{
|
||||
color: #ff6306;
|
||||
}
|
||||
.kanban .state_custom .box.p40,
|
||||
.kanban .state_20 .box.p40,
|
||||
.kanban .state_40 .box.p40{
|
||||
border: 5px solid #ff6306;
|
||||
@@ -233,6 +239,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p50 .name{
|
||||
color: #ff4c06;
|
||||
}
|
||||
.kanban .state_custom .box.p50,
|
||||
.kanban .state_20 .box.p50,
|
||||
.kanban .state_40 .box.p50{
|
||||
border: 5px solid #ff4c06;
|
||||
@@ -241,6 +248,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p60 .name{
|
||||
color: #ff3506;
|
||||
}
|
||||
.kanban .state_custom .box.p60,
|
||||
.kanban .state_20 .box.p60,
|
||||
.kanban .state_40 .box.p60{
|
||||
border: 5px solid #ff3506;
|
||||
@@ -249,6 +257,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p70 .name{
|
||||
color: #ff0000;
|
||||
}
|
||||
.kanban .state_custom .box.p70,
|
||||
.kanban .state_20 .box.p70,
|
||||
.kanban .state_40 .box.p70{
|
||||
border: 5px solid #ff0000;
|
||||
@@ -257,6 +266,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p80 .name{
|
||||
color: #df153b;
|
||||
}
|
||||
.kanban .state_custom .box.p80,
|
||||
.kanban .state_20 .box.p80,
|
||||
.kanban .state_40 .box.p80{
|
||||
border: 5px solid #df153b;
|
||||
@@ -266,6 +276,7 @@ tr:hover .taglist .tag button {
|
||||
background-color: #991c34;
|
||||
color: #ffff00;
|
||||
}
|
||||
.kanban .state_custom .box.p90,
|
||||
.kanban .state_20 .box.p90,
|
||||
.kanban .state_40 .box.p90{
|
||||
border: 5px solid #991c34;
|
||||
@@ -275,6 +286,7 @@ tr:hover .taglist .tag button {
|
||||
background-color: #733440;
|
||||
color: #ffff00;
|
||||
}
|
||||
.kanban .state_custom .box.p100,
|
||||
.kanban .state_20 .box.p100,
|
||||
.kanban .state_40 .box.p100{
|
||||
border: 5px solid #733440;
|
||||
@@ -282,4 +294,4 @@ tr:hover .taglist .tag button {
|
||||
|
||||
.vcard span.inactive{
|
||||
color: #222200;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,6 @@ tr:hover .taglist .tag button {
|
||||
background: black;
|
||||
}
|
||||
|
||||
|
||||
.version a.selected{
|
||||
border-color: orange;
|
||||
}
|
||||
@@ -194,6 +193,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p10 .name{
|
||||
color: #fff066;
|
||||
}
|
||||
.kanban .state_custom .box.p10,
|
||||
.kanban .state_20 .box.p10,
|
||||
.kanban .state_40 .box.p10{
|
||||
border: 5px solid #fff066;
|
||||
@@ -202,6 +202,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p20 .name{
|
||||
color: #ffe706;
|
||||
}
|
||||
.kanban .state_custom .box.p20,
|
||||
.kanban .state_20 .box.p20,
|
||||
.kanban .state_40 .box.p20{
|
||||
border: 5px solid #ffe706;
|
||||
@@ -210,6 +211,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p30 .name{
|
||||
color: #ffa906;
|
||||
}
|
||||
.kanban .state_custom .box.p30,
|
||||
.kanban .state_20 .box.p30,
|
||||
.kanban .state_40 .box.p30{
|
||||
border: 5px solid #ffa906;
|
||||
@@ -218,6 +220,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p40 .name{
|
||||
color: #ff8606;
|
||||
}
|
||||
.kanban .state_custom .box.p40,
|
||||
.kanban .state_20 .box.p40,
|
||||
.kanban .state_40 .box.p40{
|
||||
border: 5px solid #ff8606;
|
||||
@@ -226,6 +229,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p50 .name{
|
||||
color: #ff4c06;
|
||||
}
|
||||
.kanban .state_custom .box.p50,
|
||||
.kanban .state_20 .box.p50,
|
||||
.kanban .state_40 .box.p50{
|
||||
border: 5px solid #ff4c06;
|
||||
@@ -234,6 +238,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p60 .name{
|
||||
color: #ff3506;
|
||||
}
|
||||
.kanban .state_custom .box.p60,
|
||||
.kanban .state_20 .box.p60,
|
||||
.kanban .state_40 .box.p60{
|
||||
border: 5px solid #ff3506;
|
||||
@@ -242,6 +247,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p70 .name{
|
||||
color: #ff0000;
|
||||
}
|
||||
.kanban .state_custom .box.p70,
|
||||
.kanban .state_20 .box.p70,
|
||||
.kanban .state_40 .box.p70{
|
||||
border: 5px solid #ff0000;
|
||||
@@ -250,6 +256,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p80 .name{
|
||||
color: #df153b;
|
||||
}
|
||||
.kanban .state_custom .box.p80,
|
||||
.kanban .state_20 .box.p80,
|
||||
.kanban .state_40 .box.p80{
|
||||
border: 5px solid #df153b;
|
||||
@@ -259,6 +266,7 @@ tr:hover .taglist .tag button {
|
||||
background-color: #991c34;
|
||||
color: #ffff00;
|
||||
}
|
||||
.kanban .state_custom .box.p90,
|
||||
.kanban .state_20 .box.p90,
|
||||
.kanban .state_40 .box.p90{
|
||||
border: 5px solid #991c34;
|
||||
@@ -268,6 +276,7 @@ tr:hover .taglist .tag button {
|
||||
background-color: #733440;
|
||||
color: #ffff00;
|
||||
}
|
||||
.kanban .state_custom .box.p100,
|
||||
.kanban .state_20 .box.p100,
|
||||
.kanban .state_40 .box.p100{
|
||||
border: 5px solid #733440;
|
||||
|
||||
@@ -124,6 +124,10 @@ tr:hover .taglist .tag button {
|
||||
border-color: blue;
|
||||
}
|
||||
|
||||
.states .active{
|
||||
background: #dfe4ff;
|
||||
}
|
||||
|
||||
.taglist .tag{
|
||||
border-color: blue;
|
||||
}
|
||||
@@ -179,6 +183,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p10 .name{
|
||||
color: #c9fbb2;
|
||||
}
|
||||
.kanban .state_custom .box.p10,
|
||||
.kanban .state_20 .box.p10,
|
||||
.kanban .state_40 .box.p10{
|
||||
border: 5px solid #c9fbb2;
|
||||
@@ -187,6 +192,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p20 .name{
|
||||
color: #cbff57;
|
||||
}
|
||||
.kanban .state_custom .box.p20,
|
||||
.kanban .state_20 .box.p20,
|
||||
.kanban .state_40 .box.p20{
|
||||
border: 5px solid #cbff57;
|
||||
@@ -195,6 +201,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p30 .name{
|
||||
color: #dfff44;
|
||||
}
|
||||
.kanban .state_custom .box.p30,
|
||||
.kanban .state_20 .box.p30,
|
||||
.kanban .state_40 .box.p30{
|
||||
border: 5px solid #dfff44;
|
||||
@@ -203,6 +210,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p40 .name{
|
||||
color: #f8ff29;
|
||||
}
|
||||
.kanban .state_custom .box.p40,
|
||||
.kanban .state_20 .box.p40,
|
||||
.kanban .state_40 .box.p40{
|
||||
border: 5px solid #f8ff29;
|
||||
@@ -211,6 +219,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p50 .name{
|
||||
color: #ffdb1b;
|
||||
}
|
||||
.kanban .state_custom .box.p50,
|
||||
.kanban .state_20 .box.p50,
|
||||
.kanban .state_40 .box.p50{
|
||||
border: 5px solid #ffdb1b;
|
||||
@@ -219,6 +228,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p60 .name{
|
||||
color: #ff9309;
|
||||
}
|
||||
.kanban .state_custom .box.p60,
|
||||
.kanban .state_20 .box.p60,
|
||||
.kanban .state_40 .box.p60{
|
||||
border: 5px solid #ff9309;
|
||||
@@ -227,6 +237,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p70 .name{
|
||||
color: #ff6c00;
|
||||
}
|
||||
.kanban .state_custom .box.p70,
|
||||
.kanban .state_20 .box.p70,
|
||||
.kanban .state_40 .box.p70{
|
||||
border: 5px solid #ff6c00;
|
||||
@@ -235,6 +246,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p80 .name{
|
||||
color: #ff3c00;
|
||||
}
|
||||
.kanban .state_custom .box.p80,
|
||||
.kanban .state_20 .box.p80,
|
||||
.kanban .state_40 .box.p80{
|
||||
border: 5px solid #ff3c00;
|
||||
@@ -243,6 +255,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p90 .name{
|
||||
color: #ff0000;
|
||||
}
|
||||
.kanban .state_custom .box.p90,
|
||||
.kanban .state_20 .box.p90,
|
||||
.kanban .state_40 .box.p90{
|
||||
border: 5px solid #ff0000;
|
||||
@@ -251,6 +264,7 @@ tr:hover .taglist .tag button {
|
||||
.task.p100 .name{
|
||||
color: #ff0048;
|
||||
}
|
||||
.kanban .state_custom .box.p100,
|
||||
.kanban .state_20 .box.p100,
|
||||
.kanban .state_40 .box.p100{
|
||||
border: 5px solid #ff0048;
|
||||
@@ -258,4 +272,4 @@ tr:hover .taglist .tag button {
|
||||
|
||||
.vcard span.inactive{
|
||||
color: #bbb;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user