working on journal

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2026-07-28 08:46:31 +02:00
parent e614880d71
commit 722a6ae97e
7 changed files with 120 additions and 40 deletions
@@ -5,7 +5,6 @@ import static de.srsoftware.umbrella.core.constants.Field.*;
import static java.util.Optional.*;
import de.srsoftware.tools.Diff;
import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.model.ObjectWithId;
import de.srsoftware.umbrella.core.model.Translatable;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
@@ -5,32 +5,91 @@ import static de.srsoftware.umbrella.core.Util.mapMarkdown;
import static de.srsoftware.umbrella.core.constants.Field.*;
import static java.time.ZoneOffset.UTC;
import de.srsoftware.tools.Mappable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
public record Bookmark(long urlId, String url, String comment, LocalDateTime timestamp, Collection<String> tags) implements Mappable {
public final class Bookmark extends ObjectWithId {
private final String url;
private final String comment;
private final LocalDateTime timestamp;
private final Collection<String> tags;
public static Bookmark of(ResultSet rs) throws SQLException {
return new Bookmark(rs.getLong(ID),rs.getString(URL),rs.getString(COMMENT),LocalDateTime.ofEpochSecond(rs.getLong(TIMESTAMP),0, UTC),new ArrayList<>());
public Bookmark(long urlId, String url, String comment, LocalDateTime timestamp, Collection<String> tags) {
super(urlId);
this.url = url;
this.comment = comment;
this.timestamp = timestamp;
this.tags = tags;
}
public static Bookmark of(long urlId, String url, String comment, LocalDateTime timestamp){
return new Bookmark(urlId,url,comment,timestamp,new ArrayList<>());
public static Bookmark of(ResultSet rs) throws SQLException {
return new Bookmark(rs.getLong(ID), rs.getString(URL), rs.getString(COMMENT), LocalDateTime.ofEpochSecond(rs.getLong(TIMESTAMP), 0, UTC), new ArrayList<>());
}
public static Bookmark of(long urlId, String url, String comment, LocalDateTime timestamp) {
return new Bookmark(urlId, url, comment, timestamp, new ArrayList<>());
}
@Override
public Map<String, Object> toMap() {
return Map.of(
ID, urlId,
return map(
URL, url,
COMMENT, mapMarkdown(comment),
TAGS, tags,
TIMESTAMP, timestamp.withNano(0)
);
}
public long urlId() {
return id();
}
public String url() {
return url;
}
public String comment() {
return comment;
}
public LocalDateTime timestamp() {
return timestamp;
}
public Collection<String> tags() {
return tags;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Bookmark) obj;
return this.urlId() == that.urlId() &&
Objects.equals(this.url, that.url) &&
Objects.equals(this.comment, that.comment) &&
Objects.equals(this.timestamp, that.timestamp) &&
Objects.equals(this.tags, that.tags);
}
@Override
public int hashCode() {
return Objects.hash(urlId(), url, comment, timestamp, tags);
}
@Override
public String toString() {
return "Bookmark[" +
"urlId=" + urlId() + ", " +
"url=" + url + ", " +
"comment=" + comment + ", " +
"timestamp=" + timestamp + ", " +
"tags=" + tags + ']';
}
}
@@ -4,13 +4,11 @@ import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.constants.Field;
import java.security.InvalidParameterException;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class ObjectWithId implements Mappable {
private final long id;
private long id;
public ObjectWithId(long id){
this.id = id;
@@ -20,6 +18,11 @@ public abstract class ObjectWithId implements Mappable {
return id;
}
public ObjectWithId setId(long newValue){
id = newValue;
return this;
}
protected Map<String, Object> map(Object ... keysAndValues) {
if (keysAndValues.length % 2 != 0) throw new InvalidParameterException("Expected even number of keys and parameters!");
var map = new HashMap<String, Object>();
@@ -7,7 +7,6 @@ import static de.srsoftware.umbrella.core.constants.Field.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
import static java.lang.System.Logger.Level.WARNING;
import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.constants.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -15,9 +14,9 @@ import java.time.LocalDate;
import java.util.*;
import org.json.JSONObject;
public class Task implements Mappable {
public class Task extends ObjectWithId {
public static final System.Logger LOG = System.getLogger(Task.class.getSimpleName());
private final long id, projectId;
private final long projectId;
private Long parentTaskId;
private String description, name;
private final Set<Long> requiredTasksIds;
@@ -30,7 +29,7 @@ public class Task implements Mappable {
private final Set<String> tags = new HashSet<>();
public Task (long id, long projectId, Long parentTaskId, String name, String description, int status, Double estimatedTime, LocalDate start, LocalDate dueDate, boolean showClosed, boolean noIndex, Map<Long,Member> members, int priority){
this.id = id;
super(id);
this.projectId = projectId;
this.parentTaskId = parentTaskId;
this.name = name;
@@ -82,10 +81,6 @@ public class Task implements Mappable {
return members.containsKey(user.id());
}
public long id(){
return id;
}
public boolean isDirty() {
return !dirtyFields.isEmpty();
}
@@ -229,28 +224,27 @@ public class Task implements Mappable {
}
public Map<String,Object> toMap(boolean renderMarkdown){
var map = new HashMap<String,Object>();
var memberMap = new HashMap<Long,Map<String,Object>>();
if (members != null) for (var entry : members.entrySet()){
memberMap.put(entry.getKey(),entry.getValue().toMap());
}
map.put(ID, id);
map.put(PROJECT_ID, projectId);
map.put(PARENT_TASK_ID, parentTaskId);
map.put(PRIORITY,priority);
map.put(NAME, name);
map.put(DESCRIPTION, renderMarkdown ? mapMarkdown(description) : Map.of(SOURCE,description));
map.put(STATUS, status);
map.put(EST_TIME, estimatedTime);
map.put(START_DATE,start);
map.put(DUE_DATE,dueDate);
map.put(NO_INDEX,noIndex);
map.put(MEMBERS,memberMap);
map.put(REQUIRED_TASKS_IDS,requiredTasksIds);
map.put(SHOW_CLOSED,showClosed);
map.put(TOTAL_PRIO,totalPrio());
map.put(TAGS,tags);
return map;
return map(
PROJECT_ID, projectId,
PARENT_TASK_ID, parentTaskId,
PRIORITY,priority,
NAME, name,
DESCRIPTION, renderMarkdown ? mapMarkdown(description) : Map.of(SOURCE,description),
STATUS, status,
EST_TIME, estimatedTime,
START_DATE,start,
DUE_DATE,dueDate,
NO_INDEX,noIndex,
MEMBERS,memberMap,
REQUIRED_TASKS_IDS,requiredTasksIds,
SHOW_CLOSED,showClosed,
TOTAL_PRIO,totalPrio(),
TAGS,tags
);
}
@Override
@@ -0,0 +1,17 @@
<script>
import { api, get } from '../../urls.svelte';
import { error, yikes } from '../../warn.svelte';
import { t } from '../../translations.svelte';
let { module, entityId } = $props();
async function loadJournal(){
const url = api(`journal/${module}/${entityId}`);
const res = await get(url);
if (res.ok) {
} else error(res);
}
$effect(loadJournal);
</script>
...
+6 -1
View File
@@ -8,6 +8,7 @@
import { timetrack } from '../../user.svelte.js';
import { now } from '../../time.svelte';
import Journal from '../journal/related.svelte';
import LineEditor from '../../Components/LineEditor.svelte';
import MarkdownEditor from '../../Components/MarkdownEditor.svelte';
import ParentSelector from './ParentSelector.svelte';
@@ -363,9 +364,13 @@
{/if}
</div>
<h3>{t('Journal')}</h3>
<div>
<Journal module="task" entityId={id} />
</div>
<h3>{t('notes')}</h3>
<div>
<Notes module="task" entity_id={id} />
<Notes module="task" entity_id={id} />
</div>
</div>
{/if}
@@ -476,7 +476,10 @@ public class SqliteDb extends BaseDb implements StockDb {
var rs = insertInto(TABLE_ITEMS, OWNER, OWNER_NUMBER, Field.CODE, NAME, DESCRIPTION, LOCATION_ID)
.values(item.owner().dbCode(), number, item.code(), item.name(), item.description(), item.location().id())
.execute(db).getGeneratedKeys();
if (rs.next()) item.id(rs.getLong(1)).ownerNumber(number);
if (rs.next()) {
item.setId(rs.getLong(1));
item.ownerNumber(number);
}
rs.close();
} catch (SQLException e) {
throw failedToStoreObject(item.name()).causedBy(e);