preparing for task priorities
This commit is contained in:
@@ -135,6 +135,7 @@ public class Constants {
|
|||||||
public static final String PASSWORD = "password";
|
public static final String PASSWORD = "password";
|
||||||
public static final String PERMISSION = "permission";
|
public static final String PERMISSION = "permission";
|
||||||
public static final String POST = "POST";
|
public static final String POST = "POST";
|
||||||
|
public static final String PRIORITY = "priority";
|
||||||
public static final String PROJECT = "project";
|
public static final String PROJECT = "project";
|
||||||
public static final String PROJECT_ID = "project_id";
|
public static final String PROJECT_ID = "project_id";
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package de.srsoftware.umbrella.core.model;
|
|||||||
import static de.srsoftware.umbrella.core.Constants.*;
|
import static de.srsoftware.umbrella.core.Constants.*;
|
||||||
|
|
||||||
import de.srsoftware.tools.Mappable;
|
import de.srsoftware.tools.Mappable;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ public class Task implements Mappable {
|
|||||||
private final long id, projectId;
|
private final long id, projectId;
|
||||||
private Long parentTaskId;
|
private Long parentTaskId;
|
||||||
private String description, name;
|
private String description, name;
|
||||||
private Set<Long> requiredTasksIds;
|
private final Set<Long> requiredTasksIds;
|
||||||
private int status;
|
private int status, priority;
|
||||||
private Double estimatedTime;
|
private Double estimatedTime;
|
||||||
private LocalDate dueDate, start;
|
private LocalDate dueDate, start;
|
||||||
private boolean noIndex, showClosed;
|
private boolean noIndex, showClosed;
|
||||||
@@ -29,7 +29,7 @@ public class Task implements Mappable {
|
|||||||
private final Set<String> dirtyFields = new HashSet<>();
|
private final Set<String> dirtyFields = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
public Task (long id, long projectId, Long parentTaskId, String name, String description, int status, Double estimatedTime, LocalDate start, LocalDate dueDate, boolean showClosed, boolean noIndex, Map<Long,Member> members){
|
public Task (long id, long projectId, Long parentTaskId, String name, String description, int status, Double estimatedTime, LocalDate start, LocalDate dueDate, boolean showClosed, boolean noIndex, Map<Long,Member> members, int priority){
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.projectId = projectId;
|
this.projectId = projectId;
|
||||||
this.parentTaskId = parentTaskId;
|
this.parentTaskId = parentTaskId;
|
||||||
@@ -43,6 +43,7 @@ public class Task implements Mappable {
|
|||||||
this.noIndex = noIndex;
|
this.noIndex = noIndex;
|
||||||
this.members = members;
|
this.members = members;
|
||||||
this.requiredTasksIds = new HashSet<>();
|
this.requiredTasksIds = new HashSet<>();
|
||||||
|
this.priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task clean() {
|
public Task clean() {
|
||||||
@@ -105,6 +106,7 @@ public class Task implements Mappable {
|
|||||||
var parentTaskId = rs.getLong(PARENT_TASK_ID);
|
var parentTaskId = rs.getLong(PARENT_TASK_ID);
|
||||||
var startDate = nullIfEmpty(rs.getString(START_DATE));
|
var startDate = nullIfEmpty(rs.getString(START_DATE));
|
||||||
var dueDate = nullIfEmpty(rs.getString(DUE_DATE));
|
var dueDate = nullIfEmpty(rs.getString(DUE_DATE));
|
||||||
|
|
||||||
return new Task(
|
return new Task(
|
||||||
rs.getLong(ID),
|
rs.getLong(ID),
|
||||||
rs.getLong(PROJECT_ID),
|
rs.getLong(PROJECT_ID),
|
||||||
@@ -117,7 +119,8 @@ public class Task implements Mappable {
|
|||||||
dueDate != null ? LocalDate.parse(dueDate) : null,
|
dueDate != null ? LocalDate.parse(dueDate) : null,
|
||||||
rs.getBoolean(SHOW_CLOSED),
|
rs.getBoolean(SHOW_CLOSED),
|
||||||
rs.getBoolean(NO_INDEX),
|
rs.getBoolean(NO_INDEX),
|
||||||
new HashMap<>()
|
new HashMap<>(),
|
||||||
|
rs.getInt(PRIORITY)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,9 +152,9 @@ public class Task implements Mappable {
|
|||||||
LocalDate dueDate = json.has(DUE_DATE) && json.get(DUE_DATE) instanceof String d ? LocalDate.parse(d) : null;
|
LocalDate dueDate = json.has(DUE_DATE) && json.get(DUE_DATE) instanceof String d ? LocalDate.parse(d) : null;
|
||||||
var showClosed = json.has(SHOW_CLOSED) && json.get(SHOW_CLOSED) instanceof Boolean sc ? sc : false;
|
var showClosed = json.has(SHOW_CLOSED) && json.get(SHOW_CLOSED) instanceof Boolean sc ? sc : false;
|
||||||
var noIndex = json.has(NO_INDEX) && json.get(NO_INDEX) instanceof Boolean ni ? ni : false;
|
var noIndex = json.has(NO_INDEX) && json.get(NO_INDEX) instanceof Boolean ni ? ni : false;
|
||||||
|
var priority = json.has(PRIORITY) && json.get(PRIORITY) instanceof Number pr ? prjId.intValue() : 0;
|
||||||
if (!(json.has(MEMBERS) && json.get(MEMBERS) instanceof JSONObject)) throw missingFieldException(MEMBERS);
|
if (!(json.has(MEMBERS) && json.get(MEMBERS) instanceof JSONObject)) throw missingFieldException(MEMBERS);
|
||||||
return new Task(0,prjId.longValue(),parentTaskId,name,description,status,estimatedTime,startDate,dueDate,showClosed,noIndex,new HashMap<>());
|
return new Task(0,prjId.longValue(),parentTaskId,name,description,status,estimatedTime,startDate,dueDate,showClosed,noIndex,new HashMap<>(),priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task patch(JSONObject json) {
|
public Task patch(JSONObject json) {
|
||||||
@@ -164,6 +167,7 @@ public class Task implements Mappable {
|
|||||||
case NAME: name = json.getString(key); break;
|
case NAME: name = json.getString(key); break;
|
||||||
case NO_INDEX: noIndex = json.getBoolean(NO_INDEX); 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.getLong(PARENT_TASK_ID); break;
|
||||||
|
case PRIORITY: priority = json.getInt(PRIORITY); break;
|
||||||
case REQUIRED_TASKS_IDS:
|
case REQUIRED_TASKS_IDS:
|
||||||
requiredTasksIds.clear();
|
requiredTasksIds.clear();
|
||||||
requiredTasksIds.addAll(json.getJSONArray(REQUIRED_TASKS_IDS).toList().stream().map(entry -> Long.parseLong(entry.toString())).toList());
|
requiredTasksIds.addAll(json.getJSONArray(REQUIRED_TASKS_IDS).toList().stream().map(entry -> Long.parseLong(entry.toString())).toList());
|
||||||
@@ -185,6 +189,10 @@ public class Task implements Mappable {
|
|||||||
return parentTaskId;
|
return parentTaskId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int priority(){
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
public long projectId(){
|
public long projectId(){
|
||||||
return projectId;
|
return projectId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,6 +263,11 @@
|
|||||||
<input type="number" bind:value={task.estimated_time} onchange={() => update({estimated_time:task.estimated_time})} /> h
|
<input type="number" bind:value={task.estimated_time} onchange={() => update({estimated_time:task.estimated_time})} /> h
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>{t('priority')}</div>
|
||||||
|
<div>
|
||||||
|
<input type="number" bind:value={task.priority} onchange={() => update({priority:task.priority})} />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>{t('depends_on')}</div>
|
<div>{t('depends_on')}</div>
|
||||||
<div>
|
<div>
|
||||||
<RequiredTasks {task} />
|
<RequiredTasks {task} />
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import java.util.*;
|
|||||||
|
|
||||||
public class SqliteDb extends BaseDb implements TaskDb {
|
public class SqliteDb extends BaseDb implements TaskDb {
|
||||||
private static final System.Logger LOG = System.getLogger("TaskDb");
|
private static final System.Logger LOG = System.getLogger("TaskDb");
|
||||||
private static final int INITIAL_DB_VERSION = 1;
|
|
||||||
|
|
||||||
public SqliteDb(Connection connection) {
|
public SqliteDb(Connection connection) {
|
||||||
super(connection);
|
super(connection);
|
||||||
@@ -41,9 +40,11 @@ public class SqliteDb extends BaseDb implements TaskDb {
|
|||||||
swapStates(TABLE_TASKS);
|
swapStates(TABLE_TASKS);
|
||||||
case 2:
|
case 2:
|
||||||
createDependencyTable();
|
createDependencyTable();
|
||||||
|
case 3:
|
||||||
|
createPriorityColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
return setCurrentVersion(3);
|
return setCurrentVersion(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDependencyTable() {
|
private void createDependencyTable() {
|
||||||
@@ -59,6 +60,15 @@ public class SqliteDb extends BaseDb implements TaskDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createPriorityColumn() {
|
||||||
|
var sql = format("ALTER TABLE {0} ADD {1} INT NOT NULL DEFAULT 0",TABLE_TASKS,PRIORITY);
|
||||||
|
try {
|
||||||
|
db.prepareStatement(sql).execute();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw databaseException("Failed to add {0} column to {1}",PRIORITY,TABLE_TASKS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void createTaskTable() {
|
private void createTaskTable() {
|
||||||
var createTable = """
|
var createTable = """
|
||||||
CREATE TABLE IF NOT EXISTS "{0}" (
|
CREATE TABLE IF NOT EXISTS "{0}" (
|
||||||
@@ -299,15 +309,15 @@ CREATE TABLE IF NOT EXISTS {0} (
|
|||||||
public Task save(Task task) {
|
public Task save(Task task) {
|
||||||
try {
|
try {
|
||||||
if (task.id() == 0){ // new task
|
if (task.id() == 0){ // new task
|
||||||
var rs = insertInto(TABLE_TASKS,PROJECT_ID,PARENT_TASK_ID,NAME,DESCRIPTION,STATUS,EST_TIME,START_DATE,DUE_DATE,SHOW_CLOSED,NO_INDEX)
|
var rs = insertInto(TABLE_TASKS,PROJECT_ID,PARENT_TASK_ID,NAME,DESCRIPTION,STATUS,EST_TIME,START_DATE,DUE_DATE,SHOW_CLOSED,NO_INDEX,PRIORITY)
|
||||||
.values(task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex())
|
.values(task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex(),task.priority())
|
||||||
.execute(db)
|
.execute(db)
|
||||||
.getGeneratedKeys();
|
.getGeneratedKeys();
|
||||||
Long taskId = null;
|
Long taskId = null;
|
||||||
if (rs.next()) taskId=rs.getLong(1);
|
if (rs.next()) taskId=rs.getLong(1);
|
||||||
rs.close();
|
rs.close();
|
||||||
if (taskId == null) throw new UmbrellaException("Failed to save task {0}",task.name());
|
if (taskId == null) throw new UmbrellaException("Failed to save task {0}",task.name());
|
||||||
return new Task(taskId,task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex(),task.members());
|
return new Task(taskId,task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex(),task.members(), task.priority());
|
||||||
}
|
}
|
||||||
if (task.isDirty(MEMBERS)){
|
if (task.isDirty(MEMBERS)){
|
||||||
var query = replaceInto(TABLE_TASKS_USERS,TASK_ID,USER_ID,PERMISSIONS);
|
var query = replaceInto(TABLE_TASKS_USERS,TASK_ID,USER_ID,PERMISSIONS);
|
||||||
@@ -332,9 +342,9 @@ CREATE TABLE IF NOT EXISTS {0} (
|
|||||||
task.clean(REQUIRED_TASKS_IDS);
|
task.clean(REQUIRED_TASKS_IDS);
|
||||||
}
|
}
|
||||||
if (task.isDirty()) {
|
if (task.isDirty()) {
|
||||||
update(TABLE_TASKS).set(PROJECT_ID,PARENT_TASK_ID,NAME,DESCRIPTION,STATUS,EST_TIME,START_DATE,DUE_DATE,SHOW_CLOSED,NO_INDEX)
|
update(TABLE_TASKS).set(PROJECT_ID,PARENT_TASK_ID,NAME,DESCRIPTION,STATUS,EST_TIME,START_DATE,DUE_DATE,SHOW_CLOSED,NO_INDEX,PRIORITY)
|
||||||
.where(ID,equal(task.id())).prepare(db)
|
.where(ID,equal(task.id())).prepare(db)
|
||||||
.apply(task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex())
|
.apply(task.projectId(),task.parentTaskId(),task.name(),task.description(),task.status(),task.estimatedTime(),task.start(),task.dueDate(),task.showClosed(),task.noIndex(),task.priority())
|
||||||
.close();
|
.close();
|
||||||
task.clean();
|
task.clean();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ import de.srsoftware.umbrella.core.BaseHandler;
|
|||||||
import de.srsoftware.umbrella.core.api.WikiService;
|
import de.srsoftware.umbrella.core.api.WikiService;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.*;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class WikiModule extends BaseHandler implements WikiService {
|
public class WikiModule extends BaseHandler implements WikiService {
|
||||||
private final WikiDb wikiDb;
|
private final WikiDb wikiDb;
|
||||||
|
|||||||
Reference in New Issue
Block a user