Merge branch 'main' into module/contact
This commit is contained in:
@@ -7,10 +7,12 @@
|
|||||||
import { t } from '../../translations.svelte.js';
|
import { t } from '../../translations.svelte.js';
|
||||||
import { user } from '../../user.svelte.js';
|
import { user } from '../../user.svelte.js';
|
||||||
|
|
||||||
import Card from './KanbanCard.svelte';
|
import Card from './KanbanCard.svelte';
|
||||||
import LineEditor from '../../Components/LineEditor.svelte';
|
import LineEditor from '../../Components/LineEditor.svelte';
|
||||||
|
import MarkdownEditor from '../../Components/MarkdownEditor.svelte';
|
||||||
|
|
||||||
let { id } = $props();
|
let { id } = $props();
|
||||||
|
let descr = $state(false);
|
||||||
let filter_input = $state('');
|
let filter_input = $state('');
|
||||||
let router = useTinyRouter();
|
let router = useTinyRouter();
|
||||||
if (router.hasQueryParam('filter')) filter_input = router.getQueryParam('filter');
|
if (router.hasQueryParam('filter')) filter_input = router.getQueryParam('filter');
|
||||||
@@ -25,6 +27,24 @@
|
|||||||
|
|
||||||
$effect(() => updateUrl(filter_input));
|
$effect(() => updateUrl(filter_input));
|
||||||
|
|
||||||
|
async function do_archive(ex){
|
||||||
|
ex.preventDefault();
|
||||||
|
var task = dragged;
|
||||||
|
const url = api(`task/${task.id}`);
|
||||||
|
const resp = await fetch(url,{
|
||||||
|
credentials : 'include',
|
||||||
|
method : 'PATCH',
|
||||||
|
body : JSON.stringify({no_index:true})
|
||||||
|
});
|
||||||
|
delete highlight.archive;
|
||||||
|
if (resp.ok){
|
||||||
|
yikes();
|
||||||
|
delete tasks[task.assignee][task.status][task.id]
|
||||||
|
} else {
|
||||||
|
error(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateUrl(){
|
function updateUrl(){
|
||||||
let url = window.location.origin + window.location.pathname;
|
let url = window.location.origin + window.location.pathname;
|
||||||
if (filter_input) url += '?filter=' + encodeURI(filter_input);
|
if (filter_input) url += '?filter=' + encodeURI(filter_input);
|
||||||
@@ -149,6 +169,11 @@
|
|||||||
highlight = {user:user_id,state:state};
|
highlight = {user:user_id,state:state};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hover_archive(ev){
|
||||||
|
ev.preventDefault();
|
||||||
|
highlight.archive = true;
|
||||||
|
}
|
||||||
|
|
||||||
function openTask(task_id){
|
function openTask(task_id){
|
||||||
controller.abort();
|
controller.abort();
|
||||||
router.navigate(`/task/${task_id}/view`)
|
router.navigate(`/task/${task_id}/view`)
|
||||||
@@ -190,6 +215,10 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if project}
|
{#if project}
|
||||||
|
<fieldset class="kanban description {descr?'active':''}" onclick={e => descr = !descr}>
|
||||||
|
<legend>{t('description')} – {t('expand_on_click')}</legend>
|
||||||
|
{@html project.description.rendered}
|
||||||
|
</fieldset>
|
||||||
<div class="kanban" style="display: grid; grid-template-columns: {`repeat(${columns}, auto)`}">
|
<div class="kanban" style="display: grid; grid-template-columns: {`repeat(${columns}, auto)`}">
|
||||||
<span class="filter">
|
<span class="filter">
|
||||||
<input type="text" bind:value={filter_input} autofocus />
|
<input type="text" bind:value={filter_input} autofocus />
|
||||||
@@ -207,7 +236,7 @@
|
|||||||
{#each Object.entries(tasks) as [uid,stateList]}
|
{#each Object.entries(tasks) as [uid,stateList]}
|
||||||
<div class="user">{users[uid]}</div>
|
<div class="user">{users[uid]}</div>
|
||||||
{#each Object.entries(project.allowed_states) as [state,name]}
|
{#each Object.entries(project.allowed_states) as [state,name]}
|
||||||
<div class={['state_'+state, highlight.user == uid && highlight.state == state ? 'highlight':'']} ondragover={ev => hover(ev,uid,state)} ondrop={ev => drop(uid,state)} >
|
<div class={['state_'+state, highlight.user == uid && highlight.state == state ? 'highlight':'']} ondragover={ev => hover(ev,uid,state)} ondragleave={e => delete highlight.user} ondrop={ev => drop(uid,state)} >
|
||||||
{#if stateList[state]}
|
{#if stateList[state]}
|
||||||
{#each Object.values(stateList[state]).sort((a,b) => a.name.localeCompare(b.name)) as task}
|
{#each Object.values(stateList[state]).sort((a,b) => a.name.localeCompare(b.name)) as task}
|
||||||
{#if !filter || task.name.toLowerCase().includes(filter) || (task.tags && task.tags.filter(tag => tag.toLowerCase().includes(filter)).length)}
|
{#if !filter || task.name.toLowerCase().includes(filter) || (task.tags && task.tags.filter(tag => tag.toLowerCase().includes(filter)).length)}
|
||||||
@@ -222,4 +251,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<div class="archive {highlight.archive?'hover':''}" ondragover={hover_archive} ondragleave={e => delete highlight.archive} ondrop={do_archive} >
|
||||||
|
{t('archive')}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|||||||
@@ -16,7 +16,10 @@
|
|||||||
<div
|
<div
|
||||||
draggable="true"
|
draggable="true"
|
||||||
class={`box prio_${task.total_prio} p${Math.floor(task.total_prio/10)*10} p${task.total_prio % 10}`}
|
class={`box prio_${task.total_prio} p${Math.floor(task.total_prio/10)*10} p${task.total_prio % 10}`}
|
||||||
{onclick} {ondragstart} style={style}>
|
{onclick} {ondragstart}
|
||||||
|
style={style}
|
||||||
|
title={task.description.source}
|
||||||
|
>
|
||||||
<span class="title">{task.name}</span>
|
<span class="title">{task.name}</span>
|
||||||
{#if task.estimated_time}
|
{#if task.estimated_time}
|
||||||
<span class="estimate">
|
<span class="estimate">
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
{#if module=='bookmark'}
|
{#if module=='bookmark'}
|
||||||
{@html target(object.comment.rendered).replace(/<p>(.*?)<\/p>/, '$1')} <!-- this is a workaround for in-proper formatting of paragraphs within list items in firefox -->
|
{@html target(object.comment.rendered).replace(/<p>(.*?)<\/p>/, '$1')} <!-- this is a workaround for in-proper formatting of paragraphs within list items in firefox -->
|
||||||
<p>
|
<p>
|
||||||
<a href={object.url}>{object.url}</a>
|
<a href={object.url} target="_blank">{object.url}</a>
|
||||||
</p>
|
</p>
|
||||||
<hr/>
|
<hr/>
|
||||||
{:else if module=='task' || module=='project'}
|
{:else if module=='task' || module=='project'}
|
||||||
|
|||||||
@@ -81,6 +81,7 @@
|
|||||||
"end": "Ende",
|
"end": "Ende",
|
||||||
"estimated_time": "geschätzte Zeit",
|
"estimated_time": "geschätzte Zeit",
|
||||||
"estimated_times": "geschätzte Zeiten",
|
"estimated_times": "geschätzte Zeiten",
|
||||||
|
"expand_on_click": "Anklicken zum Anzeigen",
|
||||||
"extended_settings": "erweiterte Einstellungen",
|
"extended_settings": "erweiterte Einstellungen",
|
||||||
|
|
||||||
"failed": "fehlgeschlagen",
|
"failed": "fehlgeschlagen",
|
||||||
|
|||||||
@@ -81,6 +81,7 @@
|
|||||||
"end": "end",
|
"end": "end",
|
||||||
"estimated_time": "estimated duration",
|
"estimated_time": "estimated duration",
|
||||||
"estimated_times": "estimated durations",
|
"estimated_times": "estimated durations",
|
||||||
|
"expand_on_click": "click to expand",
|
||||||
"extended_settings": "extended settings",
|
"extended_settings": "extended settings",
|
||||||
|
|
||||||
"failed": "failed",
|
"failed": "failed",
|
||||||
|
|||||||
@@ -42,6 +42,16 @@ textarea{
|
|||||||
background-color: black;
|
background-color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.archive{
|
||||||
|
background: red;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive.hover{
|
||||||
|
background: orange;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
color: black;
|
color: black;
|
||||||
|
|||||||
@@ -36,6 +36,15 @@ button{
|
|||||||
border-style: solid;
|
border-style: solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fieldset[tabindex="0"]{
|
||||||
|
max-height: 55px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset[tabindex="0"]:focus-within{
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@@ -53,6 +62,21 @@ nav {
|
|||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td, tr{
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive {
|
||||||
|
position: fixed;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
padding: 7px 30px;
|
||||||
|
z-index: 100;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -63,17 +87,6 @@ nav {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset[tabindex="0"]{
|
|
||||||
max-height: 55px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset[tabindex="0"]:focus-within{
|
|
||||||
max-height: unset;
|
|
||||||
}
|
|
||||||
td, tr{
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
.customer,
|
.customer,
|
||||||
.sender,
|
.sender,
|
||||||
.invoice_meta{
|
.invoice_meta{
|
||||||
@@ -193,6 +206,15 @@ textarea{
|
|||||||
right: 20px;
|
right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kanban.description{
|
||||||
|
max-height: 50px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban.description.active{
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
.project th,
|
.project th,
|
||||||
.task th{
|
.task th{
|
||||||
text-align: right;
|
text-align: right;
|
||||||
@@ -362,7 +384,7 @@ a.wikilink{
|
|||||||
}
|
}
|
||||||
|
|
||||||
.grid2 > :nth-child(2n-1){
|
.grid2 > :nth-child(2n-1){
|
||||||
text-align: initial ;
|
text-align: initial;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,6 +45,15 @@ textarea{
|
|||||||
background-color: #333;
|
background-color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.archive{
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive.hover{
|
||||||
|
background: orange;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
.em {
|
.em {
|
||||||
background: rgba(255, 215, 0, 0.09);
|
background: rgba(255, 215, 0, 0.09);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,15 @@ button{
|
|||||||
border-style: solid;
|
border-style: solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fieldset[tabindex="0"]{
|
||||||
|
max-height: 55px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset[tabindex="0"]:focus-within{
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@@ -53,6 +62,21 @@ nav {
|
|||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td, tr{
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive {
|
||||||
|
position: fixed;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
padding: 7px 30px;
|
||||||
|
z-index: 100;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -63,17 +87,6 @@ nav {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset[tabindex="0"]{
|
|
||||||
max-height: 55px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset[tabindex="0"]:focus-within{
|
|
||||||
max-height: unset;
|
|
||||||
}
|
|
||||||
td, tr{
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
.customer,
|
.customer,
|
||||||
.sender,
|
.sender,
|
||||||
.invoice_meta{
|
.invoice_meta{
|
||||||
@@ -193,6 +206,15 @@ textarea{
|
|||||||
right: 20px;
|
right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kanban.description{
|
||||||
|
max-height: 50px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban.description.active{
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
.project th,
|
.project th,
|
||||||
.task th{
|
.task th{
|
||||||
text-align: right;
|
text-align: right;
|
||||||
@@ -254,6 +276,10 @@ nav > form{
|
|||||||
display:inline;
|
display:inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li > a > p:nth-child(1){
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
.timetracks .duration{
|
.timetracks .duration{
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
@@ -361,5 +387,4 @@ a.wikilink{
|
|||||||
text-align: initial;
|
text-align: initial;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +41,15 @@ textarea{
|
|||||||
background-color: lightcyan;;
|
background-color: lightcyan;;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.archive{
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive.hover{
|
||||||
|
background: lightblue;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
color: black;
|
color: black;
|
||||||
|
|||||||
@@ -36,6 +36,15 @@ button{
|
|||||||
border-style: solid;
|
border-style: solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fieldset[tabindex="0"]{
|
||||||
|
max-height: 55px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset[tabindex="0"]:focus-within{
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@@ -53,6 +62,21 @@ nav {
|
|||||||
border-bottom: 1px solid;
|
border-bottom: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td, tr{
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive {
|
||||||
|
position: fixed;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
padding: 7px 30px;
|
||||||
|
z-index: 100;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -63,17 +87,6 @@ nav {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset[tabindex="0"]{
|
|
||||||
max-height: 55px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset[tabindex="0"]:focus-within{
|
|
||||||
max-height: unset;
|
|
||||||
}
|
|
||||||
td, tr{
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
.customer,
|
.customer,
|
||||||
.sender,
|
.sender,
|
||||||
.invoice_meta{
|
.invoice_meta{
|
||||||
@@ -193,6 +206,15 @@ textarea{
|
|||||||
right: 20px;
|
right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kanban.description{
|
||||||
|
max-height: 50px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban.description.active{
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
.project th,
|
.project th,
|
||||||
.task th{
|
.task th{
|
||||||
text-align: right;
|
text-align: right;
|
||||||
@@ -362,7 +384,7 @@ a.wikilink{
|
|||||||
}
|
}
|
||||||
|
|
||||||
.grid2 > :nth-child(2n-1){
|
.grid2 > :nth-child(2n-1){
|
||||||
text-align: initial ;
|
text-align: initial;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user