working on journal
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -5,7 +5,6 @@ import static de.srsoftware.umbrella.core.constants.Field.*;
|
|||||||
import static java.util.Optional.*;
|
import static java.util.Optional.*;
|
||||||
|
|
||||||
import de.srsoftware.tools.Diff;
|
import de.srsoftware.tools.Diff;
|
||||||
import de.srsoftware.tools.Mappable;
|
|
||||||
import de.srsoftware.umbrella.core.model.ObjectWithId;
|
import de.srsoftware.umbrella.core.model.ObjectWithId;
|
||||||
import de.srsoftware.umbrella.core.model.Translatable;
|
import de.srsoftware.umbrella.core.model.Translatable;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
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 de.srsoftware.umbrella.core.constants.Field.*;
|
||||||
import static java.time.ZoneOffset.UTC;
|
import static java.time.ZoneOffset.UTC;
|
||||||
|
|
||||||
import de.srsoftware.tools.Mappable;
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
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 {
|
public Bookmark(long urlId, String url, String comment, LocalDateTime timestamp, Collection<String> tags) {
|
||||||
return new Bookmark(rs.getLong(ID),rs.getString(URL),rs.getString(COMMENT),LocalDateTime.ofEpochSecond(rs.getLong(TIMESTAMP),0, UTC),new ArrayList<>());
|
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){
|
public static Bookmark of(ResultSet rs) throws SQLException {
|
||||||
return new Bookmark(urlId,url,comment,timestamp,new ArrayList<>());
|
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
|
@Override
|
||||||
public Map<String, Object> toMap() {
|
public Map<String, Object> toMap() {
|
||||||
return Map.of(
|
return map(
|
||||||
ID, urlId,
|
|
||||||
URL, url,
|
URL, url,
|
||||||
COMMENT, mapMarkdown(comment),
|
COMMENT, mapMarkdown(comment),
|
||||||
TAGS, tags,
|
TAGS, tags,
|
||||||
TIMESTAMP, timestamp.withNano(0)
|
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 de.srsoftware.umbrella.core.constants.Field;
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
import java.security.InvalidParameterException;
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class ObjectWithId implements Mappable {
|
public abstract class ObjectWithId implements Mappable {
|
||||||
private final long id;
|
private long id;
|
||||||
|
|
||||||
public ObjectWithId(long id){
|
public ObjectWithId(long id){
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@@ -20,6 +18,11 @@ public abstract class ObjectWithId implements Mappable {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ObjectWithId setId(long newValue){
|
||||||
|
id = newValue;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
protected Map<String, Object> map(Object ... keysAndValues) {
|
protected Map<String, Object> map(Object ... keysAndValues) {
|
||||||
if (keysAndValues.length % 2 != 0) throw new InvalidParameterException("Expected even number of keys and parameters!");
|
if (keysAndValues.length % 2 != 0) throw new InvalidParameterException("Expected even number of keys and parameters!");
|
||||||
var map = new HashMap<String, Object>();
|
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 de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
import static java.lang.System.Logger.Level.WARNING;
|
import static java.lang.System.Logger.Level.WARNING;
|
||||||
|
|
||||||
import de.srsoftware.tools.Mappable;
|
|
||||||
import de.srsoftware.umbrella.core.constants.Field;
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -15,9 +14,9 @@ import java.time.LocalDate;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.json.JSONObject;
|
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());
|
public static final System.Logger LOG = System.getLogger(Task.class.getSimpleName());
|
||||||
private final long id, projectId;
|
private final long projectId;
|
||||||
private Long parentTaskId;
|
private Long parentTaskId;
|
||||||
private String description, name;
|
private String description, name;
|
||||||
private final Set<Long> requiredTasksIds;
|
private final Set<Long> requiredTasksIds;
|
||||||
@@ -30,7 +29,7 @@ public class Task implements Mappable {
|
|||||||
private final Set<String> tags = new HashSet<>();
|
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){
|
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.projectId = projectId;
|
||||||
this.parentTaskId = parentTaskId;
|
this.parentTaskId = parentTaskId;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -82,10 +81,6 @@ public class Task implements Mappable {
|
|||||||
return members.containsKey(user.id());
|
return members.containsKey(user.id());
|
||||||
}
|
}
|
||||||
|
|
||||||
public long id(){
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
return !dirtyFields.isEmpty();
|
return !dirtyFields.isEmpty();
|
||||||
}
|
}
|
||||||
@@ -229,28 +224,27 @@ public class Task implements Mappable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<String,Object> toMap(boolean renderMarkdown){
|
public Map<String,Object> toMap(boolean renderMarkdown){
|
||||||
var map = new HashMap<String,Object>();
|
|
||||||
var memberMap = new HashMap<Long,Map<String,Object>>();
|
var memberMap = new HashMap<Long,Map<String,Object>>();
|
||||||
if (members != null) for (var entry : members.entrySet()){
|
if (members != null) for (var entry : members.entrySet()){
|
||||||
memberMap.put(entry.getKey(),entry.getValue().toMap());
|
memberMap.put(entry.getKey(),entry.getValue().toMap());
|
||||||
}
|
}
|
||||||
map.put(ID, id);
|
return map(
|
||||||
map.put(PROJECT_ID, projectId);
|
PROJECT_ID, projectId,
|
||||||
map.put(PARENT_TASK_ID, parentTaskId);
|
PARENT_TASK_ID, parentTaskId,
|
||||||
map.put(PRIORITY,priority);
|
PRIORITY,priority,
|
||||||
map.put(NAME, name);
|
NAME, name,
|
||||||
map.put(DESCRIPTION, renderMarkdown ? mapMarkdown(description) : Map.of(SOURCE,description));
|
DESCRIPTION, renderMarkdown ? mapMarkdown(description) : Map.of(SOURCE,description),
|
||||||
map.put(STATUS, status);
|
STATUS, status,
|
||||||
map.put(EST_TIME, estimatedTime);
|
EST_TIME, estimatedTime,
|
||||||
map.put(START_DATE,start);
|
START_DATE,start,
|
||||||
map.put(DUE_DATE,dueDate);
|
DUE_DATE,dueDate,
|
||||||
map.put(NO_INDEX,noIndex);
|
NO_INDEX,noIndex,
|
||||||
map.put(MEMBERS,memberMap);
|
MEMBERS,memberMap,
|
||||||
map.put(REQUIRED_TASKS_IDS,requiredTasksIds);
|
REQUIRED_TASKS_IDS,requiredTasksIds,
|
||||||
map.put(SHOW_CLOSED,showClosed);
|
SHOW_CLOSED,showClosed,
|
||||||
map.put(TOTAL_PRIO,totalPrio());
|
TOTAL_PRIO,totalPrio(),
|
||||||
map.put(TAGS,tags);
|
TAGS,tags
|
||||||
return map;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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>
|
||||||
|
|
||||||
|
...
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
import { timetrack } from '../../user.svelte.js';
|
import { timetrack } from '../../user.svelte.js';
|
||||||
import { now } from '../../time.svelte';
|
import { now } from '../../time.svelte';
|
||||||
|
|
||||||
|
import Journal from '../journal/related.svelte';
|
||||||
import LineEditor from '../../Components/LineEditor.svelte';
|
import LineEditor from '../../Components/LineEditor.svelte';
|
||||||
import MarkdownEditor from '../../Components/MarkdownEditor.svelte';
|
import MarkdownEditor from '../../Components/MarkdownEditor.svelte';
|
||||||
import ParentSelector from './ParentSelector.svelte';
|
import ParentSelector from './ParentSelector.svelte';
|
||||||
@@ -363,9 +364,13 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h3>{t('Journal')}</h3>
|
||||||
|
<div>
|
||||||
|
<Journal module="task" entityId={id} />
|
||||||
|
</div>
|
||||||
<h3>{t('notes')}</h3>
|
<h3>{t('notes')}</h3>
|
||||||
<div>
|
<div>
|
||||||
<Notes module="task" entity_id={id} />
|
<Notes module="task" entity_id={id} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/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)
|
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())
|
.values(item.owner().dbCode(), number, item.code(), item.name(), item.description(), item.location().id())
|
||||||
.execute(db).getGeneratedKeys();
|
.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();
|
rs.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw failedToStoreObject(item.name()).causedBy(e);
|
throw failedToStoreObject(item.name()).causedBy(e);
|
||||||
|
|||||||
Reference in New Issue
Block a user