Browse Source

Merge remote-tracking branch 'origin/module/stock' into module/stock

module/stock
Stephan Richter 22 hours ago
parent
commit
97ee1e4aad
  1. 21
      core/src/main/java/de/srsoftware/umbrella/core/Constants.java
  2. 61
      frontend/src/routes/stock/Index.svelte
  3. 10
      frontend/src/routes/stock/Locations.svelte
  4. 24
      stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java
  5. 29
      stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java
  6. 4
      stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java

21
core/src/main/java/de/srsoftware/umbrella/core/Constants.java

@ -93,16 +93,17 @@ public class Constants {
public static final String OWNER_NUMBER = "owner_number"; public static final String OWNER_NUMBER = "owner_number";
public static final String PARENT_LOCATION_ID = "parent_location_id"; public static final String PARENT_LOCATION_ID = "parent_location_id";
public static final String PARENT_TASK_ID = "parent_task_id"; public static final String PARENT_TASK_ID = "parent_task_id";
public static final String PASS = "pass"; public static final String PASS = "pass";
public static final String PASSWORD = "password"; public static final String PASSWORD = "password";
public static final String PERMISSION = "permission"; public static final String PATH = "path";
public static final String POST = "POST"; public static final String PERMISSION = "permission";
public static final String PRIORITY = "priority"; public static final String POST = "POST";
public static final String PROJECT = "project"; public static final String PRIORITY = "priority";
public static final String PROJECT_ID = "project_id"; public static final String PROJECT = "project";
public static final String PROPERTIES = "properties"; public static final String PROJECT_ID = "project_id";
public static final String PROPERTY = "property"; public static final String PROPERTIES = "properties";
public static final String PROPERTY = "property";
public static final String RECEIVERS = "receivers"; public static final String RECEIVERS = "receivers";
public static final String REDIRECT = "redirect"; public static final String REDIRECT = "redirect";

61
frontend/src/routes/stock/Index.svelte

@ -1,6 +1,6 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { api } from '../../urls.svelte'; import { api, drop, get, patch } from '../../urls.svelte';
import { error, yikes } from '../../warn.svelte'; import { error, yikes } from '../../warn.svelte';
import { t } from '../../translations.svelte'; import { t } from '../../translations.svelte';
@ -17,7 +17,7 @@
let location = $state(null); let location = $state(null);
let draggedItem = $state(null) let draggedItem = $state(null)
let draggedLocation = $state(null) let draggedLocation = $state(null)
let { location_id } = $props(); let { item_id, location_id, owner, owner_id } = $props();
$effect(() => { $effect(() => {
// This effect runs whenever `location` changes // This effect runs whenever `location` changes
@ -36,10 +36,7 @@
async function deleteLocation(loc){ async function deleteLocation(loc){
if (!confirm(t('confirm_delete',{element:loc.name}))) return; if (!confirm(t('confirm_delete',{element:loc.name}))) return;
const url = api(`stock/location/${loc.id}`); const url = api(`stock/location/${loc.id}`);
const res = await fetch(url,{ const res = await drop(url);
credentials: 'include',
method: 'DELETE',
});
if (res.ok){ if (res.ok){
yikes(); yikes();
unlistLocation(loc); unlistLocation(loc);
@ -70,11 +67,7 @@
async function move_dragged_to(new_loc){ async function move_dragged_to(new_loc){
const data = draggedItem ? { item : draggedItem.id, target: new_loc.id } : { parent_location_id: new_loc.id } const data = draggedItem ? { item : draggedItem.id, target: new_loc.id } : { parent_location_id: new_loc.id }
const url = api(draggedItem ? 'stock/move_item' : `stock/location/${draggedLocation.id}`); const url = api(draggedItem ? 'stock/move_item' : `stock/location/${draggedLocation.id}`);
const res = await fetch(url,{ const res = await patch(url,data);
credentials : 'include',
method : 'PATCH',
body : JSON.stringify(data)
});
if (res.ok){ if (res.ok){
yikes(); yikes();
location = new_loc; location = new_loc;
@ -88,8 +81,8 @@
async function loadLocation(){ async function loadLocation(){
if (!location) return null; if (!location) return null;
const url = api(`stock/location/${location.id}`) const url = api(`stock/location/${location.id}`);
const res = await fetch(url,{credentials:'include'}); const res = await get(url);
if (res.ok){ if (res.ok){
yikes(); yikes();
return res.json(); return res.json();
@ -99,9 +92,24 @@
} }
} }
async function loadPath(){
if (!location_id) return;
const url = api(`stock/location/${location_id}`);
const res = await get(url);
if (res.ok){
yikes();
var path = res.json();
} else {
error(res);
return null;
}
}
async function loadProperties(){ async function loadProperties(){
const url = api('stock/properties') const url = api('stock/properties')
const res = await fetch(url,{credentials:'include'}); const res = await get(url);
if (res.ok){ if (res.ok){
var json = await res.json(); var json = await res.json();
var dict = {} var dict = {}
@ -114,7 +122,7 @@
async function loadUserLocations(){ async function loadUserLocations(){
const url = api('stock/locations/of_user') const url = api('stock/locations/of_user')
const res = await fetch(url,{credentials:'include'}); const res = await get(url);
if (res.ok){ if (res.ok){
top_level = await res.json(); top_level = await res.json();
yikes(); yikes();
@ -123,7 +131,7 @@
function load(){ function load(){
loadUserLocations(); loadUserLocations();
unfoldPath(); loadPath();
loadProperties(); loadProperties();
} }
@ -143,11 +151,7 @@
const data = {}; const data = {};
data[field] = newValue; data[field] = newValue;
const url = api(`stock/location/${location.id}`); const url = api(`stock/location/${location.id}`);
const res = await fetch(url,{ const res = await patch(url,data);
credentials: 'include',
method:'PATCH',
body:JSON.stringify(data)
});
if (res.ok){ if (res.ok){
yikes(); yikes();
return true; return true;
@ -169,12 +173,6 @@
window.history.replaceState(window.history.state, '', url); window.history.replaceState(window.history.state, '', url);
} }
// tries to unfold the path to a certain location, if a locationId is supplied via URL
function unfoldPath(){
if (!locationId) return;
// TODO
}
function unlistLocation(loc){ function unlistLocation(loc){
for (var owner of top_level){ for (var owner of top_level){
if (owner.locations && dropNestedLocation(owner.locations,loc)) break; if (owner.locations && dropNestedLocation(owner.locations,loc)) break;
@ -185,9 +183,12 @@
</script> </script>
<h2>{t('Stock')}</h2> <h2>{t('Stock')}</h2>
{#if location_id} <span class="warn">
{location_id} {#if location_id}location id: {location_id}{/if}
{/if} {#if owner}owner type: {owner},{/if}
{#if owner_id}owner id: {owner_id},{/if}
{#if item_id}item id: {item_id}{/if}
</span>
<div class="grid3"> <div class="grid3">
<div class="locations"> <div class="locations">
{#if top_level} {#if top_level}

10
frontend/src/routes/stock/Locations.svelte

@ -1,5 +1,5 @@
<script> <script>
import { api } from '../../urls.svelte'; import { api, get } from '../../urls.svelte';
import { error, yikes } from '../../warn.svelte'; import { error, yikes } from '../../warn.svelte';
import { t } from '../../translations.svelte'; import { t } from '../../translations.svelte';
@ -41,7 +41,7 @@
delete location.locations; delete location.locations;
} else { } else {
const url = api(`stock/locations/below/${location.id}`); const url = api(`stock/locations/below/${location.id}`);
const res = await fetch(url,{credentials:'include'}); const res = await get(url);
if (res.ok){ if (res.ok){
yikes(); yikes();
location.locations = await res.json(); location.locations = await res.json();
@ -67,11 +67,7 @@
parent: parent parent: parent
} }
const url = api('stock/location'); const url = api('stock/location');
const res = await fetch(url,{ const res = await post(url,data);
credentials: 'include',
method: 'POST',
body: JSON.stringify(data)
});
if (res.ok){ if (res.ok){
yikes; yikes;
const saved = await res.json(); const saved = await res.json();

24
stock/src/main/java/de/srsoftware/umbrella/stock/SqliteDb.java

@ -286,6 +286,30 @@ public class SqliteDb extends BaseDb implements StockDb {
} }
} }
@Override
public Map<String, Object> pathToLocation(Location target) {
var root = new HashMap<String,Object>();
var location = loadLocation(target.id());
root.put(NAME,location.name());
root.put(ID,location.id());
try {
while (!is0(location.parent())) {
var rs = select(ALL).from(TABLE_LOCATIONS).where(ID, equal(location.parent())).exec(db);
var parent = DbLocation.of(rs);
rs.close();
var current = new HashMap<String,Object>();
current.put(NAME,parent.name());
current.put(ID,parent.id());
current.put(PATH,root);
root = current;
location = parent;
}
} catch (SQLException e){
throw databaseException("Failed to load path to location {0}",target);
}
return root;
}
private void replaceItemsTable() throws SQLException { private void replaceItemsTable() throws SQLException {
db.prepareStatement(format("DROP TABLE {0}",TABLE_ITEMS)).execute(); db.prepareStatement(format("DROP TABLE {0}",TABLE_ITEMS)).execute();
db.prepareStatement(format("ALTER TABLE {0} RENAME TO {1}","items_temp",TABLE_ITEMS)).execute(); db.prepareStatement(format("ALTER TABLE {0} RENAME TO {1}","items_temp",TABLE_ITEMS)).execute();

29
stock/src/main/java/de/srsoftware/umbrella/stock/StockDb.java

@ -5,20 +5,21 @@ import de.srsoftware.umbrella.core.api.Owner;
import de.srsoftware.umbrella.core.model.*; import de.srsoftware.umbrella.core.model.*;
import de.srsoftware.umbrella.core.model.Location; import de.srsoftware.umbrella.core.model.Location;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
public interface StockDb { public interface StockDb {
Property addNewProperty(long itemId, String name, Object value, String unit); Property addNewProperty(long itemId, String name, Object value, String unit);
Location delete(DbLocation location); Location delete(DbLocation location);
Collection<DbLocation> listChildLocations(long parentId); Collection<DbLocation> listChildLocations(long parentId);
Collection<DbLocation> listCompanyLocations(Company company); Collection<DbLocation> listCompanyLocations(Company company);
Collection<Item> listItemsAt(Location location); Collection<Item> listItemsAt(Location location);
Collection<Property> listProperties(); Collection<Property> listProperties();
Collection<DbLocation> listUserLocations(UmbrellaUser userId); Collection<DbLocation> listUserLocations(UmbrellaUser userId);
Item loadItem(long id); Item loadItem(long id);
DbLocation loadLocation(long locationId); DbLocation loadLocation(long locationId);
DbLocation save(DbLocation location); long nextItemNumberFor(Owner owner);
Item save(Item item); Map<String,Object> pathToLocation(Location location);
Property setProperty(long itemId, long existingPropId, Object value); DbLocation save(DbLocation location);
Item save(Item item);
long nextItemNumberFor(Owner owner); Property setProperty(long itemId, long existingPropId, Object value);
} }

4
stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java

@ -165,8 +165,8 @@ public class StockModule extends BaseHandler implements StockService {
case USER -> List.of(owner.id()); case USER -> List.of(owner.id());
case null, default -> throw unprocessable("Unprocessable owner type: {0}",owner.type()); case null, default -> throw unprocessable("Unprocessable owner type: {0}",owner.type());
}; };
var pathToLocation = stockDb.pathToLocation(location);
return sendContent(ex,Map.of(ITEMS,items,USERS,userIds)); return sendContent(ex,Map.of(ITEMS,items,USERS,userIds,PATH,pathToLocation));
} }
private boolean getLocations(Path path, UmbrellaUser user, HttpExchange ex) throws IOException { private boolean getLocations(Path path, UmbrellaUser user, HttpExchange ex) throws IOException {

Loading…
Cancel
Save