working on time list

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2025-08-18 15:37:57 +02:00
parent d394c9d817
commit 7ab844bcff
6 changed files with 47 additions and 63 deletions

View File

@@ -10,7 +10,7 @@ import java.util.List;
public interface TaskService { public interface TaskService {
HashMap<Long, Task> listCompanyTasks(long companyId) throws UmbrellaException; HashMap<Long, Task> listCompanyTasks(long companyId) throws UmbrellaException;
HashMap<Long, Task> listProjectTasks(long projectId) throws UmbrellaException; HashMap<Long, Task> listProjectTasks(long projectId) throws UmbrellaException;
HashMap<Long, Task> load(List<Long> taskIds); HashMap<Long, Task> load(Collection<Long> taskIds);
Collection<Task> loadMembers(Collection<Task> tasks); Collection<Task> loadMembers(Collection<Task> tasks);
default Task loadMembers(Task task){ default Task loadMembers(Task task){

View File

@@ -1,9 +1,11 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { useTinyRouter } from 'svelte-tiny-router';
import { api } from '../../urls.svelte.js'; import { api } from '../../urls.svelte.js';
import { t } from '../../translations.svelte.js'; import { t } from '../../translations.svelte.js';
let error = $state(null); let error = $state(null);
let router = useTinyRouter();
let times = $state(null); let times = $state(null);
async function loadTimes(){ async function loadTimes(){
@@ -16,6 +18,10 @@
} }
} }
function openTask(tid){
router.navigate(`task/${tid}/view`);
}
onMount(loadTimes); onMount(loadTimes);
</script> </script>
@@ -34,14 +40,20 @@
<td> <td>
{time.start_time}{time.end_time} {time.start_time}{time.end_time}
</td> </td>
<td>
{time.duration}&nbsp;h
</td>
<td> <td>
{time.subject} {time.subject}
</td> </td>
<td> <td>
{#each time.task_ids as tid} {#each Object.entries(time.tasks) as [tid,task]}
{tid}&nbsp; <a href="#" onclick={e => openTask(tid)}>{task}</a>
{/each} {/each}
</td> </td>
<td>
{t("state_"+time.state.name.toLowerCase())}
</td>
</tr> </tr>
{/each} {/each}
</tbody> </tbody>

View File

@@ -216,7 +216,7 @@ public class TaskModule extends BaseHandler implements TaskService {
} }
@Override @Override
public HashMap<Long, Task> load(List<Long> taskIds) { public HashMap<Long, Task> load(Collection<Long> taskIds) {
try { try {
var map = taskIds.stream().map(taskDb::load).collect(Collectors.toMap(Task::id, t -> t)); var map = taskIds.stream().map(taskDb::load).collect(Collectors.toMap(Task::id, t -> t));
return new HashMap<>(map); return new HashMap<>(map);

View File

@@ -1,12 +1,11 @@
/* © SRSoftware 2025 */ /* © SRSoftware 2025 */
package de.srsoftware.umbrella.time; package de.srsoftware.umbrella.time;
import static de.srsoftware.tools.jdbc.Condition.equal; import static de.srsoftware.tools.jdbc.Condition.*;
import static de.srsoftware.tools.jdbc.Condition.in;
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL; import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
import static de.srsoftware.tools.jdbc.Query.select; import static de.srsoftware.tools.jdbc.Query.select;
import static de.srsoftware.umbrella.core.Constants.ID; import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.Constants.USER_ID; import static de.srsoftware.umbrella.core.model.Time.State.Complete;
import static de.srsoftware.umbrella.time.Constants.*; import static de.srsoftware.umbrella.time.Constants.*;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
@@ -26,7 +25,7 @@ public class SqliteDb implements TimeDb {
} }
@Override @Override
public HashMap<Long,Time> listTimes(Collection<Long> taskIds) throws UmbrellaException { public HashMap<Long,Time> listTimes(Collection<Long> taskIds, boolean showClosed) throws UmbrellaException {
try { try {
var rs = select(ALL).from(TABLE_TASK_TIMES).where(TASK_ID,in(taskIds.toArray())).exec(db); var rs = select(ALL).from(TABLE_TASK_TIMES).where(TASK_ID,in(taskIds.toArray())).exec(db);
var mapFromTimesToTasks = new HashMap<Long,HashSet<Long>>(); var mapFromTimesToTasks = new HashMap<Long,HashSet<Long>>();
@@ -36,7 +35,9 @@ public class SqliteDb implements TimeDb {
mapFromTimesToTasks.computeIfAbsent(timeId, k -> new HashSet<>()).add(taskId); mapFromTimesToTasks.computeIfAbsent(timeId, k -> new HashSet<>()).add(taskId);
} }
rs.close(); rs.close();
rs = select(ALL).from(TABLE_TIMES).where(ID,in(mapFromTimesToTasks.keySet().toArray())).exec(db); var query = select(ALL).from(TABLE_TIMES).where(ID,in(mapFromTimesToTasks.keySet().toArray()));
if (!showClosed) query.where(STATE,lessThan(Complete.code()));
rs = query.exec(db);
var times = new HashMap<Long,Time>(); var times = new HashMap<Long,Time>();
while (rs.next()) { while (rs.next()) {
var time = Time.of(rs); var time = Time.of(rs);
@@ -45,15 +46,17 @@ public class SqliteDb implements TimeDb {
} }
rs.close(); rs.close();
return times; return times;
} catch (SQLException e) { } catch (Exception e) {
throw new UmbrellaException("Failed to load times for task list"); throw new UmbrellaException("Failed to load times for task list");
} }
} }
@Override @Override
public HashMap<Long, Time> listUserTimes(long userId) { public HashMap<Long, Time> listUserTimes(long userId, boolean showClosed) {
try { try {
var rs = select(ALL).from(TABLE_TIMES).where(USER_ID,equal(userId)).exec(db); var query = select(ALL).from(TABLE_TIMES).where(USER_ID,equal(userId));
if (!showClosed) query.where(STATE,lessThan(Complete.code()));
var rs = query.exec(db);
var times = new HashMap<Long,Time>(); var times = new HashMap<Long,Time>();
while (rs.next()) { while (rs.next()) {
var time = Time.of(rs); var time = Time.of(rs);

View File

@@ -7,7 +7,7 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
public interface TimeDb { public interface TimeDb {
HashMap<Long,Time> listTimes(Collection<Long> taskIds) throws UmbrellaException; HashMap<Long,Time> listTimes(Collection<Long> taskIds, boolean showClosed) throws UmbrellaException;
HashMap<Long,Time> listUserTimes(long userId); HashMap<Long,Time> listUserTimes(long userId, boolean showClosed);
} }

View File

@@ -4,12 +4,10 @@ package de.srsoftware.umbrella.time;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect; import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.Paths.LIST; import static de.srsoftware.umbrella.core.Paths.LIST;
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_NOT_IMPLEMENTED;
import static de.srsoftware.umbrella.core.Util.mapValues;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.forbidden; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.forbidden;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.time.Constants.*; import static de.srsoftware.umbrella.time.Constants.*;
import static java.util.function.Predicate.not; import static java.util.stream.Collectors.toSet;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.configuration.Configuration; import de.srsoftware.configuration.Configuration;
@@ -23,6 +21,7 @@ import de.srsoftware.umbrella.core.model.*;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class TimeModule extends BaseHandler implements TimeService { public class TimeModule extends BaseHandler implements TimeService {
@@ -82,54 +81,24 @@ public class TimeModule extends BaseHandler implements TimeService {
} }
private boolean getUserTimes(UmbrellaUser user, HttpExchange ex) throws IOException { private boolean getUserTimes(UmbrellaUser user, HttpExchange ex) throws IOException {
// TODO Set<Long> taskIds = new HashSet<>();
var taskIds = new HashSet<Long>();
Map<Long, Project> projects = projectService().listUserProjects(user.id(), true); Map<Long, Project> projects = projectService().listUserProjects(user.id(), true);
for (var pid : projects.keySet()) taskIds.addAll(taskService().listProjectTasks(pid).keySet()); for (var pid : projects.keySet()) taskIds.addAll(taskService().listProjectTasks(pid).keySet());
var times = timeDb.listTimes(taskIds); boolean showClosed = false;
times.putAll(timeDb.listUserTimes(user.id())); var times = timeDb.listTimes(taskIds, showClosed);
return sendContent(ex,mapValues(times)); times.putAll(timeDb.listUserTimes(user.id(), showClosed));
} taskIds = times.values().stream().map(Time::taskIds).flatMap(Collection::stream).collect(toSet());
var tasks = taskService().load(taskIds);
/* var result = new HashMap<Long,Map<String,Object>>();
{ for (var entry : times.entrySet()) {
1 : { var time = entry.getValue();
name: Projekt 1 var map = time.toMap();
id: 1 map.remove(TASK_IDS);
times: { map.put(TASKS,time.taskIds().stream().collect(Collectors.toMap(tid -> tid, tid -> tasks.get(tid).name())));
3:{ result.put(entry.getKey(),map);
name: time 3
start: 123456
end: 78901
},
4:{
name: time 4
start: 234567
end: 890123
tasks:{
5:{
name: task5
},
6:{
name: task6
}
}
}
}
},
2: {
name: Projekt 2
id: 2
times: {
7:{
name: time 7
start: 456789
end: 012345
}
}
} }
return sendContent(ex,result);
} }
*/
private boolean listTimes(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException { private boolean listTimes(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
var json = json(ex); var json = json(ex);
@@ -141,7 +110,7 @@ public class TimeModule extends BaseHandler implements TimeService {
long projectId = pid.longValue(); long projectId = pid.longValue();
Map<Long,Task> tasksOfProject = taskService().listProjectTasks(projectId); Map<Long,Task> tasksOfProject = taskService().listProjectTasks(projectId);
List<Map<String, Object>> times = timeDb.listTimes(tasksOfProject.keySet()) List<Map<String, Object>> times = timeDb.listTimes(tasksOfProject.keySet(), true)
.entrySet().stream() .entrySet().stream()
.filter(entry -> !entry.getValue().isClosed()) .filter(entry -> !entry.getValue().isClosed())
.sorted(Comparator.comparing(entry ->entry.getValue().start())) .sorted(Comparator.comparing(entry ->entry.getValue().start()))