Browse Source

implemented changing project state from project page

kanban
Stephan Richter 4 months ago
parent
commit
c8b6c3feb7
  1. 1
      core/src/main/java/de/srsoftware/umbrella/core/Paths.java
  2. 1
      documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java
  3. 1
      documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java
  4. 30
      frontend/src/Components/StateSelector.svelte
  5. 7
      frontend/src/routes/project/View.svelte
  6. 13
      project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java
  7. 29
      task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java
  8. 2
      translations/src/main/resources/de.json
  9. BIN
      web/src/main/resources/web/fontawesome-webfont.woff

1
core/src/main/java/de/srsoftware/umbrella/core/Paths.java

@ -14,6 +14,7 @@ public class Paths {
public static final String SEARCH = "search"; public static final String SEARCH = "search";
public static final String SERVICE = "service"; public static final String SERVICE = "service";
public static final String SETTINGS = "settings"; public static final String SETTINGS = "settings";
public static final String STATES = "states";
public static final String SUBMIT = "submit"; public static final String SUBMIT = "submit";
public static final String TOKEN = "token"; public static final String TOKEN = "token";
public static final String VIEW = "view"; public static final String VIEW = "view";

1
documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java

@ -84,7 +84,6 @@ public class Constants {
public static final String POSITION = "position"; public static final String POSITION = "position";
public static final String PROJECT_ID = "project_id"; public static final String PROJECT_ID = "project_id";
public static final String STATES = "states";
public static final String TABLE_COMPANY_SETTINGS = "company_settings"; public static final String TABLE_COMPANY_SETTINGS = "company_settings";
public static final String TABLE_CUSTOMER_SETTINGS = "company_customer_settings"; public static final String TABLE_CUSTOMER_SETTINGS = "company_customer_settings";

1
documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java

@ -14,6 +14,7 @@ import static de.srsoftware.tools.Strings.escapeHtmlEntities;
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.Paths.STATES;
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE;
import static de.srsoftware.umbrella.core.Util.request; import static de.srsoftware.umbrella.core.Util.request;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;

30
frontend/src/Components/StateSelector.svelte

@ -0,0 +1,30 @@
<script>
import {onMount} from 'svelte';
import {t} from '../translations.svelte.js';
let { caption = t('select_state'), selected = $bindable(0), onchange = (val) => console.log('changed to '+val)} = $props();
let message = $state(t('loading'));
let states = $state(null);
async function loadStates(){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/task/states`;
var resp = await fetch(url,{credentials: 'include'});
if (resp.ok){
states = await resp.json();
} else {
message = await resp.text();
}
}
onMount(loadStates)
</script>
{#if states}
<select bind:value={selected} onchange={() => onchange(selected)}>
{#each Object.entries(states) as [k,s]}
<option value={+k}>{t('state_'+s.toLowerCase())}</option>
{/each}
</select>
{:else}
<span>{message}</span>
{/if}

7
frontend/src/routes/project/View.svelte

@ -4,6 +4,7 @@
import TaskList from '../../Components/TaskList.svelte'; import TaskList from '../../Components/TaskList.svelte';
import MarkdownEditor from '../../Components/MarkdownEditor.svelte'; import MarkdownEditor from '../../Components/MarkdownEditor.svelte';
import LineEditor from '../../Components/LineEditor.svelte'; import LineEditor from '../../Components/LineEditor.svelte';
import StateSelector from '../../Components/StateSelector.svelte';
let { id } = $props(); let { id } = $props();
let project = $state(null); let project = $state(null);
@ -69,6 +70,12 @@
<LineEditor bind:value={project.name} editable={true} onSet={val => update({name:val})} /> <LineEditor bind:value={project.name} editable={true} onSet={val => update({name:val})} />
</td> </td>
</tr> </tr>
<tr>
<th>{t('state')}</th>
<td>
<StateSelector selected={project.status.code} onchange={val => update({status:val})}/>
</td>
</tr>
{#if project.company} {#if project.company}
<tr> <tr>
<th>{t('company')}</th> <th>{t('company')}</th>

13
project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java

@ -115,9 +115,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
} }
} }
private boolean getProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException { private boolean addMembers(Project project, HttpExchange ex) throws IOException {
var project = projects.load(projectId);
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>>(); var members = new HashMap<Long,Map<String,Object>>();
for (var member : project.members()){ for (var member : project.members()){
@ -128,6 +126,13 @@ public class ProjectModule extends BaseHandler implements ProjectService {
if (!members.isEmpty()) map.put(MEMBERS,members); 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 getProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException {
var project = projects.load(projectId);
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
return addMembers(project,ex);
} }
private boolean postProjectList(HttpExchange ex, UmbrellaUser user) throws IOException { private boolean postProjectList(HttpExchange ex, UmbrellaUser user) throws IOException {
@ -183,7 +188,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
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));
return sendContent(ex,project.toMap()); return addMembers(project,ex);
} }

29
task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java

@ -6,6 +6,7 @@ import static de.srsoftware.tools.Optionals.isSet;
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.Paths.STATES;
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_NOT_IMPLEMENTED; import static de.srsoftware.umbrella.core.ResponseCode.HTTP_NOT_IMPLEMENTED;
import static de.srsoftware.umbrella.core.Util.mapValues; 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;
@ -22,10 +23,7 @@ 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.*;
import de.srsoftware.umbrella.core.model.Task;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
@ -49,6 +47,23 @@ public class TaskModule extends BaseHandler implements TaskService {
return companies; return companies;
} }
@Override
public boolean doGet(Path path, HttpExchange ex) throws IOException {
addCors(ex);
try {
Optional<Token> token = SessionToken.from(ex).map(Token::of);
var user = users.loadUser(token);
if (user.isEmpty()) return unauthorized(ex);
var head = path.pop();
return switch (head) {
case STATES -> getStateList(ex);
default -> super.doGet(path,ex);
};
} catch (UmbrellaException e){
return send(ex,e);
}
}
@Override @Override
public boolean doPost(Path path, HttpExchange ex) throws IOException { public boolean doPost(Path path, HttpExchange ex) throws IOException {
addCors(ex); addCors(ex);
@ -89,6 +104,12 @@ public class TaskModule extends BaseHandler implements TaskService {
return sendContent(ex,result); return sendContent(ex,result);
} }
private boolean getStateList(HttpExchange ex) throws IOException {
var map = new HashMap<Integer,String>();
for (var status : Status.values()) map.put(status.code(),status.name());
return sendContent(ex,map);
}
@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);

2
translations/src/main/resources/de.json

@ -175,7 +175,9 @@
"state_new":"neu", "state_new":"neu",
"state_open": "offen", "state_open": "offen",
"state_payed": "bezahlt", "state_payed": "bezahlt",
"state_pending": "ausstehend",
"state_sent": "versendet", "state_sent": "versendet",
"state_started": "gestartet",
"status" : { "status" : {
"403": "Zugriff verweigert", "403": "Zugriff verweigert",
"404": "Seite nicht gefunden", "404": "Seite nicht gefunden",

BIN
web/src/main/resources/web/fontawesome-webfont.woff

Binary file not shown.
Loading…
Cancel
Save