working on usability
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -13,10 +13,12 @@ import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
|||||||
import de.srsoftware.umbrella.core.model.*;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Path.SOURCES;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Path.DESTINATIONS;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -72,6 +74,8 @@ public class AccountingModule extends BaseHandler implements AccountingService {
|
|||||||
var head = path.pop();
|
var head = path.pop();
|
||||||
return switch (head) {
|
return switch (head) {
|
||||||
case null -> postEntry(user.get(),ex);
|
case null -> postEntry(user.get(),ex);
|
||||||
|
case SOURCES -> postSearchSources(user.get(),ex);
|
||||||
|
case DESTINATIONS -> postSearchDestinations(user.get(),ex);
|
||||||
default -> super.doPost(path,ex);
|
default -> super.doPost(path,ex);
|
||||||
};
|
};
|
||||||
} catch (UmbrellaException e){
|
} catch (UmbrellaException e){
|
||||||
@@ -170,4 +174,18 @@ public class AccountingModule extends BaseHandler implements AccountingService {
|
|||||||
|
|
||||||
return sendContent(ex,newAccount != null ? newAccount : transaction);
|
return sendContent(ex,newAccount != null ? newAccount : transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean postSearchDestinations(UmbrellaUser user, HttpExchange ex) throws IOException {
|
||||||
|
var key = body(ex);
|
||||||
|
var users = userService().search(key);
|
||||||
|
// TODO: search known transactions for possible destinations
|
||||||
|
return sendContent(ex,mapValues(users));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean postSearchSources(UmbrellaUser user, HttpExchange ex) throws IOException {
|
||||||
|
var key = body(ex);
|
||||||
|
var users = userService().search(key);
|
||||||
|
// TODO: search known transactions for possible sources
|
||||||
|
return sendContent(ex,mapValues(users));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,4 +22,5 @@ public interface UserService {
|
|||||||
Optional<UmbrellaUser> loadUser(Optional<Token> sessionToken) throws UmbrellaException;
|
Optional<UmbrellaUser> loadUser(Optional<Token> sessionToken) throws UmbrellaException;
|
||||||
Optional<UmbrellaUser> loadUser(HttpExchange ex) throws UmbrellaException;
|
Optional<UmbrellaUser> loadUser(HttpExchange ex) throws UmbrellaException;
|
||||||
Optional<UmbrellaUser> refreshSession(HttpExchange ex);
|
Optional<UmbrellaUser> refreshSession(HttpExchange ex);
|
||||||
|
Map<Long, ? extends UmbrellaUser> search(String key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ public class Path {
|
|||||||
public static final String COMPANY = "company";
|
public static final String COMPANY = "company";
|
||||||
public static final String CONNECTED = "connected";
|
public static final String CONNECTED = "connected";
|
||||||
|
|
||||||
|
public static final String DESTINATIONS = "destinations";
|
||||||
|
|
||||||
public static final String EVALUATE = "evaluate";
|
public static final String EVALUATE = "evaluate";
|
||||||
|
|
||||||
public static final String ITEM = "item";
|
public static final String ITEM = "item";
|
||||||
@@ -44,6 +46,7 @@ public class Path {
|
|||||||
public static final String SEARCH = "search";
|
public static final String SEARCH = "search";
|
||||||
public static final String SELECT = "select";
|
public static final String SELECT = "select";
|
||||||
public static final String SETTINGS = "settings";
|
public static final String SETTINGS = "settings";
|
||||||
|
public static final String SOURCES = "sources";
|
||||||
public static final String STATES = "states";
|
public static final String STATES = "states";
|
||||||
public static final String STARTED = "started";
|
public static final String STARTED = "started";
|
||||||
public static final String STATE = "state";
|
public static final String STATE = "state";
|
||||||
|
|||||||
@@ -27,8 +27,7 @@
|
|||||||
});
|
});
|
||||||
let router = useTinyRouter();
|
let router = useTinyRouter();
|
||||||
|
|
||||||
async function getUsers(text){
|
async function getTerminal(text,url){
|
||||||
var url = api('user/search');
|
|
||||||
var res = await post(url,text);
|
var res = await post(url,text);
|
||||||
if (res.ok){
|
if (res.ok){
|
||||||
yikes();
|
yikes();
|
||||||
@@ -40,6 +39,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getDestinations(text){
|
||||||
|
var url = api('accounting/destinations');
|
||||||
|
return await getTerminal(text,url);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getSources(text){
|
||||||
|
var url = api('accounting/sources');
|
||||||
|
return await getTerminal(text,url);
|
||||||
|
}
|
||||||
|
|
||||||
async function save(){
|
async function save(){
|
||||||
let data = {
|
let data = {
|
||||||
...entry,
|
...entry,
|
||||||
@@ -68,24 +77,32 @@
|
|||||||
<fieldset class="grid2">
|
<fieldset class="grid2">
|
||||||
{#if new_account}
|
{#if new_account}
|
||||||
<legend>{t('create_new_object',{object:t('account')})}</legend>
|
<legend>{t('create_new_object',{object:t('account')})}</legend>
|
||||||
|
<span style="display:none"></span>
|
||||||
<span>{t('account name')}</span>
|
<span>{t('account name')}</span>
|
||||||
<input type="text" bind:value={entry.account.name} />
|
<span>
|
||||||
|
<input type="text" bind:value={entry.account.name} />
|
||||||
|
</span>
|
||||||
<span>{t('currency')}</span>
|
<span>{t('currency')}</span>
|
||||||
<input type="text" bind:value={entry.account.currency} />
|
<span>
|
||||||
|
<input type="text" bind:value={entry.account.currency} />
|
||||||
|
</span>
|
||||||
<hr/>
|
<hr/>
|
||||||
|
<span style="grid-column-end: span 2">{t('first transaction')}</span>
|
||||||
{:else}
|
{:else}
|
||||||
<legend>{t('add_object',{object:t('entry')})}</legend>
|
<legend>{t('add_object',{object:t('transaction')})}</legend>
|
||||||
|
<span style="display:none"></span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<span>{t('date')}</span>
|
<span>{t('date')}</span>
|
||||||
<input type="date" value={entry.date} />
|
<span>
|
||||||
|
<input type="date" value={entry.date} />
|
||||||
|
</span>
|
||||||
|
|
||||||
<span>{t('source')}</span>
|
<span>{t('source')}</span>
|
||||||
<Autocomplete bind:candidate={entry.source} getCandidates={getUsers} />
|
<Autocomplete bind:candidate={entry.source} getCandidates={getSources} />
|
||||||
|
|
||||||
<span>{t('destination')}</span>
|
<span>{t('destination')}</span>
|
||||||
<Autocomplete bind:candidate={entry.destination} getCandidates={getUsers} />
|
<Autocomplete bind:candidate={entry.destination} getCandidates={getDestinations} />
|
||||||
|
|
||||||
<span>{t('amount')}</span>
|
<span>{t('amount')}</span>
|
||||||
<span>
|
<span>
|
||||||
@@ -100,14 +117,3 @@
|
|||||||
<button onclick={save}>{t('save')}</button>
|
<button onclick={save}>{t('save')}</button>
|
||||||
</span>
|
</span>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
{JSON.stringify(entry,null,2)}
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
{JSON.stringify(user,null,2)}
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{t('accounts')}</legend>
|
|
||||||
|
|
||||||
<span></span>
|
<span></span>
|
||||||
<span>
|
<span>
|
||||||
@@ -47,4 +46,6 @@
|
|||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
<legend>{t('accounts')}</legend>
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@@ -555,7 +555,7 @@ public class UserModule extends BaseHandler implements UserService {
|
|||||||
var requestingUser = loadUser(ex);
|
var requestingUser = loadUser(ex);
|
||||||
if (!(requestingUser.isPresent() && requestingUser.get() instanceof DbUser dbUser)) return unauthorized(ex);
|
if (!(requestingUser.isPresent() && requestingUser.get() instanceof DbUser dbUser)) return unauthorized(ex);
|
||||||
var key = body(ex);
|
var key = body(ex);
|
||||||
return sendContent(ex,mapValues(users.search(key)));
|
return sendContent(ex,mapValues(search(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -576,6 +576,11 @@ public class UserModule extends BaseHandler implements UserService {
|
|||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, ? extends UmbrellaUser> search(String key) {
|
||||||
|
return users.search(key);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean update(HttpExchange ex, DbUser user, JSONObject json) throws UmbrellaException, IOException {
|
private boolean update(HttpExchange ex, DbUser user, JSONObject json) throws UmbrellaException, IOException {
|
||||||
var id = user.id();
|
var id = user.id();
|
||||||
var name = json.has(NAME) && json.get(NAME) instanceof String s && !s.isBlank() ? s : user.name();
|
var name = json.has(NAME) && json.get(NAME) instanceof String s && !s.isBlank() ? s : user.name();
|
||||||
|
|||||||
Reference in New Issue
Block a user