Merge branch 'module/projects' into dev
Build Docker Image / Docker-Build (push) Successful in 5m20s
Build Docker Image / Clean-Registry (push) Successful in 3s

This commit is contained in:
2026-05-11 20:14:32 +02:00
3 changed files with 35 additions and 13 deletions
+20 -12
View File
@@ -2,7 +2,7 @@
import { onMount, onDestroy } from 'svelte';
import { useTinyRouter } from 'svelte-tiny-router';
import { api, eventStream } from '../../urls.svelte';
import { api, eventStream, patch, post } from '../../urls.svelte';
import { error, yikes } from '../../warn.svelte';
import { t } from '../../translations.svelte';
@@ -35,11 +35,7 @@
async function addState(){
const url = api(`project/${id}/state`);
const resp = await fetch(url,{
credentials: 'include',
method: 'POST',
body: JSON.stringify(new_state)
});
const resp = await post(url,new_state);
if (resp.ok){
const json = await resp.json();
project.allowed_states[json.code] = json.name;
@@ -139,11 +135,7 @@
async function update(data){
const url = api(`project/${id}`);
const resp = await fetch(url,{
credentials : 'include',
method : 'PATCH',
body : JSON.stringify(data)
});
const resp = await patch(url,data);
if (resp.ok){
yikes();
project = await resp.json();
@@ -160,6 +152,20 @@
update({members:members});
}
async function updateStateName(state_id,name){
const url = api(`project/${id}/state`);
const resp = await patch(url,{id:state_id,name});
if (resp.ok){
const json = await resp.json();
project.allowed_states[json.code]=json.name;
yikes();
return true;
} else {
error(resp);
return false;
}
}
function showClosed(){
show_closed = !show_closed;
loadTasks();
@@ -243,7 +249,9 @@
{/if}
{key}
</div>
<div>{project.allowed_states[key]}</div>
<div>
<LineEditor value={project.allowed_states[key]} editable={true} onSet={newName => updateStateName(+key,newName)} />
</div>
{/each}
<div>
<input type="number" bind:value={new_state.code} />
@@ -97,6 +97,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
head = path.pop();
yield switch (head){
case null -> patchProject(ex,projectId,user.get());
case Path.STATE -> patchProjectState(ex,projectId,user.get());
default -> super.doPatch(path,ex);
};
}
@@ -229,6 +230,19 @@ public class ProjectModule extends BaseHandler implements ProjectService {
return sendContent(ex,project.toMap());
}
private boolean patchProjectState(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException {
var project = loadMembers(projectDb.load(projectId));
if (!project.hasMember(user)) throw notAmember(t(PROJECT_WITH_ID,ID,project.name()));
var json = json(ex);
if (!json.has(ID)) throw missingField(ID);
if (!json.has(NAME)) throw missingField(NAME);
if (!(json.get(ID) instanceof Number fieldId)) throw invalidField(ID,Text.NUMBER);
var newName = json.getString(NAME);
if (newName.isBlank()) throw invalidField(NAME, STRING);
var newState = new Status(newName,fieldId.intValue());
return sendContent(ex, projectDb.save(projectId,newState));
}
private boolean postNewState(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException {
var project = loadMembers(load(projectId));
@@ -267,7 +267,7 @@ CREATE TABLE IF NOT EXISTS {0} (
@Override
public Status save(long projectId, Status newState) {
try {
insertInto(TABLE_CUSTOM_STATES, PROJECT_ID, Field.CODE, NAME).values(projectId,newState.code(),newState.name()).execute(db).close();
replaceInto(TABLE_CUSTOM_STATES, PROJECT_ID, Field.CODE, NAME).values(projectId,newState.code(),newState.name()).execute(db).close();
return newState;
} catch (SQLException e) {
throw databaseException(FAILED_TO_CREATE_STATE).causedBy(e);