diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/DbLocation.java b/core/src/main/java/de/srsoftware/umbrella/core/model/DbLocation.java index 040f25e..d92ca00 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/DbLocation.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/DbLocation.java @@ -43,6 +43,11 @@ public class DbLocation extends Location { return parentLocationId; } + public DbLocation parent(DbLocation newParent) { + parentLocationId = newParent.id(); + return this; + } + @Override public DbLocation resolve() { return this; diff --git a/frontend/src/routes/stock/Index.svelte b/frontend/src/routes/stock/Index.svelte index 6eb70ad..2eac356 100644 --- a/frontend/src/routes/stock/Index.svelte +++ b/frontend/src/routes/stock/Index.svelte @@ -10,10 +10,11 @@ import Notes from '../notes/RelatedNotes.svelte'; import Tags from '../tags/TagList.svelte'; - let loc_data = $derived.by(loadLocation); - let item = $state(null); - let location = $state(null); - let draggedItem = $state(null) + let loc_data = $derived.by(loadLocation); + let item = $state(null); + let location = $state(null); + let draggedItem = $state(null) + let draggedLocation = $state(null) $effect(() => { // This effect runs whenever `location` changes @@ -37,6 +38,16 @@ } else error(res); } + function drag_item(item){ + draggedLocation = null; + draggedItem = item; + } + + function drag_location(loc){ + draggedItem = null; + draggedLocation = loc; + } + function dropNestedLocation(locations,loc){ for (let [idx,entry] of locations.entries()){ if (entry.id == loc.id){ @@ -49,8 +60,9 @@ } async function move_dragged_to(new_loc){ - const data = { item : draggedItem.id, target: new_loc.id }; - const url = api('stock/move_item'); + console.log({move_dragged_to:JSON.parse(JSON.stringify(new_loc))}); + const data = draggedItem ? { item : draggedItem.id, target: new_loc.id } : { location : draggedLocation.id, target: new_loc.id } + const url = api(draggedItem ? 'stock/move_item' : 'stock/move_location'); const res = await fetch(url,{ credentials : 'include', method : 'PATCH', @@ -118,7 +130,12 @@ {#each top_level as realm,idx}

{realm.name}

{#if realm.locations} - + {/if} {/each} {/if} @@ -130,7 +147,7 @@ {#if location}

{location.name}

{/if} - a.code.localeCompare(b.code))} bind:selected={item} drag_start={item => draggedItem = item} /> + a.code.localeCompare(b.code))} bind:selected={item} drag_start={drag_item} />
diff --git a/frontend/src/routes/stock/Locations.svelte b/frontend/src/routes/stock/Locations.svelte index 3dea134..93e2f21 100644 --- a/frontend/src/routes/stock/Locations.svelte +++ b/frontend/src/routes/stock/Locations.svelte @@ -5,7 +5,13 @@ import LineEditor from '../../Components/LineEditor.svelte'; - let { locations, move_dragged_to = new_loc => {}, parent = null, selected = $bindable(null) } = $props(); + let { + drag_start = loc => console.log({dragging:loc}), + locations, + move_dragged_to = new_loc => {}, + parent = null, + selected = $bindable(null) + } = $props(); let show_location_form = $state(false); let new_location_name = $state(null); @@ -102,12 +108,14 @@ {#each locations as location}
  • toggleChildren(e, location)} class="{location.locations?'expanded':'collapsed'} {location.highlight?'highlight':null}" + draggable={true} ondragover={e => drag_over(e,location)} ondrop={e => onDrop(e,location)} - ondragleave={e => delete location.highlight}> + ondragleave={e => delete location.highlight} + ondragstart={e => drag_start(location)} > {location.name} {#if location.locations} - + {/if}
  • {/each} diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java b/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java index c56347b..4445dcb 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java @@ -13,6 +13,7 @@ public class Constants { public static final String ITEMS = "items"; public static final String LOCATIONS = "locations"; public static final String MOVE_ITEM = "move_item"; + public static final String MOVE_LOCATION = "move_location"; public static final String OF_USER = "of_user"; public static final String PARENT = "parent"; public static final String PROPERTY_ID = "prop_id"; diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java b/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java index c904b84..a75ad0d 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java @@ -288,7 +288,7 @@ public class SqliteDb extends BaseDb implements StockDb { } @Override - public Location save(DbLocation location) { + public DbLocation save(DbLocation location) { if (location.id() == 0) { // new location try { var rs = insertInto(TABLE_LOCATIONS,OWNER,PARENT_LOCATION_ID,NAME,DESCRIPTION) diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java b/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java index 80a954b..e0904a3 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java @@ -15,7 +15,7 @@ public interface StockDb { Collection listUserLocations(UmbrellaUser userId); Item loadItem(long id); DbLocation loadLocation(long locationId); - Location save(DbLocation location); + DbLocation save(DbLocation location); Item save(Item item); Property setProperty(long itemId, long existingPropId, Object value); } diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java index a1205c8..597b3ac 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java @@ -113,7 +113,8 @@ public class StockModule extends BaseHandler implements StockService { var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); return switch (path.pop()){ - case MOVE_ITEM -> patchMove(user.get(), path,ex); + case MOVE_ITEM -> patchMoveItem(user.get(), path,ex); + case MOVE_LOCATION -> patchMoveLocation(user.get(), path, ex); case null -> patchItem(user.get(),ex); default -> super.doPatch(path,ex); }; @@ -213,7 +214,7 @@ public class StockModule extends BaseHandler implements StockService { return sendContent(ex,stockDb.save(item)); } - private boolean patchMove(UmbrellaUser user, Path path, HttpExchange ex) throws IOException { + private boolean patchMoveItem(UmbrellaUser user, Path path, HttpExchange ex) throws IOException { var json = json(ex); if (!(json.get(ITEM) instanceof Number itemId)) throw missingFieldException(ITEM); if (!(json.get(TARGET) instanceof Number locationId)) throw missingFieldException(TARGET); @@ -232,6 +233,24 @@ public class StockModule extends BaseHandler implements StockService { return sendContent(ex,item); } + private boolean patchMoveLocation(UmbrellaUser user, Path path, HttpExchange ex) throws IOException { + var json = json(ex); + if (!(json.get(LOCATION) instanceof Number locationId)) throw missingFieldException(LOCATION); + if (!(json.get(TARGET) instanceof Number destLocationId)) throw missingFieldException(TARGET); + var location = stockDb.loadLocation(locationId.longValue()); + + var owner = location.owner().resolve(); + if (!assigned(owner,user)) throw forbidden("You are not allowed to alter the location of \"{0}\"!",location.name()); + + var target = stockDb.loadLocation(locationId.longValue()); + var locOwner = target.resolve().owner().resolve(); + if (!assigned(locOwner,user)) throw forbidden("You are not allowed to modify \"{0}\"!",target.name()); + + if (!locOwner.equals(owner)) throw unprocessable("You may not move locations from one owner ({0}) to another ({1})",owner,locOwner); + location = stockDb.save(location.parent(target)); + return sendContent(ex,location); + } + private boolean postLocation(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); if (!(json.get(NAME) instanceof String name)) throw missingFieldException(NAME);