refactoring project module: better separation of loading of projects and loading of project members
This commit is contained in:
@@ -11,7 +11,10 @@ public class Constants {
|
|||||||
public static final String ADDRESS = "address";
|
public static final String ADDRESS = "address";
|
||||||
public static final String ATTACHMENTS = "attachments";
|
public static final String ATTACHMENTS = "attachments";
|
||||||
public static final String AUTHORIZATION = "Authorization";
|
public static final String AUTHORIZATION = "Authorization";
|
||||||
|
|
||||||
public static final String BODY = "body";
|
public static final String BODY = "body";
|
||||||
|
|
||||||
|
public static final String CODE = "code";
|
||||||
public static final String COMPANY = "company";
|
public static final String COMPANY = "company";
|
||||||
public static final String COMPANY_ID = "company_id";
|
public static final String COMPANY_ID = "company_id";
|
||||||
public static final String CONTENT_TYPE = "Content-Type";
|
public static final String CONTENT_TYPE = "Content-Type";
|
||||||
|
|||||||
@@ -4,10 +4,17 @@ package de.srsoftware.umbrella.core.api;
|
|||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.Project;
|
import de.srsoftware.umbrella.core.model.Project;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface ProjectService {
|
public interface ProjectService {
|
||||||
public Collection<Project> listCompanyProjects(long companyId, boolean includeClosed) throws UmbrellaException;
|
|
||||||
public Map<Long,Project> listUserProjects(long userId, boolean includeClosed) throws UmbrellaException;
|
|
||||||
CompanyService companyService();
|
CompanyService companyService();
|
||||||
|
public Map<Long,Project> listCompanyProjects(long companyId, boolean includeClosed) throws UmbrellaException;
|
||||||
|
public Map<Long,Project> listUserProjects(long userId, boolean includeClosed) throws UmbrellaException;
|
||||||
|
public Collection<Project> loadMembers(Collection<Project> projects);
|
||||||
|
public default Project loadMembers(Project project){
|
||||||
|
loadMembers(List.of(project));
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
Map<Long, Map<String,Object>> mapProjects(Map<Long, Project> projects);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import static de.srsoftware.umbrella.core.Constants.*;
|
|||||||
import de.srsoftware.tools.Mappable;
|
import de.srsoftware.tools.Mappable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public record Member(long userId, Permission permission) implements Mappable {
|
public record Member(UmbrellaUser user, Permission permission) implements Mappable {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> toMap() {
|
public Map<String, Object> toMap() {
|
||||||
return Map.of(USER_ID,userId,PERMISSION,permission.name());
|
return Map.of(USER,user.toMap(),PERMISSION,permission.toMap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
/* © SRSoftware 2025 */
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.core.model;
|
package de.srsoftware.umbrella.core.model;
|
||||||
|
|
||||||
|
import static de.srsoftware.umbrella.core.Constants.CODE;
|
||||||
|
import static de.srsoftware.umbrella.core.Constants.NAME;
|
||||||
import static java.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
|
|
||||||
|
import de.srsoftware.tools.Mappable;
|
||||||
import java.security.InvalidParameterException;
|
import java.security.InvalidParameterException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public enum Permission {
|
public enum Permission implements Mappable {
|
||||||
OWNER(1),
|
OWNER(1),
|
||||||
EDIT(2),
|
EDIT(2),
|
||||||
ASSIGNEE(3),
|
ASSIGNEE(3),
|
||||||
@@ -27,4 +31,9 @@ public enum Permission {
|
|||||||
}
|
}
|
||||||
throw new InvalidParameterException(format("{0} is not a valid permission code"));
|
throw new InvalidParameterException(format("{0} is not a valid permission code"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> toMap() {
|
||||||
|
return Map.of(NAME,name(),CODE,code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class Project implements Mappable {
|
|||||||
|
|
||||||
public boolean hasMember(UmbrellaUser user) {
|
public boolean hasMember(UmbrellaUser user) {
|
||||||
for (var member : members){
|
for (var member : members){
|
||||||
if (member.userId() == user.id()) return true;
|
if (member.user().id() == user.id()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package de.srsoftware.umbrella.items;
|
|||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
private Constants(){}
|
private Constants(){}
|
||||||
public static final String CODE = "code";
|
|
||||||
public static final String CONFIG_DATABASE = "umbrella.modules.items.database";
|
public static final String CONFIG_DATABASE = "umbrella.modules.items.database";
|
||||||
public static final String TABLE_ITEMS = "items";
|
public static final String TABLE_ITEMS = "items";
|
||||||
public static final String TAX = "tax";
|
public static final String TAX = "tax";
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
package de.srsoftware.umbrella.project;
|
package de.srsoftware.umbrella.project;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
|
import de.srsoftware.umbrella.core.model.Permission;
|
||||||
import de.srsoftware.umbrella.core.model.Project;
|
import de.srsoftware.umbrella.core.model.Project;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface ProjectDb {
|
public interface ProjectDb {
|
||||||
|
Map<Long, Permission> getMembers(Project project);
|
||||||
|
Project load(long projectId) throws UmbrellaException;
|
||||||
Map<Long, Project> ofCompany(long companyId, boolean includeClosed) throws UmbrellaException;
|
Map<Long, Project> ofCompany(long companyId, boolean includeClosed) throws UmbrellaException;
|
||||||
Map<Long, Project> ofUser(long userId, boolean includeClosed) throws UmbrellaException;
|
Map<Long, Project> ofUser(long userId, boolean includeClosed) throws UmbrellaException;
|
||||||
|
|
||||||
Project save(Project prj) throws UmbrellaException;
|
Project save(Project prj) throws UmbrellaException;
|
||||||
|
|
||||||
Project load(long projectId) throws UmbrellaException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import static de.srsoftware.umbrella.core.model.Status.OPEN;
|
|||||||
import static de.srsoftware.umbrella.project.Constants.CONFIG_DATABASE;
|
import static de.srsoftware.umbrella.project.Constants.CONFIG_DATABASE;
|
||||||
import static java.lang.Boolean.TRUE;
|
import static java.lang.Boolean.TRUE;
|
||||||
import static java.net.HttpURLConnection.HTTP_OK;
|
import static java.net.HttpURLConnection.HTTP_OK;
|
||||||
import static java.util.Comparator.comparing;
|
|
||||||
|
|
||||||
import com.sun.net.httpserver.HttpExchange;
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import de.srsoftware.configuration.Configuration;
|
import de.srsoftware.configuration.Configuration;
|
||||||
@@ -57,10 +56,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
|||||||
default -> {
|
default -> {
|
||||||
var projectId = Long.parseLong(head);
|
var projectId = Long.parseLong(head);
|
||||||
head = path.pop();
|
head = path.pop();
|
||||||
yield switch (head){
|
yield head == null ? getProject(ex,projectId,user.get()) : super.doGet(path,ex);
|
||||||
case null -> getProject(ex,projectId,user.get());
|
|
||||||
default -> super.doGet(path,ex);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} catch (UmbrellaException e){
|
} catch (UmbrellaException e){
|
||||||
@@ -116,70 +112,61 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean getProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException {
|
private boolean getProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||||
var project = projects.load(projectId);
|
var project = loadMembers(projects.load(projectId));
|
||||||
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
|
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
|
||||||
var map = project.toMap();
|
var map = project.toMap();
|
||||||
var members = new HashMap<Long,Map<String,Object>>();
|
|
||||||
for (var member : project.members()){
|
|
||||||
var perm = member.permission().name();
|
|
||||||
var userId = member.userId();
|
|
||||||
members.put(userId,Map.of(USER,users.loadUser(userId).toMap(),PERMISSION,perm));
|
|
||||||
}
|
|
||||||
if (!members.isEmpty()) map.put(MEMBERS,members);
|
|
||||||
project.companyId().map(companies::get).map(Company::toMap).ifPresent(data -> map.put(COMPANY,data));
|
project.companyId().map(companies::get).map(Company::toMap).ifPresent(data -> map.put(COMPANY,data));
|
||||||
return sendContent(ex,map);
|
return sendContent(ex,map);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean postProjectList(HttpExchange ex, UmbrellaUser user) throws IOException {
|
public Map<Long, Project> listCompanyProjects(long companyId, boolean includeClosed) throws UmbrellaException {
|
||||||
var json = json(ex);
|
var projectList = projects.ofCompany(companyId, includeClosed);
|
||||||
var showClosed = json.has(SHOW_CLOSED) && json.get(SHOW_CLOSED) instanceof Boolean bool ? bool : false;
|
loadMembers(projectList.values());
|
||||||
if (json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number companyId) return listCompanyProjects(ex, user, companyId.longValue());
|
return projectList;
|
||||||
return listUserProjects(ex,user,showClosed);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Collection<Project> listCompanyProjects(long companyId, boolean includeClosed) throws UmbrellaException {
|
|
||||||
return projects.ofCompany(companyId, includeClosed).values().stream().sorted(comparing(Project::name)).toList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean listCompanyProjects(HttpExchange ex, UmbrellaUser user, long companyId) throws IOException, UmbrellaException {
|
private boolean listCompanyProjects(HttpExchange ex, UmbrellaUser user, long companyId) throws IOException, UmbrellaException {
|
||||||
var company = companies.get(companyId);
|
var company = companies.get(companyId);
|
||||||
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name());
|
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name());
|
||||||
var projects = listCompanyProjects(companyId,false)
|
var projects = listCompanyProjects(companyId,false);
|
||||||
.stream()
|
return sendContent(ex,mapProjects(projects));
|
||||||
.map(Project::toMap)
|
|
||||||
.map(HashMap::new);
|
|
||||||
return sendContent(ex,projects);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Long, Project> listUserProjects(long userId, boolean includeClosed) throws UmbrellaException {
|
public Map<Long, Project> listUserProjects(long userId, boolean includeClosed) throws UmbrellaException {
|
||||||
return projects.ofUser(userId, includeClosed);
|
var projectMap = projects.ofUser(userId, includeClosed);
|
||||||
|
loadMembers(projectMap.values());
|
||||||
|
return projectMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean listUserProjects(HttpExchange ex, UmbrellaUser user, boolean showClosed) throws IOException, UmbrellaException {
|
private boolean listUserProjects(HttpExchange ex, UmbrellaUser user, boolean showClosed) throws IOException, UmbrellaException {
|
||||||
var projects = new HashMap<Long,Map<String,Object>>();
|
var projects = listUserProjects(user.id(),showClosed);
|
||||||
for (var entry : listUserProjects(user.id(),showClosed).entrySet()) {
|
return sendContent(ex,mapProjects(projects));
|
||||||
var project = entry.getValue();
|
}
|
||||||
var map = project.toMap();
|
|
||||||
var members = new HashMap<Long,Map<String,Object>>();
|
@Override
|
||||||
var userMap = new HashMap<Long,UmbrellaUser>();
|
public Collection<Project> loadMembers(Collection<Project> projectList) {
|
||||||
for (var member : project.members()){
|
var userMap = new HashMap<Long,UmbrellaUser>();
|
||||||
var perm = member.permission().name();
|
for (var project : projectList){
|
||||||
var userId = member.userId();
|
for (var entry : projects.getMembers(project).entrySet()){
|
||||||
var u = userMap.get(userId);
|
var userId = entry.getKey();
|
||||||
if (u == null) userMap.put(userId,u = users.loadUser(userId));
|
var permission = entry.getValue();
|
||||||
members.put(userId,Map.of(USER,u.toMap(),PERMISSION,perm));
|
var user = userMap.computeIfAbsent(userId,k -> users.loadUser(userId));
|
||||||
|
project.members().add(new Member(user,permission));
|
||||||
}
|
}
|
||||||
if (!members.isEmpty()) map.put(MEMBERS,members);
|
|
||||||
projects.put(entry.getKey(),map);
|
|
||||||
}
|
}
|
||||||
return sendContent(ex,projects);
|
return projectList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, Map<String, Object>> mapProjects(Map<Long, Project> projects) {
|
||||||
|
var mapped = new HashMap<Long,Map<String,Object>>();
|
||||||
|
for (var entry : projects.entrySet()) mapped.put(entry.getKey(),entry.getValue().toMap());
|
||||||
|
return mapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean patchProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException {
|
private boolean patchProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||||
var project = projects.load(projectId);
|
var project = loadMembers(projects.load(projectId));
|
||||||
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
|
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
|
||||||
var json = json(ex);
|
var json = json(ex);
|
||||||
projects.save(project.patch(json));
|
projects.save(project.patch(json));
|
||||||
@@ -200,8 +187,15 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
|||||||
if (json.has(SETTINGS) && json.get(SETTINGS) instanceof JSONObject settingsJson){
|
if (json.has(SETTINGS) && json.get(SETTINGS) instanceof JSONObject settingsJson){
|
||||||
showClosed = settingsJson.has(SHOW_CLOSED) && settingsJson.get(SHOW_CLOSED) == TRUE;
|
showClosed = settingsJson.has(SHOW_CLOSED) && settingsJson.get(SHOW_CLOSED) == TRUE;
|
||||||
}
|
}
|
||||||
var prj = new Project(0,name,description, OPEN,companyId,showClosed, List.of(new Member(user.id(), OWNER)));
|
var prj = new Project(0,name,description, OPEN,companyId,showClosed, List.of(new Member(user, OWNER)));
|
||||||
prj = projects.save(prj);
|
prj = projects.save(prj);
|
||||||
return sendContent(ex,prj);
|
return sendContent(ex,prj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean postProjectList(HttpExchange ex, UmbrellaUser user) throws IOException {
|
||||||
|
var json = json(ex);
|
||||||
|
var showClosed = json.has(SHOW_CLOSED) && json.get(SHOW_CLOSED) instanceof Boolean bool ? bool : false;
|
||||||
|
if (json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number companyId) return listCompanyProjects(ex, user, companyId.longValue());
|
||||||
|
return listUserProjects(ex,user,showClosed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,6 @@ import static java.text.MessageFormat.format;
|
|||||||
|
|
||||||
import de.srsoftware.tools.jdbc.Query;
|
import de.srsoftware.tools.jdbc.Query;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.Member;
|
|
||||||
import de.srsoftware.umbrella.core.model.Permission;
|
import de.srsoftware.umbrella.core.model.Permission;
|
||||||
import de.srsoftware.umbrella.core.model.Project;
|
import de.srsoftware.umbrella.core.model.Project;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
@@ -36,19 +35,6 @@ public class SqliteDb implements ProjectDb {
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Long, Project> addMembers(Map<Long, Project> projects) throws SQLException, UmbrellaException {
|
|
||||||
Object[] ids = projects.keySet().toArray();
|
|
||||||
var rs = select(ALL).from(TABLE_PROJECT_USERS).where(PROJECT_ID,in(ids)).exec(db);
|
|
||||||
while (rs.next()){
|
|
||||||
var userId = rs.getLong(USER_ID);
|
|
||||||
var projectId = rs.getLong(PROJECT_ID);
|
|
||||||
var permission = Permission.of(rs.getInt(PERMISSIONS));
|
|
||||||
projects.get(projectId).members().add(new Member(userId,permission));
|
|
||||||
}
|
|
||||||
rs.close();
|
|
||||||
return projects;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int createTables() {
|
private int createTables() {
|
||||||
createProjectTables();
|
createProjectTables();
|
||||||
return createSettingsTable();
|
return createSettingsTable();
|
||||||
@@ -129,6 +115,20 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, Permission> getMembers(Project project) {
|
||||||
|
try {
|
||||||
|
var result = new HashMap<Long,Permission>();
|
||||||
|
var rs = select(ALL).from(TABLE_PROJECT_USERS).where(PROJECT_ID,equal(project.id())).exec(db);
|
||||||
|
while (rs.next()) result.put(rs.getLong(USER_ID),Permission.of(rs.getInt(PERMISSIONS)));
|
||||||
|
rs.close();
|
||||||
|
return result;
|
||||||
|
} catch (SQLException e){
|
||||||
|
throw new UmbrellaException(HTTP_SERVER_ERROR,"Faailed to load project members");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void init(){
|
private void init(){
|
||||||
var version = createTables();
|
var version = createTables();
|
||||||
LOG.log(INFO,"Updated project db to version {0}",version);
|
LOG.log(INFO,"Updated project db to version {0}",version);
|
||||||
@@ -142,7 +142,6 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
|
|||||||
if (rs.next()) result = Project.of(rs);
|
if (rs.next()) result = Project.of(rs);
|
||||||
rs.close();
|
rs.close();
|
||||||
if (result == null) throw UmbrellaException.notFound("No project found for id {0}",projectId);
|
if (result == null) throw UmbrellaException.notFound("No project found for id {0}",projectId);
|
||||||
addMembers(Map.of(projectId,result));
|
|
||||||
return result;
|
return result;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new UmbrellaException(HTTP_SERVER_ERROR,"Failed to load items from database");
|
throw new UmbrellaException(HTTP_SERVER_ERROR,"Failed to load items from database");
|
||||||
@@ -161,7 +160,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
|
|||||||
projects.put(project.id(),project);
|
projects.put(project.id(),project);
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
return addMembers(projects);
|
return projects;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new UmbrellaException(HTTP_SERVER_ERROR,"Failed to load items from database");
|
throw new UmbrellaException(HTTP_SERVER_ERROR,"Failed to load items from database");
|
||||||
}
|
}
|
||||||
@@ -181,7 +180,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
|
|||||||
projects.put(project.id(),project);
|
projects.put(project.id(),project);
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
return addMembers(projects);
|
return projects;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new UmbrellaException(HTTP_SERVER_ERROR,"Failed to load items from database");
|
throw new UmbrellaException(HTTP_SERVER_ERROR,"Failed to load items from database");
|
||||||
}
|
}
|
||||||
@@ -198,7 +197,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
|
|||||||
if (id != null){
|
if (id != null){
|
||||||
if (!prj.members().isEmpty()) {
|
if (!prj.members().isEmpty()) {
|
||||||
var query = insertInto(TABLE_PROJECT_USERS, PROJECT_ID, USER_ID, PERMISSIONS);
|
var query = insertInto(TABLE_PROJECT_USERS, PROJECT_ID, USER_ID, PERMISSIONS);
|
||||||
for (var member : prj.members()) query.values(id, member.userId(), member.permission().code());
|
for (var member : prj.members()) query.values(id, member.user().id(), member.permission().code());
|
||||||
query.execute(db).close();
|
query.execute(db).close();
|
||||||
}
|
}
|
||||||
return new Project(id, prj.name(), prj.description(),prj.status(),prj.companyId().orElse(null),prj.showClosed(),prj.members());
|
return new Project(id, prj.name(), prj.description(),prj.status(),prj.companyId().orElse(null),prj.showClosed(),prj.members());
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import de.srsoftware.umbrella.core.model.Task;
|
|||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
public class SqliteDb implements TaskDb {
|
public class SqliteDb implements TaskDb {
|
||||||
@@ -28,7 +28,7 @@ public class SqliteDb implements TaskDb {
|
|||||||
db = connection;
|
db = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMap<Long, Task> listTasks(List<Long> projectIds) throws UmbrellaException {
|
public HashMap<Long, Task> listTasks(Collection<Long> projectIds) throws UmbrellaException {
|
||||||
try {
|
try {
|
||||||
var tasks = new HashMap<Long,Task>();
|
var tasks = new HashMap<Long,Task>();
|
||||||
var rs = select(ALL).from(TABLE_TASKS).where(PROJECT_ID, in(projectIds.toArray())).exec(db);
|
var rs = select(ALL).from(TABLE_TASKS).where(PROJECT_ID, in(projectIds.toArray())).exec(db);
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import de.srsoftware.umbrella.core.api.ProjectService;
|
|||||||
import de.srsoftware.umbrella.core.api.TaskService;
|
import de.srsoftware.umbrella.core.api.TaskService;
|
||||||
import de.srsoftware.umbrella.core.api.UserService;
|
import de.srsoftware.umbrella.core.api.UserService;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.Project;
|
|
||||||
import de.srsoftware.umbrella.core.model.Task;
|
import de.srsoftware.umbrella.core.model.Task;
|
||||||
import de.srsoftware.umbrella.core.model.Token;
|
import de.srsoftware.umbrella.core.model.Token;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
@@ -73,17 +72,17 @@ public class TaskModule extends BaseHandler implements TaskService {
|
|||||||
var companyId = cid.longValue();
|
var companyId = cid.longValue();
|
||||||
var company = companies.get(companyId);
|
var company = companies.get(companyId);
|
||||||
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name());
|
if (!companies.membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name());
|
||||||
var projects = this.projects.listCompanyProjects(companyId,false);
|
var projectMap = this.projects.listCompanyProjects(companyId,false);
|
||||||
var map = taskDb.listTasks(projects.stream().map(Project::id).toList());
|
var taskMap = taskDb.listTasks(projectMap.keySet());
|
||||||
var tree = new HashMap<Long,Map<String,Object>>();
|
var taskTree = new HashMap<Long,Map<String,Object>>();
|
||||||
map.values().stream().filter(task -> !is0(task.estimatedTime())).forEach(task -> placeInTree(task,tree,map));
|
taskMap.values().stream().filter(task -> !is0(task.estimatedTime())).forEach(task -> placeInTree(task,taskTree,taskMap));
|
||||||
var result = new ArrayList<Map<String,Object>>();
|
var result = new ArrayList<Map<String,Object>>();
|
||||||
projects.forEach(project -> {
|
projectMap.values().forEach(project -> {
|
||||||
var projectMap = new HashMap<>(project.toMap());
|
var mappedProject = new HashMap<>(project.toMap());
|
||||||
var children = tree.values().stream().filter(root -> project.id() == (Long)root.get(PROJECT_ID)).toList();
|
var children = taskTree.values().stream().filter(root -> project.id() == (Long)root.get(PROJECT_ID)).toList();
|
||||||
if (!children.isEmpty()) {
|
if (!children.isEmpty()) {
|
||||||
projectMap.put(TASKS, children);
|
mappedProject.put(TASKS, children);
|
||||||
result.add(projectMap);
|
result.add(mappedProject);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return sendContent(ex,result);
|
return sendContent(ex,result);
|
||||||
@@ -92,7 +91,7 @@ public class TaskModule extends BaseHandler implements TaskService {
|
|||||||
@Override
|
@Override
|
||||||
public HashMap<Long, Task> listCompanyTasks(long companyId) throws UmbrellaException {
|
public HashMap<Long, Task> listCompanyTasks(long companyId) throws UmbrellaException {
|
||||||
var projectList = projects.listCompanyProjects(companyId,false);
|
var projectList = projects.listCompanyProjects(companyId,false);
|
||||||
return taskDb.listTasks(projectList.stream().map(Project::id).toList());
|
return taskDb.listTasks(projectList.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -100,18 +99,18 @@ public class TaskModule extends BaseHandler implements TaskService {
|
|||||||
return taskDb.listTasks(List.of(projectId));
|
return taskDb.listTasks(List.of(projectId));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String,Object> placeInTree(Task task, HashMap<Long, Map<String,Object>> tree, Map<Long, Task> map) {
|
private Map<String,Object> placeInTree(Task task, HashMap<Long, Map<String,Object>> taskTree, Map<Long, Task> taskMap) {
|
||||||
var taskMap = task.toMap();
|
var mappedTask = task.toMap();
|
||||||
if (task.parentTaskId() != null){
|
if (task.parentTaskId() != null){
|
||||||
Task parent = map.get(task.parentTaskId());
|
Task parent = taskMap.get(task.parentTaskId());
|
||||||
var trunk = placeInTree(parent,tree,map);
|
var trunk = placeInTree(parent,taskTree,taskMap);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
ArrayList<Object> children = (ArrayList<Object>) trunk.computeIfAbsent(CHILDREN, k -> new ArrayList<Object>());
|
ArrayList<Object> children = (ArrayList<Object>) trunk.computeIfAbsent(CHILDREN, k -> new ArrayList<>());
|
||||||
children.add(taskMap);
|
children.add(mappedTask);
|
||||||
return taskMap;
|
return mappedTask;
|
||||||
}
|
}
|
||||||
tree.put(task.id(),taskMap);
|
taskTree.put(task.id(),mappedTask);
|
||||||
return taskMap;
|
return mappedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean postTaskList(UmbrellaUser user, HttpExchange ex) throws IOException {
|
private boolean postTaskList(UmbrellaUser user, HttpExchange ex) throws IOException {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ public class Constants {
|
|||||||
|
|
||||||
public static final String CLIENT_ID = "client_id";
|
public static final String CLIENT_ID = "client_id";
|
||||||
public static final String CLIENT_SECRET = "client_secret";
|
public static final String CLIENT_SECRET = "client_secret";
|
||||||
public static final String CODE = "code";
|
|
||||||
public static final String CONFIG_DATABASE = "umbrella.modules.user.database";
|
public static final String CONFIG_DATABASE = "umbrella.modules.user.database";
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user