implemented searching in notes
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -92,11 +92,10 @@ public class Util {
|
|||||||
var svg = new String(out, UTF_8);
|
var svg = new String(out, UTF_8);
|
||||||
source = source.substring(0, start) + svg + source.substring(end);
|
source = source.substring(0, start) + svg + source.substring(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return MARKDOWN.text(source);
|
return MARKDOWN.text(source);
|
||||||
} catch (Exception e){
|
} catch (Throwable e){
|
||||||
if (LOG.isLoggable(TRACE)){
|
if (LOG.isLoggable(TRACE)){
|
||||||
LOG.log(TRACE,"Failed to render markdown, input was: \n{0}",source,e);
|
LOG.log(TRACE,"Failed to render markdown, input was: \n{0}",source,e);
|
||||||
} else LOG.log(WARNING,"Failed to render markdown. Enable TRACE log level for details.");
|
} else LOG.log(WARNING,"Failed to render markdown. Enable TRACE log level for details.");
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
import Bookmark from '../bookmark/Template.svelte';
|
import Bookmark from '../bookmark/Template.svelte';
|
||||||
|
|
||||||
const router = useTinyRouter();
|
const router = useTinyRouter();
|
||||||
console.log(router);
|
|
||||||
let bookmarks = $state(null);
|
let bookmarks = $state(null);
|
||||||
let companies = $state(null);
|
let companies = $state(null);
|
||||||
let error = $state(null);
|
let error = $state(null);
|
||||||
let fulltext = false;
|
let fulltext = false;
|
||||||
let key = $state(router.getQueryParam('key'));
|
let key = $state(router.getQueryParam('key'));
|
||||||
let input = $state(router.getQueryParam('key'));
|
let input = $state(router.getQueryParam('key'));
|
||||||
|
let notes = $state(null);
|
||||||
let projects = $state(null);
|
let projects = $state(null);
|
||||||
let tasks = $state(null);
|
let tasks = $state(null);
|
||||||
|
|
||||||
@@ -41,12 +41,17 @@
|
|||||||
};
|
};
|
||||||
fetch(api('bookmark/search'),options).then(handleBookmarks);
|
fetch(api('bookmark/search'),options).then(handleBookmarks);
|
||||||
fetch(api('company/search'),options).then(handleCompanies);
|
fetch(api('company/search'),options).then(handleCompanies);
|
||||||
|
fetch(api('notes/search'),options).then(handleNotes);
|
||||||
fetch(api('project/search'),options).then(handleProjects);
|
fetch(api('project/search'),options).then(handleProjects);
|
||||||
fetch(api('task/search'),options).then(handleTasks);
|
fetch(api('task/search'),options).then(handleTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
function go(path){
|
function onclick(e){
|
||||||
router.navigate(path);
|
e.preventDefault();
|
||||||
|
var target = e.target;
|
||||||
|
while (target && !target.href) target=target.parentNode;
|
||||||
|
let href = target.getAttribute('href');
|
||||||
|
if (href) router.navigate(href);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +73,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleNotes(resp){
|
||||||
|
if (resp.ok){
|
||||||
|
const json = await resp.json();
|
||||||
|
notes = Object.keys(json).length ? json : null;
|
||||||
|
} else {
|
||||||
|
error = await resp.text();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleProjects(resp){
|
async function handleProjects(resp){
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const res = await resp.json();
|
const res = await resp.json();
|
||||||
@@ -118,7 +132,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
{#each Object.values(projects) as project}
|
{#each Object.values(projects) as project}
|
||||||
<li>
|
<li>
|
||||||
<a href="#" onclick={e=>go(`/project/${project.id}/view`)} >{project.name}</a>
|
<a href="/project/{project.id}/view" {onclick} >{project.name}</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -132,7 +146,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
{#each Object.values(tasks) as task}
|
{#each Object.values(tasks) as task}
|
||||||
<li>
|
<li>
|
||||||
<a href="#" onclick={e=>go(`/task/${task.id}/view`)} >{task.name}</a>
|
<a href="/task/{task.id}/view" {onclick} >{task.name}</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -160,7 +174,24 @@
|
|||||||
<ul>
|
<ul>
|
||||||
{#each Object.values(companies) as company}
|
{#each Object.values(companies) as company}
|
||||||
<li>
|
<li>
|
||||||
<a href="#" onclick={e=>go(`/company/${company.id}/view`)} >{company.name}</a>
|
<a href="/company/{company.id}/view" {onclick} >{company.name}</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
|
{/if}
|
||||||
|
{#if notes}
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
{t('notes')}
|
||||||
|
</legend>
|
||||||
|
<ul>
|
||||||
|
{#each Object.values(notes) as note}
|
||||||
|
<li>
|
||||||
|
<a href="/{note.module}/{note.entity_id}/view" {onclick} >
|
||||||
|
<b>{t(note.module)} {note.entity_id}:</b>
|
||||||
|
{@html note.text.rendered}
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
package de.srsoftware.umbrella.notes;
|
package de.srsoftware.umbrella.notes;
|
||||||
|
|
||||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
||||||
import static de.srsoftware.umbrella.core.Constants.LIMIT;
|
import static de.srsoftware.umbrella.core.Constants.*;
|
||||||
import static de.srsoftware.umbrella.core.Constants.OFFSET;
|
import static de.srsoftware.umbrella.core.Constants.FULLTEXT;
|
||||||
|
import static de.srsoftware.umbrella.core.Paths.SEARCH;
|
||||||
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE;
|
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE;
|
||||||
import static de.srsoftware.umbrella.core.Util.mapValues;
|
import static de.srsoftware.umbrella.core.Util.mapValues;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
@@ -22,6 +23,7 @@ import de.srsoftware.umbrella.core.model.Token;
|
|||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -139,8 +141,10 @@ public class NoteModule extends BaseHandler implements NoteService {
|
|||||||
var user = userService().loadUser(token);
|
var user = userService().loadUser(token);
|
||||||
if (user.isEmpty()) return unauthorized(ex);
|
if (user.isEmpty()) return unauthorized(ex);
|
||||||
var module = path.pop();
|
var module = path.pop();
|
||||||
|
if (SEARCH.equals(module)) return postSearch(ex,user.get());
|
||||||
if (module == null) throw unprocessable("Module missing in path.");
|
if (module == null) throw unprocessable("Module missing in path.");
|
||||||
var entityId = path.pop();
|
var entityId = path.pop();
|
||||||
|
if (entityId == null || entityId.isBlank()) throw missingFieldException(ENTITY_ID);
|
||||||
String text = body(ex);
|
String text = body(ex);
|
||||||
if (text.isBlank()) throw missingFieldException("Note text");
|
if (text.isBlank()) throw missingFieldException("Note text");
|
||||||
var note = new Note(0,module,entityId,user.get().id(),text, LocalDateTime.now());
|
var note = new Note(0,module,entityId,user.get().id(),text, LocalDateTime.now());
|
||||||
@@ -162,6 +166,15 @@ public class NoteModule extends BaseHandler implements NoteService {
|
|||||||
return notesDb.list(module, entityId);
|
return notesDb.list(module, entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean postSearch(HttpExchange ex, UmbrellaUser user) throws IOException {
|
||||||
|
var json = json(ex);
|
||||||
|
if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingFieldException(KEY);
|
||||||
|
var keys = Arrays.asList(key.split(" "));
|
||||||
|
var fulltext = json.has(FULLTEXT) && json.get(FULLTEXT) instanceof Boolean val && val;
|
||||||
|
var notes = notesDb.find(user.id(),keys,fulltext);
|
||||||
|
return sendContent(ex,mapValues(notes));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Note save(Note note) {
|
public Note save(Note note) {
|
||||||
return notesDb.save(note);
|
return notesDb.save(note);
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
package de.srsoftware.umbrella.notes;
|
package de.srsoftware.umbrella.notes;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.model.Note;
|
import de.srsoftware.umbrella.core.model.Note;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface NotesDb {
|
public interface NotesDb {
|
||||||
@@ -9,6 +11,8 @@ public interface NotesDb {
|
|||||||
|
|
||||||
void deleteEntity(String module, String entityId);
|
void deleteEntity(String module, String entityId);
|
||||||
|
|
||||||
|
Map<Long, Note> find(long userId, List<String> keys, boolean fulltext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get all lists of a person
|
* get all lists of a person
|
||||||
* @return
|
* @return
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
package de.srsoftware.umbrella.notes;
|
package de.srsoftware.umbrella.notes;
|
||||||
|
|
||||||
import static de.srsoftware.tools.jdbc.Condition.equal;
|
import static de.srsoftware.tools.jdbc.Condition.equal;
|
||||||
|
import static de.srsoftware.tools.jdbc.Condition.like;
|
||||||
import static de.srsoftware.tools.jdbc.Query.*;
|
import static de.srsoftware.tools.jdbc.Query.*;
|
||||||
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
||||||
import static de.srsoftware.umbrella.core.Constants.*;
|
import static de.srsoftware.umbrella.core.Constants.*;
|
||||||
@@ -14,9 +15,12 @@ import de.srsoftware.tools.jdbc.Query;
|
|||||||
import de.srsoftware.umbrella.core.BaseDb;
|
import de.srsoftware.umbrella.core.BaseDb;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.Note;
|
import de.srsoftware.umbrella.core.model.Note;
|
||||||
|
import de.srsoftware.umbrella.core.model.Project;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SqliteDb extends BaseDb implements NotesDb {
|
public class SqliteDb extends BaseDb implements NotesDb {
|
||||||
@@ -161,9 +165,22 @@ CREATE TABLE IF NOT EXISTS "{0}" (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init(){
|
@Override
|
||||||
var version = createTables();
|
public Map<Long, Note> find(long userId, List<String> keys, boolean fulltext) {
|
||||||
LOG.log(INFO,"Updated task db to version {0}",version);
|
try {
|
||||||
|
var notes = new HashMap<Long, Note>();
|
||||||
|
var query = select(ALL).from(TABLE_NOTES).where(USER_ID, equal(userId));
|
||||||
|
for (var key : keys) query.where(NOTE,like("%"+key+"%"));
|
||||||
|
var rs = query.exec(db);
|
||||||
|
while (rs.next()){
|
||||||
|
var note = Note.of(rs);
|
||||||
|
notes.put(note.id(),note);
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
return notes;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new UmbrellaException("Failed to search notes");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user