Compare commits
3 Commits
search
...
feature/fa
| Author | SHA1 | Date | |
|---|---|---|---|
| 33ff47a133 | |||
| c1beda1669 | |||
| df39e6a57f |
26
Dockerfile
26
Dockerfile
@@ -1,15 +1,15 @@
|
|||||||
FROM alpine:3.22 AS svelte_build
|
FROM alpine:3.22 AS svelte_build
|
||||||
RUN apk add npm
|
RUN apk add npm
|
||||||
RUN adduser -Dh /home/svelte svelte
|
RUN adduser -Dh /home/svelte svelte
|
||||||
ADD frontend /home/svelte/Umbrella/frontend
|
ADD . /home/svelte/Umbrella
|
||||||
RUN chown -R svelte /home/svelte/Umbrella
|
RUN chown -R svelte /home/svelte/Umbrella
|
||||||
USER svelte
|
USER svelte
|
||||||
WORKDIR /home/svelte/Umbrella/frontend
|
WORKDIR /home/svelte/Umbrella/frontend
|
||||||
RUN npm install && npm run build
|
RUN npm install && npm run build
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.22 AS java_build
|
FROM alpine AS java_build
|
||||||
RUN apk add gradle
|
RUN apk add gradle fontconfig font-opensans openjdk21-jre
|
||||||
ADD . /Umbrella
|
ADD . /Umbrella
|
||||||
WORKDIR /Umbrella
|
WORKDIR /Umbrella
|
||||||
COPY --from=svelte_build /home/svelte/Umbrella/frontend/dist web/src/main/resources/web
|
COPY --from=svelte_build /home/svelte/Umbrella/frontend/dist web/src/main/resources/web
|
||||||
@@ -17,18 +17,14 @@ RUN gradle --no-daemon build
|
|||||||
|
|
||||||
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
RUN apk --no-cache add bash fontconfig font-opensans graphviz openjdk21-jre tzdata weasyprint \
|
RUN apk add bash fontconfig font-opensans graphviz openjdk21-jre weasyprint
|
||||||
&& adduser -D umbrella
|
RUN adduser -D umbrella
|
||||||
|
COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/
|
||||||
|
RUN chown -R umbrella /home/umbrella
|
||||||
|
ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar
|
||||||
WORKDIR /home/umbrella
|
WORKDIR /home/umbrella
|
||||||
|
RUN chmod a+rx plantuml.jar
|
||||||
|
USER umbrella
|
||||||
|
RUN mkdir .config && ln -s /host/config.json .config/Umbrella.json
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
CMD java -jar jar/backend.jar
|
CMD java -jar jar/backend.jar
|
||||||
|
|
||||||
ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar
|
|
||||||
COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/
|
|
||||||
RUN mkdir .config \
|
|
||||||
&& ln -s /host/config.json .config/Umbrella.json \
|
|
||||||
&& chmod a+rx plantuml.jar \
|
|
||||||
&& chown -R umbrella . \
|
|
||||||
&& ln -s /usr/share/zoneinfo/Europe/Berlin /etc/localtime
|
|
||||||
USER umbrella
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
FROM alpine:3.22
|
FROM alpine:3.22
|
||||||
LABEL Maintainer "Stephan Richter"
|
LABEL Maintainer "Stephan Richter <s.richter@srsoftware.de>"
|
||||||
ARG UID=1000
|
ARG UID=1000
|
||||||
ARG GID=1000
|
ARG GID=1000
|
||||||
RUN apk add bash npm
|
RUN apk add bash npm
|
||||||
|
|||||||
@@ -541,11 +541,6 @@ public class DocumentApi extends BaseHandler implements DocumentService {
|
|||||||
var userCompanyIds = companyService().listCompaniesOf(user).keySet();
|
var userCompanyIds = companyService().listCompaniesOf(user).keySet();
|
||||||
|
|
||||||
var documents = db.find(userCompanyIds,keys,fulltext);
|
var documents = db.find(userCompanyIds,keys,fulltext);
|
||||||
try {
|
|
||||||
Thread.sleep(5000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return sendContent(ex,mapValues(documents));
|
return sendContent(ex,mapValues(documents));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { useTinyRouter } from 'svelte-tiny-router';
|
import { useTinyRouter } from 'svelte-tiny-router';
|
||||||
import { api, get, post, target } from '../../urls.svelte.js';
|
import { api, post, target } from '../../urls.svelte.js';
|
||||||
import { error, warn, yikes } from '../../warn.svelte';
|
import { error, yikes } from '../../warn.svelte';
|
||||||
import { t } from '../../translations.svelte.js';
|
import { t } from '../../translations.svelte.js';
|
||||||
import { display } from '../../time.svelte';
|
import { display } from '../../time.svelte';
|
||||||
|
|
||||||
import Bookmark from '../bookmark/Template.svelte';
|
import Bookmark from '../bookmark/Template.svelte';
|
||||||
|
|
||||||
const router = useTinyRouter();
|
const router = useTinyRouter();
|
||||||
let counter = 9;
|
|
||||||
let bookmarks = $state(null);
|
let bookmarks = $state(null);
|
||||||
let companies = $state(null);
|
let companies = $state(null);
|
||||||
let documents = $state(null);
|
let documents = $state(null);
|
||||||
@@ -35,12 +34,12 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
function doSearch(ignored){
|
function doSearch(ignored){
|
||||||
warn(t('searching…'));
|
|
||||||
let url = window.location.origin + window.location.pathname;
|
let url = window.location.origin + window.location.pathname;
|
||||||
if (key) url += '?key=' + encodeURI(key);
|
if (key) url += '?key=' + encodeURI(key);
|
||||||
window.history.replaceState(history.state, '', url);
|
window.history.replaceState(history.state, '', url);
|
||||||
|
|
||||||
const data = { key : key, fulltext : fulltext };
|
const data = { key : key, fulltext : fulltext };
|
||||||
|
|
||||||
post(api('bookmark/search'),data).then(handleBookmarks);
|
post(api('bookmark/search'),data).then(handleBookmarks);
|
||||||
post(api('company/search '),data).then(handleCompanies);
|
post(api('company/search '),data).then(handleCompanies);
|
||||||
post(api('document/search'),data).then(handleDocuments);
|
post(api('document/search'),data).then(handleDocuments);
|
||||||
@@ -52,22 +51,6 @@
|
|||||||
post(api('wiki/search' ),data).then(handleWikiPages);
|
post(api('wiki/search' ),data).then(handleWikiPages);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getTitle(key,module,entity_id){
|
|
||||||
get(api(module+'/'+entity_id)).then(res => setTitle(res,key,module))
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setTitle(resp,key,module){
|
|
||||||
if (resp.ok){
|
|
||||||
const json = await resp.json();
|
|
||||||
if (json.name) notes[key].title = t(module)+": "+json.name;
|
|
||||||
if (json.title) notes[key].title = t(module)+": "+json.title;
|
|
||||||
if (module == 'document'){
|
|
||||||
notes[key].title = t(json.type)+" "+json.number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function onclick(e){
|
function onclick(e){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var target = e.target;
|
var target = e.target;
|
||||||
@@ -78,7 +61,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleBookmarks(resp){
|
async function handleBookmarks(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const res = await resp.json();
|
const res = await resp.json();
|
||||||
bookmarks = Object.keys(res).length ? res : null;
|
bookmarks = Object.keys(res).length ? res : null;
|
||||||
@@ -88,7 +70,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleCompanies(resp){
|
async function handleCompanies(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const json = await resp.json();
|
const json = await resp.json();
|
||||||
companies = Object.keys(json).length ? json : null;
|
companies = Object.keys(json).length ? json : null;
|
||||||
@@ -98,7 +79,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleDocuments(resp){
|
async function handleDocuments(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const json = await resp.json();
|
const json = await resp.json();
|
||||||
documents = Object.keys(json).length ? json : null;
|
documents = Object.keys(json).length ? json : null;
|
||||||
@@ -108,25 +88,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleNotes(resp){
|
async function handleNotes(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const json = await resp.json();
|
const json = await resp.json();
|
||||||
if ( Object.keys(json).length ) {
|
notes = Object.keys(json).length ? json : null;
|
||||||
for (let key of Object.keys(json)){
|
|
||||||
let module = json[key].module;
|
|
||||||
let entity_id = json[key].entity_id;
|
|
||||||
json[key].title = t(module)+' '+entity_id;
|
|
||||||
getTitle(key,module,entity_id);
|
|
||||||
}
|
|
||||||
notes = json;
|
|
||||||
} else notes = null;
|
|
||||||
} else {
|
} else {
|
||||||
error(resp);
|
error(resp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleProjects(resp){
|
async function handleProjects(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const res = await resp.json();
|
const res = await resp.json();
|
||||||
projects = Object.keys(res).length ? res : null;
|
projects = Object.keys(res).length ? res : null;
|
||||||
@@ -136,7 +106,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleStock(resp){
|
async function handleStock(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const res = await resp.json();
|
const res = await resp.json();
|
||||||
stock = Object.keys(res).length ? res : null;
|
stock = Object.keys(res).length ? res : null;
|
||||||
@@ -146,7 +115,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleTasks(resp){
|
async function handleTasks(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const res = await resp.json();
|
const res = await resp.json();
|
||||||
tasks = Object.keys(res).length ? res : null;
|
tasks = Object.keys(res).length ? res : null;
|
||||||
@@ -156,7 +124,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleTimes(resp){
|
async function handleTimes(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const res = await resp.json();
|
const res = await resp.json();
|
||||||
times = Object.keys(res).length ? res : null;
|
times = Object.keys(res).length ? res : null;
|
||||||
@@ -166,7 +133,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleWikiPages(resp){
|
async function handleWikiPages(resp){
|
||||||
quitOne();
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
const res = await resp.json();
|
const res = await resp.json();
|
||||||
pages = Object.keys(res).length ? res : null;
|
pages = Object.keys(res).length ? res : null;
|
||||||
@@ -174,13 +140,6 @@
|
|||||||
error(resp);
|
error(resp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function quitOne(){
|
|
||||||
counter--;
|
|
||||||
if (counter > 0) {
|
|
||||||
warn(t('searching…')+" "+counter);
|
|
||||||
} else yikes();
|
|
||||||
}
|
|
||||||
|
|
||||||
$effect(() => doSearch(key))
|
$effect(() => doSearch(key))
|
||||||
</script>
|
</script>
|
||||||
@@ -277,6 +236,23 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if notes}
|
||||||
|
<fieldset>
|
||||||
|
<legend>
|
||||||
|
{t('notes')}
|
||||||
|
</legend>
|
||||||
|
<ul>
|
||||||
|
{#each Object.values(notes) as note}
|
||||||
|
<li>
|
||||||
|
<b>
|
||||||
|
<a href="/{note.module}/{note.entity_id}/view" {onclick} >{t(note.module)} {note.entity_id}:</a>
|
||||||
|
</b>
|
||||||
|
{@html target(note.text.rendered)}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
|
{/if}
|
||||||
{#if times}
|
{#if times}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>
|
<legend>
|
||||||
@@ -332,20 +308,3 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{/if}
|
{/if}
|
||||||
{#if notes}
|
|
||||||
<fieldset>
|
|
||||||
<legend>
|
|
||||||
{t('notes')}
|
|
||||||
</legend>
|
|
||||||
<ul>
|
|
||||||
{#each Object.values(notes) as note}
|
|
||||||
<li>
|
|
||||||
<b>
|
|
||||||
<a href="/{note.module}/{note.entity_id}/view" {onclick} >{note.title}</a>
|
|
||||||
</b>
|
|
||||||
{@html target(note.text.rendered)}
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
</ul>
|
|
||||||
</fieldset>
|
|
||||||
{/if}
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ public class Constants {
|
|||||||
public static final String AUTH = "mail.smtp.auth";
|
public static final String AUTH = "mail.smtp.auth";
|
||||||
|
|
||||||
public static final String CONFIG_DB = "umbrella.modules.message.database";
|
public static final String CONFIG_DB = "umbrella.modules.message.database";
|
||||||
|
public static final String CONFIG_SMTP_FROM = "umbrella.modules.message.smtp.from";
|
||||||
public static final String CONFIG_SMTP_HOST = "umbrella.modules.message.smtp.host";
|
public static final String CONFIG_SMTP_HOST = "umbrella.modules.message.smtp.host";
|
||||||
public static final String CONFIG_SMTP_PASS = "umbrella.modules.message.smtp.pass";
|
public static final String CONFIG_SMTP_PASS = "umbrella.modules.message.smtp.pass";
|
||||||
public static final String CONFIG_SMTP_PORT = "umbrella.modules.message.smtp.port";
|
public static final String CONFIG_SMTP_PORT = "umbrella.modules.message.smtp.port";
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package de.srsoftware.umbrella.message;
|
|||||||
|
|
||||||
import static de.srsoftware.tools.PathHandler.CONTENT_TYPE;
|
import static de.srsoftware.tools.PathHandler.CONTENT_TYPE;
|
||||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
||||||
|
import static de.srsoftware.umbrella.core.ModuleRegistry.translator;
|
||||||
import static de.srsoftware.umbrella.core.constants.Constants.UTF8;
|
import static de.srsoftware.umbrella.core.constants.Constants.UTF8;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingConfig;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingConfig;
|
||||||
import static de.srsoftware.umbrella.message.Constants.*;
|
import static de.srsoftware.umbrella.message.Constants.*;
|
||||||
@@ -12,6 +13,7 @@ import de.srsoftware.configuration.Configuration;
|
|||||||
import de.srsoftware.umbrella.core.ModuleRegistry;
|
import de.srsoftware.umbrella.core.ModuleRegistry;
|
||||||
import de.srsoftware.umbrella.core.api.PostBox;
|
import de.srsoftware.umbrella.core.api.PostBox;
|
||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
|
import de.srsoftware.umbrella.core.model.EmailAddress;
|
||||||
import de.srsoftware.umbrella.core.model.Envelope;
|
import de.srsoftware.umbrella.core.model.Envelope;
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
import de.srsoftware.umbrella.core.model.User;
|
import de.srsoftware.umbrella.core.model.User;
|
||||||
@@ -76,10 +78,10 @@ public class MessageSystem implements PostBox {
|
|||||||
db = new SqliteMessageDb(connect(dbFile));
|
db = new SqliteMessageDb(connect(dbFile));
|
||||||
debugAddress = config.get(DEBUG_ADDREESS).map(Object::toString).orElse(null);
|
debugAddress = config.get(DEBUG_ADDREESS).map(Object::toString).orElse(null);
|
||||||
port = config.get(CONFIG_SMTP_PORT,587);
|
port = config.get(CONFIG_SMTP_PORT,587);
|
||||||
host = config.get(CONFIG_SMTP_HOST).map(Object::toString).orElseThrow(() -> new RuntimeException("umbrella.modules.message.smtp.host not configured!"));
|
host = config.get(CONFIG_SMTP_HOST).map(Object::toString).orElseThrow(() -> missingConfig(CONFIG_SMTP_HOST));
|
||||||
user = config.get(CONFIG_SMTP_USER).map(Object::toString).orElseThrow(() -> new RuntimeException("umbrella.modules.message.smtp.user not configured!"));
|
user = config.get(CONFIG_SMTP_USER).map(Object::toString).orElseThrow(() -> missingConfig(CONFIG_SMTP_USER));
|
||||||
pass = config.get(CONFIG_SMTP_PASS).map(Object::toString).orElseThrow(() -> new RuntimeException("umbrella.modules.message.smtp.pass not configured!"));
|
pass = config.get(CONFIG_SMTP_PASS).map(Object::toString).orElseThrow(() -> missingConfig(CONFIG_SMTP_PASS));
|
||||||
from = user;
|
from = config.get(CONFIG_SMTP_FROM).map(Object::toString).orElseThrow(() -> missingConfig(CONFIG_SMTP_FROM));
|
||||||
ModuleRegistry.add(this);
|
ModuleRegistry.add(this);
|
||||||
new SubmissionTask(8).schedule();
|
new SubmissionTask(8).schedule();
|
||||||
new SubmissionTask(10).schedule();
|
new SubmissionTask(10).schedule();
|
||||||
@@ -116,9 +118,9 @@ public class MessageSystem implements PostBox {
|
|||||||
var date = new Date();
|
var date = new Date();
|
||||||
|
|
||||||
for (var receiver : dueRecipients){
|
for (var receiver : dueRecipients){
|
||||||
BiFunction<String,Map<String,String>,String> translateFunction = (text,fills) -> ModuleRegistry.translator().translate(receiver.language(),text,fills);
|
BiFunction<String,Map<String,String>,String> translateFunction = (text,fills) -> translator().translate(receiver.language(),text,fills);
|
||||||
|
var fallbackSender = new User("Umbrella",new EmailAddress(from),null);
|
||||||
var combined = new CombinedMessage("Collected messages",translateFunction);
|
var combined = new CombinedMessage("Collected messages",translateFunction,fallbackSender);
|
||||||
var envelopes = queue.stream().filter(env -> env.isFor(receiver)).toList();
|
var envelopes = queue.stream().filter(env -> env.isFor(receiver)).toList();
|
||||||
for (var envelope : envelopes) combined.merge(envelope.message());
|
for (var envelope : envelopes) combined.merge(envelope.message());
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import static java.lang.System.Logger.Level.DEBUG;
|
|||||||
import static java.lang.System.Logger.Level.TRACE;
|
import static java.lang.System.Logger.Level.TRACE;
|
||||||
import static java.text.MessageFormat.format;
|
import static java.text.MessageFormat.format;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.model.Attachment;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
import de.srsoftware.umbrella.core.model.Message;
|
|
||||||
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
@@ -16,15 +14,17 @@ public class CombinedMessage {
|
|||||||
|
|
||||||
private final Set<Attachment> attachments = new HashSet<>();
|
private final Set<Attachment> attachments = new HashSet<>();
|
||||||
private final StringBuilder combinedBody = new StringBuilder();
|
private final StringBuilder combinedBody = new StringBuilder();
|
||||||
|
private final User fallbackSender;
|
||||||
private String combinedSubject = null;
|
private String combinedSubject = null;
|
||||||
private final List<Message> mergedMessages = new ArrayList<>();
|
private final List<Message> mergedMessages = new ArrayList<>();
|
||||||
private final String subjectForCombinedMessage;
|
private final String subjectForCombinedMessage;
|
||||||
private final BiFunction<String,Map<String,String>,String> translate;
|
private final BiFunction<String,Map<String,String>,String> translate;
|
||||||
private UmbrellaUser sender = null;
|
private User sender = null;
|
||||||
|
|
||||||
public CombinedMessage(String subjectForCombinedMessage, BiFunction<String, Map<String,String>,String> translateFunction){
|
public CombinedMessage(String subjectForCombinedMessage, BiFunction<String, Map<String,String>,String> translateFunction, User fallbackSender){
|
||||||
LOG.log(DEBUG,"Creating combined message…");
|
LOG.log(DEBUG,"Creating combined message…");
|
||||||
this.subjectForCombinedMessage = subjectForCombinedMessage;
|
this.subjectForCombinedMessage = translateFunction.apply(subjectForCombinedMessage,null);
|
||||||
|
this.fallbackSender = fallbackSender;
|
||||||
translate = translateFunction;
|
translate = translateFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,12 +39,12 @@ public class CombinedMessage {
|
|||||||
combinedSubject = subject;
|
combinedSubject = subject;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
combinedBody.insert(0,format("# {0}:\n# {1}:\n\n",sender,subject)); // insert sender and subject of first message right before the body of the first message
|
if (!sender.equals(message.sender())) sender = fallbackSender;
|
||||||
|
combinedBody.insert(0,format("# {0} / {1}:\n\n",sender,subject)); // insert sender and subject of first message right before the body of the first message
|
||||||
combinedSubject = subjectForCombinedMessage;
|
combinedSubject = subjectForCombinedMessage;
|
||||||
// no break here, we need to append the subject and content
|
// no break here, we need to append the subject and content
|
||||||
default:
|
default:
|
||||||
combinedBody.append("\n\n# ").append(message.sender()).append(":\n");
|
combinedBody.append("\n-----\n# ").append(message.sender()).append(" / ").append(subject).append(":\n\n");
|
||||||
combinedBody.append("# ").append(subject).append(":\n\n");
|
|
||||||
combinedBody.append(body);
|
combinedBody.append(body);
|
||||||
}
|
}
|
||||||
if (message.attachments() != null) attachments.addAll(message.attachments());
|
if (message.attachments() != null) attachments.addAll(message.attachments());
|
||||||
@@ -59,7 +59,7 @@ public class CombinedMessage {
|
|||||||
return combinedBody.toString();
|
return combinedBody.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UmbrellaUser sender() {
|
public User sender() {
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,23 +132,7 @@ public class StockModule extends BaseHandler implements StockService {
|
|||||||
yield super.doGet(path,ex);
|
yield super.doGet(path,ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case null -> super.doGet(path,ex);
|
case null, default -> super.doGet(path,ex);
|
||||||
default -> {
|
|
||||||
try {
|
|
||||||
var id = Long.parseLong(head);
|
|
||||||
Item item = stockDb.loadItem(id);
|
|
||||||
Owner owner = item.owner().resolve();
|
|
||||||
if (owner instanceof Company company) {
|
|
||||||
if (!companyService().membership(company.id(),user.get().id())) throw forbidden("You are not allowed to access {0}",OBJECT);
|
|
||||||
}
|
|
||||||
if (owner instanceof UmbrellaUser u){
|
|
||||||
if (u.id() != user.get().id()) throw forbidden("You are not allowed to access {0}",OBJECT);
|
|
||||||
}
|
|
||||||
yield sendContent(ex,item);
|
|
||||||
} catch (NumberFormatException nfe){
|
|
||||||
yield super.doGet(path,ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} catch (UmbrellaException e){
|
} catch (UmbrellaException e){
|
||||||
return send(ex,e);
|
return send(ex,e);
|
||||||
|
|||||||
@@ -278,7 +278,6 @@
|
|||||||
"saved": "gespeichert",
|
"saved": "gespeichert",
|
||||||
"save_object": "{object} speichern",
|
"save_object": "{object} speichern",
|
||||||
"search": "Suche",
|
"search": "Suche",
|
||||||
"searching…": "suche…",
|
|
||||||
"select_company" : "Wählen Sie eine ihrer Firmen:",
|
"select_company" : "Wählen Sie eine ihrer Firmen:",
|
||||||
"select_customer": "Kunde auswählen",
|
"select_customer": "Kunde auswählen",
|
||||||
"select_property": "Eigenschaft auswählen",
|
"select_property": "Eigenschaft auswählen",
|
||||||
|
|||||||
@@ -278,7 +278,6 @@
|
|||||||
"saved": "saved",
|
"saved": "saved",
|
||||||
"save_object": "save {object}",
|
"save_object": "save {object}",
|
||||||
"search": "search",
|
"search": "search",
|
||||||
"searching…": "searhcing…",
|
|
||||||
"select_company" : "select on of you companies:",
|
"select_company" : "select on of you companies:",
|
||||||
"select_customer": "select customer",
|
"select_customer": "select customer",
|
||||||
"select_property": "select property",
|
"select_property": "select property",
|
||||||
|
|||||||
@@ -9,5 +9,4 @@ tasks.processResources {
|
|||||||
from("../frontend/dist") {
|
from("../frontend/dist") {
|
||||||
into("web")
|
into("web")
|
||||||
}
|
}
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
}
|
||||||
}
|
|
||||||
@@ -152,27 +152,15 @@ public class SqliteDb extends BaseDb implements WikiDb {
|
|||||||
@Override
|
@Override
|
||||||
public Map<Long, WikiPage> find(long userId, List<String> keys, boolean fulltext) {
|
public Map<Long, WikiPage> find(long userId, List<String> keys, boolean fulltext) {
|
||||||
try {
|
try {
|
||||||
|
var query = select(ALL).from(TABLE_PAGES).leftJoin(ID,TABLE_PAGES_USERS,PAGE_ID).where(USER_ID,equal(userId));
|
||||||
|
for (var key : keys) query.where(TITLE,like("%"+key+"%"));
|
||||||
|
var rs = query.exec(db);
|
||||||
var map = new HashMap<Long,WikiPage>();
|
var map = new HashMap<Long,WikiPage>();
|
||||||
{
|
while (rs.next()) {
|
||||||
var query = select(ALL).from(TABLE_PAGES).leftJoin(ID, TABLE_PAGES_USERS, PAGE_ID).where(USER_ID, equal(userId));
|
var page = WikiPage.of(rs);
|
||||||
for (var key : keys) query.where(TITLE, like("%" + key.replaceAll("[ÄäÖöÜüß]", "%") + "%"));
|
map.put(page.id(),page);
|
||||||
var rs = query.exec(db);
|
|
||||||
while (rs.next()) {
|
|
||||||
var page = WikiPage.of(rs);
|
|
||||||
map.put(page.id(), page);
|
|
||||||
}
|
|
||||||
rs.close();
|
|
||||||
}
|
|
||||||
if (fulltext) {
|
|
||||||
var query = select(ALL).from(TABLE_PAGES).leftJoin(ID, TABLE_PAGES_USERS, PAGE_ID).where(USER_ID, equal(userId));
|
|
||||||
for (var key : keys) query.where(CONTENT, like("%" + key.replaceAll("[ÄäÖöÜüß]", "%") + "%"));
|
|
||||||
var rs = query.exec(db);
|
|
||||||
while (rs.next()) {
|
|
||||||
var page = WikiPage.of(rs);
|
|
||||||
map.put(page.id(), page);
|
|
||||||
}
|
|
||||||
rs.close();
|
|
||||||
}
|
}
|
||||||
|
rs.close();
|
||||||
return map;
|
return map;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw failedToSearchDb(t(WIKI_PAGES)).causedBy(e);
|
throw failedToSearchDb(t(WIKI_PAGES)).causedBy(e);
|
||||||
|
|||||||
Reference in New Issue
Block a user