working on referenceable locations
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -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";
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
@@ -15,8 +15,9 @@
|
|||||||
let loc_data = $derived.by(loadLocation);
|
let loc_data = $derived.by(loadLocation);
|
||||||
let item = $state(null);
|
let item = $state(null);
|
||||||
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 { item_id, location_id, owner, owner_id } = $props();
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
// This effect runs whenever `location` changes
|
// This effect runs whenever `location` changes
|
||||||
@@ -35,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);
|
||||||
@@ -69,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;
|
||||||
@@ -87,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();
|
||||||
@@ -98,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 = {}
|
||||||
@@ -113,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();
|
||||||
@@ -122,6 +131,7 @@
|
|||||||
|
|
||||||
function load(){
|
function load(){
|
||||||
loadUserLocations();
|
loadUserLocations();
|
||||||
|
loadPath();
|
||||||
loadProperties();
|
loadProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,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;
|
||||||
@@ -179,6 +185,12 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h2>{t('Stock')}</h2>
|
<h2>{t('Stock')}</h2>
|
||||||
|
<span class="warn">
|
||||||
|
{#if location_id}location id: {location_id}{/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}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user