Compare commits

..

15 Commits

Author SHA1 Message Date
30add879ad improving scroll behaviour on mobile devices
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2025-12-10 08:32:25 +01:00
1eb49a5d4e increased code font size
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2025-12-09 13:29:54 +01:00
0dc21100f8 CSS improvements
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2025-12-09 10:57:18 +01:00
a898e5eaa2 fixed broken "add task" buttons in Kanban 2025-12-09 10:21:39 +01:00
85faf31bc6 Merge branch 'main' into dev 2025-12-09 10:11:36 +01:00
a96bcff2df Merge branch 'bugfix/timetrack-buttons' 2025-12-08 15:34:22 +01:00
0a289eb59d Merge branch 'css/stock' 2025-12-08 13:26:40 +01:00
a2f47ac3eb Merge branch 'bugfix/timetrack-buttons' into dev 2025-12-08 13:25:46 +01:00
1de84979ee improving CSS
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2025-12-08 13:25:37 +01:00
4e88b2c4de Merge branch 'main' into dev 2025-12-08 13:16:51 +01:00
0d02f3cbda started backend translations
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2025-12-05 14:38:46 +01:00
ebf9a83b60 improved css for stock view
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2025-12-05 12:45:45 +01:00
9035ca48a7 Merge branch 'bugfix/scroll_dont_click' 2025-12-05 12:24:01 +01:00
1d55325501 Merge branch 'feature/tile_menu' into dev 2025-12-04 22:30:26 +01:00
fda7f34b99 tried to fix bug: easylist would register clicks when scolling on mobile devices
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2025-12-04 21:50:59 +01:00
13 changed files with 116 additions and 22 deletions

View File

@@ -2,9 +2,11 @@
package de.srsoftware.umbrella.core;
import static de.srsoftware.tools.Optionals.nullable;
import static de.srsoftware.umbrella.core.ModuleRegistry.translator;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.WARNING;
import static java.net.HttpURLConnection.*;
import static java.text.MessageFormat.format;
import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.tools.Path;
@@ -72,7 +74,9 @@ public abstract class BaseHandler extends PathHandler {
}
public boolean send(HttpExchange ex, UmbrellaException e) throws IOException {
return sendContent(ex,e.statusCode(),e.getMessage());
String lang = languages(ex).stream().findFirst().orElse(null);
var translatedMessage = translator().translate(lang,e.getMessage());
return sendContent(ex,e.statusCode(),format(translatedMessage,e.fills()));
}
public boolean unauthorized(HttpExchange ex) throws IOException {

View File

@@ -13,13 +13,15 @@ import static java.text.MessageFormat.format;
public class UmbrellaException extends RuntimeException{
private final int statusCode;
private Object[] fills;
public UmbrellaException(String message, Object ... fills){
this(HTTP_SERVER_ERROR,message,fills);
}
public UmbrellaException(int statusCode, String message, Object ... fills){
super(fills == null || fills.length<1 ? message : format(message,fills));
super(message);
this.fills = fills;
this.statusCode = statusCode;
}
@@ -34,6 +36,10 @@ public class UmbrellaException extends RuntimeException{
return new UmbrellaException(message,fills);
}
public Object[] fills(){
return fills;
}
public static UmbrellaException forbidden(String message, Object... fills) {
return new UmbrellaException(HTTP_FORBIDDEN,message,fills);
}

View File

@@ -22,8 +22,12 @@
async function applyEdit(){
let success = await onSet(editValue);
if (success) {
value = editValue;
editing=false;
if (success == 'reset'){
editValue = value;
} else {
value = editValue;
}
editing = false;
} else {
editValue = value;
}
@@ -36,7 +40,7 @@
}
function measured(evt,duration,d){
if (d > 100) return;
if (d > 10) return;
if (duration < 500){
onclick(evt);
} else {

View File

@@ -50,7 +50,7 @@ onMount(fetchModules);
}
</style>
<nav class={expand?"":"collapsed"}>
<nav class={expand?"expanded":"collapsed"}>
<form onsubmit={search}>
<input type="text" bind:value={key} />
<button type="submit">{t('search')}</button>

View File

@@ -78,8 +78,10 @@
if (!tasks[user_id][state]) tasks[user_id][state] = {};
tasks[user_id][state][task.id] = task;
yikes();
return 'reset';
} else {
error(resp);
return false;
}
}
@@ -255,7 +257,7 @@
{/if}
{/each}
<div class="add_task">
<LineEditor value={t('add_object',{object:t('task')})} editable={true} onSet={(name) => create(name,uid,state)}/>
<LineEditor value={t('add_object',{object:t('task')})} editable={true} onSet={(name) => create(name,u.id,state)}/>
</div>
</div>
{/each}

View File

@@ -73,7 +73,7 @@
}
function measured(evt,duration,d){
if (d > 100) return;
if (d > 10) return;
if (duration < 500){
onclick(evt);
} else {

View File

@@ -137,7 +137,7 @@ CREATE TABLE IF NOT EXISTS {0} (
if (rs.next()) project = Project.of(rs);
rs.close();
if (project == null) throw UmbrellaException.notFound("No project found for id {0}",projectId);
if (project == null) throw UmbrellaException.notFound("no_project_for_id",projectId);
rs = select(ALL).from(TABLE_CUSTOM_STATES).where(PROJECT_ID,equal(projectId)).exec(db);
var states = project.allowedStates();

View File

@@ -270,7 +270,7 @@ CREATE TABLE IF NOT EXISTS {0} (
public Task load(long taskId) throws UmbrellaException {
var map = load(List.of(taskId));
var task = map.get(taskId);
if (task == null) throw UmbrellaException.notFound("No task found for id {0}",taskId);
if (task == null) throw UmbrellaException.notFound("no_task_for_id",taskId);
return task;
}

View File

@@ -183,6 +183,8 @@
"new_password": "neues Passwort",
"new_property": "neue Eigenschaft",
"no_company": "keine Firma",
"no_project_for_id": "Kein Projekt mit ID {0} gefunden!",
"no_task_for_id": "Keine Aufgabe mit ID {0} gefunden!",
"note": "Notiz",
"notes": "Notizen",
"not_recent_version": "Die ist nicht die neuste Version dieser Seite!",

View File

@@ -183,6 +183,8 @@
"new_password": "new password",
"new_property": "new property",
"no_company": "no company",
"no_project_for_id": "No project found for id {0}",
"no_task_for_id": "No task found for id {0}",
"note": "note",
"notes": "notes",
"not_recent_version": "This is not the current version of this page!",
@@ -322,4 +324,4 @@
"year": "year",
"your_password_reset_token" : "Your token to create a new password",
"your_profile": "your profile"
}
}

View File

@@ -16,6 +16,10 @@ body {
background-attachment: fixed;
}
code {
font-size: 16px;
}
fieldset {
border: 1px solid;
border-radius: 4px;
@@ -427,14 +431,14 @@ a.wikilink{
}
@media screen and (min-width: 900px) {
#app nav button.symbol{
#app nav > button.symbol{
display: none;
}
}
@media screen and (max-width: 900px) {
body{
padding-top: 13px;
padding-top: 30px;
}
#app nav{
grid-template-columns: 33% 34% 33%;
@@ -443,7 +447,6 @@ a.wikilink{
position: absolute;
left: 0;
right: 0;
}
#app nav form{
grid-column-end: span 2;
@@ -462,9 +465,20 @@ a.wikilink{
text-align: center;
border: 1px solid;
margin: 5px;
padding: 15px 0;
border-radius: 7px;
}
#app nav a::before {
font-size: 30px;
}
#app nav .timetracking{
grid-column-end: span 3;
font-size: 19px;
text-align: center;
}
#app nav.expanded .timetracking{
display: none;
}
}
@@ -506,6 +520,9 @@ a.wikilink{
#app nav .logout{
grid-column-end: 3;
}
#app nav.expanded .timetracking{
grid-column-end: span 2;
}
}
fieldset.vcard{

View File

@@ -16,6 +16,10 @@ body {
background-attachment: fixed;
}
code {
font-size: 16px;
}
fieldset {
border: 1px solid;
border-radius: 4px;
@@ -505,7 +509,7 @@ a.wikilink{
}
@media screen and (min-width: 900px) {
#app nav button.symbol{
#app nav > button.symbol{
display: none;
}
}
@@ -545,11 +549,42 @@ a.wikilink{
#app nav a::before {
font-size: 30px;
}
#app nav .timetracking{
grid-column-end: span 3;
font-size: 19px;
text-align: center;
}
#app nav.expanded .timetracking{
display: none;
}
.grid3 {
grid-template-columns: auto auto;
}
.grid3 .properties{
grid-column-end: span 2;
order: 1;
}
.grid3 .tags{
order: 2;
}
.grid3 .notes{
grid-column-end: span 2;
order: 3;
}
.grid3 .locations{
order: 5;
}
.grid3 .items{
order: 6;
}
}
@media screen and (max-width: 600px) {
.grid2{
.grid2,
.grid3{
display: grid;
grid-template-columns: auto;
}
@@ -580,12 +615,18 @@ a.wikilink{
#app nav{
grid-template-columns: auto auto;
}
#app nav form{
#app nav form,
.grid3 .notes,
.grid3 .tags,
.grid3 .properties{
grid-column-end: span 1;
}
#app nav .logout{
grid-column-end: 3;
}
#app nav.expanded .timetracking{
grid-column-end: span 2;
}
}
fieldset.vcard{

View File

@@ -16,6 +16,9 @@ body {
background-attachment: fixed;
}
code {
font-size: 16px;
}
fieldset {
border: 1px solid;
border-radius: 4px;
@@ -427,14 +430,14 @@ a.wikilink{
}
@media screen and (min-width: 900px) {
#app nav button.symbol{
#app nav > button.symbol{
display: none;
}
}
@media screen and (max-width: 900px) {
body{
padding-top: 13px;
padding-top: 30px;
}
#app nav{
grid-template-columns: 33% 34% 33%;
@@ -443,7 +446,6 @@ a.wikilink{
position: absolute;
left: 0;
right: 0;
}
#app nav form{
grid-column-end: span 2;
@@ -462,9 +464,20 @@ a.wikilink{
text-align: center;
border: 1px solid;
margin: 5px;
padding: 15px 0;
border-radius: 7px;
}
#app nav a::before {
font-size: 30px;
}
#app nav .timetracking{
grid-column-end: span 3;
font-size: 19px;
text-align: center;
}
#app nav.expanded .timetracking{
display: none;
}
}
@@ -506,6 +519,9 @@ a.wikilink{
#app nav .logout{
grid-column-end: 3;
}
#app nav.expanded .timetracking{
grid-column-end: span 2;
}
}
fieldset.vcard{