preparing creation of new times
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -92,6 +92,10 @@ public class Time implements Mappable{
|
||||
return start;
|
||||
}
|
||||
|
||||
public State state(){
|
||||
return state;
|
||||
}
|
||||
|
||||
public Collection<Long> taskIds(){
|
||||
return taskIds;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
import TagUses from "./routes/tags/TagUses.svelte";
|
||||
import TaskList from "./routes/task/Index.svelte";
|
||||
import Times from "./routes/time/Index.svelte";
|
||||
import TimeTask from "./routes/time/AddTask.svelte";
|
||||
import User from "./routes/user/User.svelte";
|
||||
import ViewDoc from "./routes/document/View.svelte";
|
||||
import ViewPrj from "./routes/project/View.svelte";
|
||||
@@ -76,6 +77,7 @@
|
||||
<Route path="/task/:id/edit" component={ViewTask} />
|
||||
<Route path="/task/:id/view" component={ViewTask} />
|
||||
<Route path="/time" component={Times} />
|
||||
<Route path="/time/add_task/:task_id" component={TimeTask} />
|
||||
<Route path="/user" component={User} />
|
||||
<Route path="/user/create" component={EditUser} />
|
||||
<Route path="/user/login" component={User} />
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
router.navigate(`/task/${task.id}/add_subtask`);
|
||||
}
|
||||
|
||||
function addTime(){
|
||||
router.navigate(`/time/add_task/${task.id}`);
|
||||
}
|
||||
|
||||
async function deleteTask(){
|
||||
if (confirm(t('confirm_delete',{element:task.name}))){
|
||||
const url = api(`task/${task.id}`);
|
||||
@@ -147,7 +151,7 @@
|
||||
{/if}
|
||||
<button class="symbol" title={t('delete_task')} onclick={deleteTask} ></button>
|
||||
<button class="symbol" title={t('add_subtask')} onclick={addSubtask}></button>
|
||||
<a href="/time/add_task?tid={task.id}" class="symbol"></a>
|
||||
<button class="symbol" title={t('timetracking')} onclick={addTime}></button>
|
||||
{#if error}
|
||||
<span class="error">{error}</span>
|
||||
{/if}
|
||||
|
||||
16
frontend/src/routes/time/AddTask.svelte
Normal file
16
frontend/src/routes/time/AddTask.svelte
Normal file
@@ -0,0 +1,16 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { api } from '../../urls.svelte.js';
|
||||
import { t } from '../../translations.svelte.js';
|
||||
|
||||
let { task_id } = $props();
|
||||
|
||||
async function addTask(){
|
||||
const url = api(`time/add_task/${task_id}`);
|
||||
const resp = await fetch(url,{credentials:'include'}); // create new time or return time with assigned tasks
|
||||
}
|
||||
|
||||
onMount(addTask)
|
||||
</script>
|
||||
|
||||
{t('timetracking')}
|
||||
@@ -5,6 +5,7 @@ public class Constants {
|
||||
private Constants(){}
|
||||
|
||||
|
||||
public static final String ADD_TASK = "add_task";
|
||||
public static final String CONFIG_DATABASE = "umbrella.modules.time.database";
|
||||
|
||||
public static final String TABLE_TASK_TIMES = "task_times";
|
||||
|
||||
@@ -5,9 +5,13 @@ import static de.srsoftware.tools.jdbc.Condition.*;
|
||||
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
||||
import static de.srsoftware.tools.jdbc.Query.select;
|
||||
import static de.srsoftware.umbrella.core.Constants.*;
|
||||
import static de.srsoftware.umbrella.core.model.Status.OPEN;
|
||||
import static de.srsoftware.umbrella.core.model.Time.State.Complete;
|
||||
import static de.srsoftware.umbrella.time.Constants.*;
|
||||
import static java.lang.System.Logger.Level.ERROR;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import de.srsoftware.umbrella.core.BaseDb;
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||
import de.srsoftware.umbrella.core.model.Time;
|
||||
import java.sql.Connection;
|
||||
@@ -16,15 +20,70 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class SqliteDb implements TimeDb {
|
||||
public class SqliteDb extends BaseDb implements TimeDb {
|
||||
|
||||
private final Connection db;
|
||||
|
||||
public SqliteDb(Connection connection) {
|
||||
db = connection;
|
||||
}
|
||||
public SqliteDb(Connection connection) {
|
||||
super(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Time createNew(long userId, String subject, String description) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int createTables() {
|
||||
int currentVersion = createSettingsTable();
|
||||
switch (currentVersion){
|
||||
case 0:
|
||||
createTimesTable();
|
||||
createTaskTimesTable();
|
||||
}
|
||||
return setCurrentVersion(1);
|
||||
}
|
||||
|
||||
private void createTaskTimesTable() {
|
||||
var sql = """
|
||||
CREATE TABLE IF NOT EXISTS {0} (
|
||||
{1} INT NOT NULL,
|
||||
{2} INT NOT NULL,
|
||||
PRIMARY KEY({1}, {2})
|
||||
)""";
|
||||
sql = format(sql,TABLE_TASK_TIMES,TASK_ID,TIME_ID);
|
||||
try {
|
||||
var stmt = db.prepareStatement(sql);
|
||||
stmt.execute();
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
LOG.log(ERROR, ERROR_FAILED_CREATE_TABLE, TABLE_TASK_TIMES, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void createTimesTable() {
|
||||
var sql = """
|
||||
CREATE TABLE IF NOT EXISTS {0} (
|
||||
{1} INTEGER PRIMARY KEY,
|
||||
{2} INTEGER NOT NULL,
|
||||
{3} VARCHAR(255) NOT NULL,
|
||||
{4} TEXT,
|
||||
{5} TIMESTAMP,
|
||||
{6} TIMESTAMP,
|
||||
{7} INT NOT NULL DEFAULT {8}
|
||||
)""";
|
||||
sql = format(sql,TABLE_TIMES,ID,USER_ID,SUBJECT,DESCRIPTION,START_TIME,END_TIME,STATE, Time.State.Started.code());
|
||||
try {
|
||||
var stmt = db.prepareStatement(sql);
|
||||
stmt.execute();
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
LOG.log(ERROR, ERROR_FAILED_CREATE_TABLE, TABLE_TIMES, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Long,Time> listTimes(Collection<Long> taskIds, boolean showClosed) throws UmbrellaException {
|
||||
try {
|
||||
var rs = select(ALL).from(TABLE_TASK_TIMES).where(TASK_ID,in(taskIds.toArray())).exec(db);
|
||||
@@ -47,6 +106,7 @@ public class SqliteDb implements TimeDb {
|
||||
rs.close();
|
||||
return times;
|
||||
} catch (Exception e) {
|
||||
|
||||
throw new UmbrellaException("Failed to load times for task list");
|
||||
}
|
||||
}
|
||||
@@ -67,7 +127,6 @@ public class SqliteDb implements TimeDb {
|
||||
while (rs.next()){
|
||||
var time = times.get(rs.getLong(TIME_ID));
|
||||
time.taskIds().add(rs.getLong(TASK_ID));
|
||||
System.out.println(time);
|
||||
}
|
||||
rs.close();
|
||||
return times;
|
||||
|
||||
@@ -7,6 +7,8 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
public interface TimeDb {
|
||||
Time createNew(long userId, String subject, String description);
|
||||
|
||||
HashMap<Long,Time> listTimes(Collection<Long> taskIds, boolean showClosed) throws UmbrellaException;
|
||||
|
||||
HashMap<Long,Time> listUserTimes(long userId, boolean showClosed);
|
||||
|
||||
@@ -4,9 +4,10 @@ package de.srsoftware.umbrella.time;
|
||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
||||
import static de.srsoftware.umbrella.core.Constants.*;
|
||||
import static de.srsoftware.umbrella.core.Paths.LIST;
|
||||
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.*;
|
||||
import static de.srsoftware.umbrella.core.model.Time.State.Started;
|
||||
import static de.srsoftware.umbrella.time.Constants.*;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
@@ -21,6 +22,7 @@ import de.srsoftware.umbrella.core.model.*;
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class TimeModule extends BaseHandler implements TimeService {
|
||||
@@ -55,6 +57,7 @@ public class TimeModule extends BaseHandler implements TimeService {
|
||||
if (user.isEmpty()) return unauthorized(ex);
|
||||
var head = path.pop();
|
||||
return switch (head) {
|
||||
case ADD_TASK -> getAddTask(user.get(),path,ex);
|
||||
case null -> getUserTimes(user.get(),ex);
|
||||
default -> super.doGet(path,ex);
|
||||
};
|
||||
@@ -63,7 +66,7 @@ public class TimeModule extends BaseHandler implements TimeService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public boolean doPost(Path path, HttpExchange ex) throws IOException {
|
||||
addCors(ex);
|
||||
try {
|
||||
@@ -80,7 +83,31 @@ public class TimeModule extends BaseHandler implements TimeService {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getUserTimes(UmbrellaUser user, HttpExchange ex) throws IOException {
|
||||
private boolean getAddTask(UmbrellaUser user, Path path, HttpExchange ex) throws IOException {
|
||||
if (path.empty()) throw missingFieldException(TASK_ID);
|
||||
long taskId;
|
||||
try {
|
||||
taskId = Long.parseLong(path.pop());
|
||||
} catch (NumberFormatException e) {
|
||||
throw invalidFieldException(TASK_ID,"long value");
|
||||
}
|
||||
var taskIds = new HashSet<Long>();
|
||||
var times = timeDb.listUserTimes(user.id(), false).values().stream()
|
||||
.filter(time -> time.state() == Started)
|
||||
.peek(time -> taskIds.addAll(time.taskIds()))
|
||||
.collect(Collectors.toMap(Time::id, t -> t));
|
||||
taskIds.add(taskId);
|
||||
var tasks = taskService().load(taskIds);
|
||||
if (times.isEmpty()){
|
||||
var task = tasks.get(taskId);
|
||||
if (task == null) throw UmbrellaException.notFound("Failed to find task with id = {0}",taskId);
|
||||
var time = timeDb.createNew(user.id(),task.name(),task.description());
|
||||
times.put(time.id(),time);
|
||||
}
|
||||
return sendContent(ex,Map.of(TIMES,times,TASKS,tasks));
|
||||
}
|
||||
|
||||
private boolean getUserTimes(UmbrellaUser user, HttpExchange ex) throws IOException {
|
||||
Set<Long> taskIds = new HashSet<>();
|
||||
Map<Long, Project> projects = projectService().listUserProjects(user.id(), true);
|
||||
for (var pid : projects.keySet()) taskIds.addAll(taskService().listProjectTasks(pid).keySet());
|
||||
|
||||
Reference in New Issue
Block a user