Merge branch 'feature/tag_proposal' into dev
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
/* © SRSoftware 2025 */
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.bookmarks;
|
package de.srsoftware.umbrella.bookmarks;
|
||||||
|
|
||||||
import static de.srsoftware.umbrella.messagebus.events.Event.EventType;
|
|
||||||
import static de.srsoftware.umbrella.bookmarks.Constants.*;
|
import static de.srsoftware.umbrella.bookmarks.Constants.*;
|
||||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
||||||
import static de.srsoftware.umbrella.core.ModuleRegistry.tagService;
|
import static de.srsoftware.umbrella.core.ModuleRegistry.tagService;
|
||||||
@@ -29,14 +28,9 @@ import de.srsoftware.umbrella.core.constants.Text;
|
|||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.Token;
|
import de.srsoftware.umbrella.core.model.Token;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
|
import de.srsoftware.umbrella.messagebus.events.BookmarkEvent;
|
||||||
import java.awt.print.Book;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.messagebus.events.BookmarkEvent;
|
|
||||||
import de.srsoftware.umbrella.messagebus.events.Event;
|
|
||||||
import de.srsoftware.umbrella.messagebus.events.TaskEvent;
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
|
|
||||||
public class BookmarkApi extends BaseHandler implements BookmarkService {
|
public class BookmarkApi extends BaseHandler implements BookmarkService {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package de.srsoftware.umbrella.bookmarks;
|
|||||||
|
|
||||||
import de.srsoftware.umbrella.core.model.Bookmark;
|
import de.srsoftware.umbrella.core.model.Bookmark;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import static de.srsoftware.umbrella.core.constants.Field.*;
|
|||||||
import static de.srsoftware.umbrella.core.constants.Text.BOOKMARK;
|
import static de.srsoftware.umbrella.core.constants.Text.BOOKMARK;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus;
|
import static de.srsoftware.umbrella.messagebus.MessageBus.messageBus;
|
||||||
import static de.srsoftware.umbrella.messagebus.events.Event.EventType.CREATE;
|
|
||||||
import static de.srsoftware.umbrella.messagebus.events.Event.EventType.UPDATE;
|
|
||||||
import static java.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
import static java.time.ZoneOffset.UTC;
|
import static java.time.ZoneOffset.UTC;
|
||||||
|
|
||||||
@@ -24,7 +22,6 @@ import de.srsoftware.umbrella.core.model.Translatable;
|
|||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import de.srsoftware.umbrella.messagebus.events.BookmarkEvent;
|
import de.srsoftware.umbrella.messagebus.events.BookmarkEvent;
|
||||||
import de.srsoftware.umbrella.messagebus.events.Event;
|
import de.srsoftware.umbrella.messagebus.events.Event;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.messagebus.events;
|
package de.srsoftware.umbrella.messagebus.events;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.constants.Field;
|
|
||||||
import de.srsoftware.umbrella.core.model.Bookmark;
|
|
||||||
import de.srsoftware.umbrella.core.model.Task;
|
|
||||||
import de.srsoftware.umbrella.core.model.Translatable;
|
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static de.srsoftware.umbrella.core.constants.Module.BOOKMARK;
|
import static de.srsoftware.umbrella.core.constants.Module.BOOKMARK;
|
||||||
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||||
|
|
||||||
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
|
import de.srsoftware.umbrella.core.model.Bookmark;
|
||||||
|
import de.srsoftware.umbrella.core.model.Translatable;
|
||||||
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class BookmarkEvent extends Event<Bookmark> {
|
public class BookmarkEvent extends Event<Bookmark> {
|
||||||
|
|
||||||
public BookmarkEvent(UmbrellaUser initiator, Bookmark bookmark, EventType type){
|
public BookmarkEvent(UmbrellaUser initiator, Bookmark bookmark, EventType type){
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ public class Field {
|
|||||||
public static final String SUBJECT = "subject";
|
public static final String SUBJECT = "subject";
|
||||||
|
|
||||||
public static final String TABLE = "table";
|
public static final String TABLE = "table";
|
||||||
|
public static final String TAG = "tag";
|
||||||
public static final String TAGS = "tags";
|
public static final String TAGS = "tags";
|
||||||
public static final String TAG_COLORS = "tag_colors";
|
public static final String TAG_COLORS = "tag_colors";
|
||||||
public static final String TASK = "task";
|
public static final String TASK = "task";
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
candidates = [];
|
candidates = [];
|
||||||
selected = [];
|
selected = [];
|
||||||
onCommit(candidate);
|
onCommit(candidate);
|
||||||
|
candidate = { display : '' };
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
import {onMount} from 'svelte';
|
import {onMount} from 'svelte';
|
||||||
import { useTinyRouter } from 'svelte-tiny-router';
|
import { useTinyRouter } from 'svelte-tiny-router';
|
||||||
|
|
||||||
import { api } from '../../urls.svelte.js';
|
import Autocomplete from '../../Components/Autocomplete.svelte';
|
||||||
|
|
||||||
|
import { api, get, post } from '../../urls.svelte.js';
|
||||||
import { error, yikes } from '../../warn.svelte';
|
import { error, yikes } from '../../warn.svelte';
|
||||||
import { t } from '../../translations.svelte.js';
|
import { t } from '../../translations.svelte.js';
|
||||||
import { user } from '../../user.svelte.js'
|
import { user } from '../../user.svelte.js'
|
||||||
@@ -13,10 +15,9 @@
|
|||||||
tags = $bindable([]),
|
tags = $bindable([]),
|
||||||
user_list = [],
|
user_list = [],
|
||||||
} = $props();
|
} = $props();
|
||||||
let newTag = $state('');
|
|
||||||
let router = useTinyRouter();
|
let router = useTinyRouter();
|
||||||
|
|
||||||
async function addTag(){
|
async function addTag(newTag){
|
||||||
if (!newTag) return;
|
if (!newTag) return;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
// when creating elements, they don`t have an id, yet
|
// when creating elements, they don`t have an id, yet
|
||||||
@@ -63,10 +64,21 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getCandidates(input){
|
||||||
|
if (!input || input.length <3) return [];
|
||||||
|
const url = api(`tags/search/${encodeURI(input)}`);
|
||||||
|
const res = await get(url);
|
||||||
|
if (res.ok){
|
||||||
|
yikes();
|
||||||
|
const list = await res.json();
|
||||||
|
return list.map(elem => {return {display:elem}});
|
||||||
|
} else error(res);
|
||||||
|
}
|
||||||
|
|
||||||
async function loadTags(entityId){
|
async function loadTags(entityId){
|
||||||
if (!entityId) return; // when crating elements, they dont`t have an id, yet.
|
if (!entityId) return; // when crating elements, they dont`t have an id, yet.
|
||||||
const url = api(`tags/${module}/${entityId}`);
|
const url = api(`tags/${module}/${entityId}`);
|
||||||
const resp = await fetch(url,{credentials:'include'});
|
const resp = await get(url);
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
||||||
tags = await resp.json();
|
tags = await resp.json();
|
||||||
tags = tags.sort();
|
tags = tags.sort();
|
||||||
@@ -75,13 +87,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onCommit(wrapped){
|
||||||
|
addTag(wrapped.display);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSelect(dummy){}
|
||||||
|
|
||||||
function show(tag){
|
function show(tag){
|
||||||
router.navigate(`/tags/use/${tag}`);
|
router.navigate(`/tags/use/${tag}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function typed(ev){
|
|
||||||
if (ev.keyCode == 13) addTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
$effect(() => loadTags(id));
|
$effect(() => loadTags(id));
|
||||||
</script>
|
</script>
|
||||||
@@ -93,6 +108,6 @@
|
|||||||
</span>
|
</span>
|
||||||
{/each}
|
{/each}
|
||||||
<span class="tag editor">
|
<span class="tag editor">
|
||||||
<input type="text" bind:value={newTag} onkeyup={typed} />
|
<Autocomplete {getCandidates} {onCommit} {onSelect} />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
|||||||
import static de.srsoftware.umbrella.bookmarks.Constants.*;
|
import static de.srsoftware.umbrella.bookmarks.Constants.*;
|
||||||
import static de.srsoftware.umbrella.core.Errors.*;
|
import static de.srsoftware.umbrella.core.Errors.*;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.*;
|
import static de.srsoftware.umbrella.core.constants.Field.*;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.TAG;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.TAGS;
|
import static de.srsoftware.umbrella.core.constants.Field.TAGS;
|
||||||
import static de.srsoftware.umbrella.core.constants.Module.BOOKMARK;
|
import static de.srsoftware.umbrella.core.constants.Module.BOOKMARK;
|
||||||
import static de.srsoftware.umbrella.core.constants.Text.TABLE_WITH_NAME;
|
import static de.srsoftware.umbrella.core.constants.Text.TABLE_WITH_NAME;
|
||||||
@@ -25,8 +26,10 @@ import de.srsoftware.tools.Tuple;
|
|||||||
import de.srsoftware.tools.jdbc.Query;
|
import de.srsoftware.tools.jdbc.Query;
|
||||||
import de.srsoftware.umbrella.bookmarks.BookmarkDb;
|
import de.srsoftware.umbrella.bookmarks.BookmarkDb;
|
||||||
import de.srsoftware.umbrella.core.BaseDb;
|
import de.srsoftware.umbrella.core.BaseDb;
|
||||||
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
import de.srsoftware.umbrella.core.constants.Text;
|
import de.srsoftware.umbrella.core.constants.Text;
|
||||||
import de.srsoftware.umbrella.core.model.Translatable;
|
import de.srsoftware.umbrella.core.model.Translatable;
|
||||||
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -333,6 +336,19 @@ CREATE TABLE IF NOT EXISTS {0} (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> search(String key, UmbrellaUser user) {
|
||||||
|
try {
|
||||||
|
var tags = new HashSet<String>();
|
||||||
|
var rs = select("DISTINCT tag").from(TABLE_TAGS).where(USER_ID,equal(user.id())).where(Field.TAG,like("%"+key+"%")).exec(db);
|
||||||
|
while (rs.next()) tags.add(rs.getString(1));
|
||||||
|
rs.close();
|
||||||
|
return tags;
|
||||||
|
} catch (SQLException s){
|
||||||
|
throw failedToLoadObject(Text.TAGS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateId(String module, Object oldId, Object newId) {
|
public void updateId(String module, Object oldId, Object newId) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package de.srsoftware.umbrella.tags;
|
|||||||
|
|
||||||
|
|
||||||
import de.srsoftware.tools.Tuple;
|
import de.srsoftware.tools.Tuple;
|
||||||
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -32,5 +33,7 @@ public interface TagDB {
|
|||||||
|
|
||||||
void save(Collection<Long> userIds, String module, long entityId, Collection<String> tags);
|
void save(Collection<Long> userIds, String module, long entityId, Collection<String> tags);
|
||||||
|
|
||||||
|
Collection<String> search(String key, UmbrellaUser user);
|
||||||
|
|
||||||
void updateId(String module, Object oldId, Object newId);
|
void updateId(String module, Object oldId, Object newId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
|||||||
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
|
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
|
||||||
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE;
|
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.USER_LIST;
|
import static de.srsoftware.umbrella.core.constants.Field.USER_LIST;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Path.SEARCH;
|
||||||
import static de.srsoftware.umbrella.core.constants.Path.USES;
|
import static de.srsoftware.umbrella.core.constants.Path.USES;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
import static de.srsoftware.umbrella.tags.Constants.*;
|
import static de.srsoftware.umbrella.tags.Constants.*;
|
||||||
@@ -66,11 +67,13 @@ public class TagModule extends BaseHandler implements TagService {
|
|||||||
var user = userService().refreshSession(ex);
|
var user = userService().refreshSession(ex);
|
||||||
if (user.isEmpty()) return unauthorized(ex);
|
if (user.isEmpty()) return unauthorized(ex);
|
||||||
var module = path.pop();
|
var module = path.pop();
|
||||||
if (module == null) return getUserTags(ex, user.get());
|
return switch (module){
|
||||||
var head = path.pop();
|
case SEARCH -> searchTags(ex,path.pop(),user.get());
|
||||||
if (USES.equals(module)) return getTagUses(ex,head,user.get());
|
case USES -> getTagUses(ex,path.pop(),user.get());
|
||||||
long entityId = Long.parseLong(head);
|
case null -> getUserTags(ex, user.get());
|
||||||
return sendContent(ex, getTags(module,entityId,user.get()));
|
default -> sendContent(ex, getTags(module,Long.parseLong(path.pop()),user.get()));
|
||||||
|
};
|
||||||
|
|
||||||
} catch (NumberFormatException e){
|
} catch (NumberFormatException e){
|
||||||
return sendContent(ex,HTTP_UNPROCESSABLE,"Entity id missing in path.");
|
return sendContent(ex,HTTP_UNPROCESSABLE,"Entity id missing in path.");
|
||||||
} catch (UmbrellaException e){
|
} catch (UmbrellaException e){
|
||||||
@@ -150,6 +153,10 @@ public class TagModule extends BaseHandler implements TagService {
|
|||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean searchTags(HttpExchange ex, String head, UmbrellaUser user) throws IOException {
|
||||||
|
return sendContent(ex, tagDb.search(head, user));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateId(String module, Object oldId, Object newId) {
|
public void updateId(String module, Object oldId, Object newId) {
|
||||||
tagDb.updateId(module,oldId,newId);
|
tagDb.updateId(module,oldId,newId);
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import de.srsoftware.tools.SessionToken;
|
|||||||
import de.srsoftware.umbrella.core.BaseHandler;
|
import de.srsoftware.umbrella.core.BaseHandler;
|
||||||
import de.srsoftware.umbrella.core.ModuleRegistry;
|
import de.srsoftware.umbrella.core.ModuleRegistry;
|
||||||
import de.srsoftware.umbrella.core.api.*;
|
import de.srsoftware.umbrella.core.api.*;
|
||||||
import de.srsoftware.umbrella.core.constants.Field;
|
|
||||||
import de.srsoftware.umbrella.core.constants.Text;
|
import de.srsoftware.umbrella.core.constants.Text;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.*;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
|
|||||||
Reference in New Issue
Block a user