Browse Source

Merge branch 'main' into module/stock

module/document
Stephan Richter 3 weeks ago
parent
commit
8e84627fcb
  1. 2
      core/src/main/java/de/srsoftware/umbrella/core/model/Task.java
  2. 39
      frontend/src/routes/task/Index.svelte
  3. 9
      frontend/src/routes/task/View.svelte
  4. 15
      frontend/src/routes/time/Index.svelte
  5. 19
      web/src/main/resources/web/css/bloodshed-color.css
  6. 49
      web/src/main/resources/web/css/bloodshed.css
  7. 14
      web/src/main/resources/web/css/default-color.css
  8. 7
      web/src/main/resources/web/css/default.css
  9. 9
      web/src/main/resources/web/css/winter-color.css
  10. 49
      web/src/main/resources/web/css/winter.css

2
core/src/main/java/de/srsoftware/umbrella/core/model/Task.java

@ -171,7 +171,7 @@ public class Task implements Mappable { @@ -171,7 +171,7 @@ public class Task implements Mappable {
case MEMBERS: continue;
case NAME: name = json.getString(key); break;
case NO_INDEX: noIndex = json.getBoolean(NO_INDEX); break;
case PARENT_TASK_ID: parentTaskId = json.getLong(PARENT_TASK_ID); break;
case PARENT_TASK_ID: parentTaskId = json.isNull(PARENT_TASK_ID) ? null : json.getLong(PARENT_TASK_ID); break;
case PRIORITY: priority = json.getInt(PRIORITY); break;
case REQUIRED_TASKS_IDS:
requiredTasksIds.clear();

39
frontend/src/routes/task/Index.svelte

@ -14,8 +14,9 @@ @@ -14,8 +14,9 @@
let map = $state({});
let hidden = $state({});
async function changeState(tid,state){
const task = tasks[tid];
async function changeState(idx,state){
const task = tasks[idx];
const tid = task.id;
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}`);
@ -25,18 +26,18 @@ @@ -25,18 +26,18 @@
body : JSON.stringify({status:stat})
});
if (resp.ok){
tasks[tid] = await resp.json();
tasks[idx] = await resp.json();
} else {
error(resp);
}
}
function abort(tid){
changeState(tid,'CANCELLED');
function abort(idx){
changeState(idx,'CANCELLED');
}
function complete(tid){
changeState(tid,'COMPLETE');
function complete(idx){
changeState(idx,'COMPLETE');
}
function edit(tid){
@ -81,16 +82,16 @@ @@ -81,16 +82,16 @@
}
}
function open(tid){
changeState(tid,'OPEN');
function open(idx){
changeState(idx,'OPEN');
}
function postpone(tid){
changeState(tid,'PENDING');
function postpone(idx){
changeState(idx,'PENDING');
}
function start(tid){
changeState(tid,'STARTED');
function start(idx){
changeState(idx,'STARTED');
}
onMount(load);
@ -115,7 +116,7 @@ @@ -115,7 +116,7 @@
</tr>
</thead>
<tbody>
{#each tasks as task (task.id)}
{#each tasks as task,idx}
{#if task.status > 10 && task.status < 60 && !task.no_index && projects[task.project_id]?.status < 60 && !hidden[task.id]}
<tr>
<td onclick={() => go('task',task.id)}>{task.name}</td>
@ -136,11 +137,11 @@ @@ -136,11 +137,11 @@
</td>
<td>
<button class="symbol" onclick={() => edit(task.id)} title={t('edit')} ></button>
<button class="symbol" onclick={() => postpone(task.id)} title={t('postpone')} ></button>
<button class="symbol" onclick={() => open(task.id)} title={t('open')}></button>
<button class="symbol" onclick={() => start(task.id)} title={t('start')} ></button>
<button class="symbol" onclick={() => complete(task.id)} title={t('complete')} ></button>
<button class="symbol" onclick={() => abort(task.id)} title={t('abort')} ></button>
<button class="symbol" onclick={() => postpone(idx)} title={t('postpone')} ></button>
<button class="symbol" onclick={() => open(idx)} title={t('open')}></button>
<button class="symbol" onclick={() => start(idx)} title={t('start')} ></button>
<button class="symbol" onclick={() => complete(idx)} title={t('complete')} ></button>
<button class="symbol" onclick={() => abort(idx)} title={t('abort')} ></button>
</td>
</tr>
{/if}

9
frontend/src/routes/task/View.svelte

@ -140,6 +140,10 @@ @@ -140,6 +140,10 @@
showSettings = !showSettings;
}
function unlink_parent(){
update({parent_task_id:null});
}
async function update(data){
const url = api(`task/${id}`);
const resp = await fetch(url,{
@ -151,7 +155,11 @@ @@ -151,7 +155,11 @@
yikes();
let old_task = task;
task = await resp.json();
if (!task.parent_id){
task.parent = null;
} else {
if (task.parent_id == old_task.parent_id) task.parent = old_task.parent;
}
return true;
} else {
error(resp);
@ -196,6 +204,7 @@ @@ -196,6 +204,7 @@
<div>{t('parent_task')}</div>
<div class="parent">
<a href="#" onclick={gotoParent}>{task.parent.name}</a>
<button class="symbol" title={t('unlink')} onclick={unlink_parent}></button>
</div>
{/if}
<div>{t('task')}</div>

15
frontend/src/routes/time/Index.svelte

@ -10,12 +10,15 @@ @@ -10,12 +10,15 @@
import TimeEditor from '../../Components/TimeRecordEditor.svelte';
let detail = $state(null);
let docLinks = $state(null);
let router = useTinyRouter();
let times = $state(null);
let tasks = {};
let projects = {};
let detail = $state(null);
let project_filter = $state(null);
if (router.hasQueryParam('project')) project_filter = router.getQueryParam('project');
let sortedTimes = $derived.by(() => Object.values(times).map(time => ({
...time,
start: display(time.start_time),
@ -114,6 +117,14 @@ @@ -114,6 +117,14 @@
}
}
function match_prj_filter(time){
if (!project_filter) return true;
for (var tid of time.task_ids){
if (project_filter == tasks[tid].project_id) return true;
}
return false;
}
function onAbort(){
detail = null;
}
@ -217,6 +228,7 @@ @@ -217,6 +228,7 @@
</thead>
<tbody>
{#each sortedTimes as time,line}
{#if match_prj_filter(time)}
<tr class={selected[time.id]?'selected':''}>
{#if timeMap.years[line]}
<td class="year" rowspan={timeMap.years[line]} onclick={e => toggleRange(time.start.substring(0,4))}>
@ -279,6 +291,7 @@ @@ -279,6 +291,7 @@
</td>
{/if}
</tr>
{/if}
{/each}
</tbody>
</table>

19
web/src/main/resources/web/css/bloodshed-color.css

@ -46,6 +46,11 @@ textarea{ @@ -46,6 +46,11 @@ textarea{
background-color: black;
}
tr:hover{
background: darkred;
color: black;
}
.archive{
background: red;
color: black;
@ -155,15 +160,21 @@ textarea{ @@ -155,15 +160,21 @@ textarea{
color: yellow;
}
.timetracks .year, .month{
border-color: 1px solid;
}
.timetracks .selected td:not(.year):not(.month){
background-color: darkred;
color: orange;
}
.timetracks.sum {
background: black;
}
.timetracks .year, .month{
border-color: 1px solid;
}
.warn {
background-color: yellow;
color: black;

49
web/src/main/resources/web/css/bloodshed.css

@ -290,11 +290,31 @@ span.timetracking { @@ -290,11 +290,31 @@ span.timetracking {
display: inline-block;
}
.markdown.editing{
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 10px;
}
.markdown .buttons,
.markdown .hint{
grid-column-end: span 2;
}
.editable:hover{
border: 1px dotted;
}
.timetracks .year, .timetracks .month{
border: 1px solid;
}
.timetracks.sum {
position: sticky;
top: 60px;
z-index: 20;
padding: 5px;
}
.timetracks.sum span{
font-weight: bold;
}
@ -307,23 +327,6 @@ span.timetracking { @@ -307,23 +327,6 @@ span.timetracking {
float: right;
}
.markdown.editing{
position: relative;
}
.markdown.editing > *{
width: 49%;
}
.markdown.editing > *:nth-child(2){
position: absolute;
right: 0;
top: 0;
}
.markdown img{
max-width: 75%;
}
table{
min-width: 30vw;
@ -370,6 +373,7 @@ a.wikilink{ @@ -370,6 +373,7 @@ a.wikilink{
.grid2{
display: grid;
grid-template-columns: 230px auto;
margin: 0 5px;
}
.grid2 > :nth-child(2n-1){
@ -399,6 +403,17 @@ a.wikilink{ @@ -399,6 +403,17 @@ a.wikilink{
text-align: initial;
padding-top: 8px;
}
.markdown.editing{
display: block;
grid-template-columns: 1fr 1fr;
column-gap: 10px;
}
.markdown textarea{
width: calc(100% - 10px);
min-height: 50px;
}
}
fieldset.vcard{

14
web/src/main/resources/web/css/default-color.css

@ -45,6 +45,15 @@ textarea{ @@ -45,6 +45,15 @@ textarea{
background-color: #333;
}
tr:hover{
background: orange;
color: black;
}
tr:hover a{
background: black;
}
.archive{
background: black;
}
@ -150,6 +159,11 @@ textarea{ @@ -150,6 +159,11 @@ textarea{
background-color: navy;
}
.timetracks.sum {
background: black;
}
.version a.selected{
border-color: orange;
}

7
web/src/main/resources/web/css/default.css

@ -308,6 +308,13 @@ span.timetracking { @@ -308,6 +308,13 @@ span.timetracking {
border: 1px solid;
}
.timetracks.sum {
position: sticky;
top: 60px;
z-index: 20;
padding: 5px;
}
.timetracks.sum span{
font-weight: bold;
}

9
web/src/main/resources/web/css/winter-color.css

@ -41,6 +41,10 @@ textarea{ @@ -41,6 +41,10 @@ textarea{
background-color: lightcyan;;
}
tr:hover{
background: #afffff;
}
.archive{
background: white;
}
@ -140,6 +144,11 @@ textarea{ @@ -140,6 +144,11 @@ textarea{
background-color: aquamarine;
}
.timetracks.sum {
background: white;
}
.version a.selected{
border-color: orange;
}

49
web/src/main/resources/web/css/winter.css

@ -290,11 +290,31 @@ span.timetracking { @@ -290,11 +290,31 @@ span.timetracking {
display: inline-block;
}
.markdown.editing{
display: grid;
grid-template-columns: 1fr 1fr;
column-gap: 10px;
}
.markdown .buttons,
.markdown .hint{
grid-column-end: span 2;
}
.editable:hover{
border: 1px dotted;
}
.timetracks .year, .timetracks .month{
border: 1px solid;
}
.timetracks.sum {
position: sticky;
top: 60px;
z-index: 20;
padding: 5px;
}
.timetracks.sum span{
font-weight: bold;
}
@ -307,23 +327,6 @@ span.timetracking { @@ -307,23 +327,6 @@ span.timetracking {
float: right;
}
.markdown.editing{
position: relative;
}
.markdown.editing > *{
width: 49%;
}
.markdown.editing > *:nth-child(2){
position: absolute;
right: 0;
top: 0;
}
.markdown img{
max-width: 75%;
}
table{
min-width: 30vw;
@ -370,6 +373,7 @@ a.wikilink{ @@ -370,6 +373,7 @@ a.wikilink{
.grid2{
display: grid;
grid-template-columns: 230px auto;
margin: 0 5px;
}
.grid2 > :nth-child(2n-1){
@ -399,6 +403,17 @@ a.wikilink{ @@ -399,6 +403,17 @@ a.wikilink{
text-align: initial;
padding-top: 8px;
}
.markdown.editing{
display: block;
grid-template-columns: 1fr 1fr;
column-gap: 10px;
}
.markdown textarea{
width: calc(100% - 10px);
min-height: 50px;
}
}
fieldset.vcard{

Loading…
Cancel
Save