implemented time tracking by clicking symbol at task.

next: stop running time, display running time in header

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2025-08-26 21:13:55 +02:00
parent 1ddb6af280
commit 72375b82cf
10 changed files with 79 additions and 59 deletions

View File

@@ -133,20 +133,27 @@ CREATE TABLE IF NOT EXISTS {0} (
}
@Override
public Time save(Time track) throws SQLException {
if (track.id() == 0){ // create new
var rs = insertInto(TABLE_TASK_TIMES,USER_ID,SUBJECT,DESCRIPTION,START_TIME,END_TIME,STATE)
.values(track.userId(),track.subject(),track.description(),track.startSecond(),track.endSecond(),track.state().code())
.execute(db)
.getGeneratedKeys();
if (rs.next()) track.setId(rs.getLong(1));
rs.close();
} else { // update
replaceInto(TABLE_TASK_TIMES,ID,USER_ID,SUBJECT,DESCRIPTION,START_TIME,END_TIME,STATE)
.values(track.id(),track.userId(),track.subject(),track.description(),track.startSecond(),track.endSecond(),track.state().code())
.execute(db).close();
public Time save(Time track) throws UmbrellaException {
try {
if (track.id() == 0) { // create new
var rs = insertInto(TABLE_TIMES, USER_ID, SUBJECT, DESCRIPTION, START_TIME, END_TIME, STATE)
.values(track.userId(), track.subject(), track.description(), track.startSecond(), track.endSecond(), track.state().code())
.execute(db)
.getGeneratedKeys();
if (rs.next()) track.setId(rs.getLong(1));
rs.close();
} else { // update
replaceInto(TABLE_TIMES, ID, USER_ID, SUBJECT, DESCRIPTION, START_TIME, END_TIME, STATE)
.values(track.id(), track.userId(), track.subject(), track.description(), track.startSecond(), track.endSecond(), track.state().code())
.execute(db).close();
}
var query = replaceInto(TABLE_TASK_TIMES,TIME_ID,TASK_ID);
for (var taskId : track.taskIds()) query.values(track.id(),taskId);
query.execute(db).close();
return track;
} catch (SQLException e){
LOG.log(ERROR,"Failed to write time to DB",e);
throw UmbrellaException.databaseException("Failed to write time to DB");
}
// TODO: save tasks
return track;
}
}

View File

@@ -13,5 +13,5 @@ public interface TimeDb {
HashMap<Long,Time> listUserTimes(long userId, boolean showClosed);
Time save(Time track) throws SQLException;
Time save(Time track) throws UmbrellaException;
}

View File

@@ -93,13 +93,21 @@ public class TimeModule extends BaseHandler implements TimeService {
} catch (NumberFormatException e) {
throw invalidFieldException(TASK_ID,"long value");
}
var now = LocalDateTime.now();
timeDb.listUserTimes(user.id(),false).values()
.stream().filter(time -> time.state() == Started)
.sorted(Comparator.comparing(Time::start))
.findFirst()
.map(running -> running.stop(now))
.ifPresent(timeDb::save);
var now = LocalDateTime.now().withSecond(0).withNano(0);
var opt = timeDb.listUserTimes(user.id(), false).values()
.stream()
.filter(time -> time.state() == Started)
.max(Comparator.comparing(Time::start));
if (opt.isPresent()){
var startedTime = opt.get();
if (startedTime.taskIds().contains(task.id())) {
// if the time started last already belongs to the task, there is nothing left to do
return sendContent(ex,startedTime);
}
timeDb.save(startedTime.stop(now));
}
var track = new Time(0,user.id(),task.name(),task.description(),now,null,Started,List.of(task.id()));
timeDb.save(track);
@@ -120,7 +128,7 @@ public class TimeModule extends BaseHandler implements TimeService {
var time = entry.getValue();
var map = time.toMap();
map.remove(TASK_IDS);
map.put(TASKS,time.taskIds().stream().collect(Collectors.toMap(tid -> tid, tid -> tasks.get(tid).name())));
map.put(TASKS,time.taskIds().stream().map(tasks::get).filter(Objects::nonNull).collect(toMap(Task::id,Task::name)));
result.put(entry.getKey(),map);
}
return sendContent(ex,result);