Compare commits
123 Commits
module/spr
...
improvemen
| Author | SHA1 | Date | |
|---|---|---|---|
| dba2657894 | |||
| 03b9a472c3 | |||
| f9bb8def03 | |||
| 229a6f8e5a | |||
| 69beabfbc8 | |||
| 7349d301dd | |||
| 24c079a0ed | |||
| 40bdad12de | |||
| 697d7b01e5 | |||
| b7219ef6ec | |||
| 7cccb7482b | |||
| dde23dc9c3 | |||
| c4351d3007 | |||
| 4a5ae7e1ad | |||
| a37a57ab3f | |||
| 6e73a71082 | |||
| d847fbecbb | |||
| f455d748f6 | |||
| 83c173a108 | |||
| 4f7cbd9f22 | |||
| 702684666c | |||
| db95cdbb58 | |||
| 99b33791ef | |||
| a72d556a36 | |||
| f7d6f2936a | |||
| fb4fcc53de | |||
| 7f39d71f4a | |||
| 4ebb5d54d3 | |||
| e86e9289ed | |||
| 604814e057 | |||
| 4964082c2e | |||
| a5e2c69afb | |||
| 494ba3ff41 | |||
| 53fe0db2c1 | |||
| 6843bbb475 | |||
| 79924094e4 | |||
| 4f4174df8d | |||
| f052b62a30 | |||
| b7c2bcb741 | |||
| c5099e41f8 | |||
| f08f7a0852 | |||
| 2a134b72b7 | |||
| 3b6e84d1af | |||
| 75441c3260 | |||
| fd3d01b905 | |||
| efd0773e5c | |||
| b2241c3504 | |||
| 7f48fc12c8 | |||
| 3ba49ed87f | |||
| 018d67e959 | |||
| f2065c5be6 | |||
| a921fac87e | |||
| 80a471d904 | |||
| 09a6a809b2 | |||
| 6656b67ae7 | |||
| b050f06467 | |||
| 06189dff5b | |||
| 31bb075be7 | |||
| f6f9a7c18b | |||
| 6fe1c82e05 | |||
| 3070f67274 | |||
| b238b21a6a | |||
| 9221449ecf | |||
| 866ce71b30 | |||
| 2088cd608d | |||
| 752a487cb0 | |||
| e48538727f | |||
| cdb8814f20 | |||
| b56979881f | |||
| 59d54b734b | |||
| c25c342d15 | |||
| 6c183d0467 | |||
| 66ea13186a | |||
| 710ac289ec | |||
| dc5044243b | |||
| b4e0b5ad6a | |||
| 6f3338a95e | |||
| 28a08670d7 | |||
| 5992bff658 | |||
| 63bc54fd1b | |||
| d7d2505847 | |||
| 93e568624e | |||
| 335309e20a | |||
| 121457d793 | |||
| 6f3cb577b0 | |||
| 9386668db0 | |||
| be2235b873 | |||
| 8c351440c8 | |||
| 5a745659b9 | |||
| ab5a74eac7 | |||
| 268cea0550 | |||
| 5b7bc95614 | |||
| 41b6af88db | |||
| c75a8a4274 | |||
| 4a6bdfb215 | |||
| f85e86bedf | |||
| 2e858e8506 | |||
| 1c104af4a6 | |||
| fafe20e9e2 | |||
| 83c19a7799 | |||
| a990903e3d | |||
| a9a518e508 | |||
| 934aa9bc89 | |||
| 6406580385 | |||
| 562c854a5b | |||
| 73994d3a4e | |||
| ac2f974e5a | |||
| cd25d23246 | |||
| 8d2f3ef88e | |||
| 8e53d3b306 | |||
| bd95c3d0c4 | |||
| 421a350f57 | |||
| dceb84669b | |||
| eaeb625d51 | |||
| e980dbf884 | |||
| dfa991b90a | |||
| 3b40250488 | |||
| 8e8992f534 | |||
| 076efda195 | |||
| 5c1e802a6f | |||
| 750e0f16e1 | |||
| c06083476f | |||
| f784ec6109 |
@@ -41,10 +41,10 @@ jobs:
|
|||||||
docker push ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }}
|
docker push ${{ secrets.REGISTRY_PATH }}/umbrella:${{ gitea.ref_name }}
|
||||||
docker push ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG
|
docker push ${{ secrets.REGISTRY_PATH }}/umbrella:$TAG
|
||||||
|
|
||||||
- name: Restart vj.srsoftware.de
|
- name: Restart umbrella.srsoftware.de
|
||||||
if: github.ref == 'refs/heads/main'
|
if: github.ref == 'refs/heads/dev'
|
||||||
run: |
|
run: |
|
||||||
curl -X POST -H "Authorization: Bearer ${{ secrets.MAKE_BEARER }}" -d vj_start https://make.srsoftware.de/launch
|
curl -X POST -H "Authorization: Bearer ${{ secrets.ELDORADO_MAKE_BEARER }}" -d umbrella_25_start https://make.eldorado.srsoftware.de/launch
|
||||||
|
|
||||||
Clean-Registry:
|
Clean-Registry:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ RUN apk --no-cache add bash fontconfig font-opensans graphviz openjdk21-jre tzda
|
|||||||
WORKDIR /home/umbrella
|
WORKDIR /home/umbrella
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
CMD java -jar jar/backend.jar
|
CMD java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:9999 -jar jar/backend.jar
|
||||||
|
|
||||||
ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.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/
|
COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class CompanyModule extends BaseHandler implements CompanyService {
|
|||||||
var company = get(companyId);
|
var company = get(companyId);
|
||||||
if (!membership(companyId,user.id())) throw forbidden("You are mot a member of company {company}", COMPANY,company.name());
|
if (!membership(companyId,user.id())) throw forbidden("You are mot a member of company {company}", COMPANY,company.name());
|
||||||
if (!documentService().list(companyId).isEmpty()) throw forbidden("There are documents owned by {company}", COMPANY,company.name());
|
if (!documentService().list(companyId).isEmpty()) throw forbidden("There are documents owned by {company}", COMPANY,company.name());
|
||||||
if (!itemService().redefineMe(companyId).isEmpty()) throw forbidden("There are items owned by {company}", COMPANY,company.name());
|
if (!itemService().getCompanyItems(companyId).isEmpty()) throw forbidden("There are items owned by {company}", COMPANY,company.name());
|
||||||
if (!projectService().listCompanyProjects(companyId,true).isEmpty()) throw forbidden("There are projects owned by {company}", COMPANY,company.name());
|
if (!projectService().listCompanyProjects(companyId,true).isEmpty()) throw forbidden("There are projects owned by {company}", COMPANY,company.name());
|
||||||
return sendContent(ex, companyDb.drop(companyId));
|
return sendContent(ex, companyDb.drop(companyId));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,12 @@ package de.srsoftware.umbrella.core.api;
|
|||||||
|
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.model.DbLocation;
|
import de.srsoftware.umbrella.core.model.DbLocation;
|
||||||
|
import de.srsoftware.umbrella.core.model.Item;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
public interface StockService {
|
public interface StockService {
|
||||||
/**
|
Collection<Item> getCompanyItems(long companyID);
|
||||||
* Das war mal die methode um zu checken, ob einer Firma noch Items zugewiesen sind.
|
|
||||||
* TODO: Diese Methode muss neu definiert werden, sobald der Stock-Service neu implementiert ist.
|
|
||||||
* @param company_id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Collection<Object> redefineMe(long company_id);
|
|
||||||
|
|
||||||
DbLocation loadLocation(long locationId);
|
DbLocation loadLocation(long locationId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
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 { api, 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 Position from './Position.svelte';
|
import Position from './Position.svelte';
|
||||||
|
import PositionSelector from './PositionSelector.svelte';
|
||||||
|
|
||||||
var {
|
var {
|
||||||
document = $bindable(null),
|
document = $bindable(null),
|
||||||
@@ -15,6 +16,18 @@
|
|||||||
|
|
||||||
let editable = $derived(document.state == 1);
|
let editable = $derived(document.state == 1);
|
||||||
let sums = $derived.by(calcSums);
|
let sums = $derived.by(calcSums);
|
||||||
|
let position_select = $state(false);
|
||||||
|
|
||||||
|
async function addPosition(selected){
|
||||||
|
const url = api(`document/${document.id}/position`);
|
||||||
|
const resp = await post(url,selected);
|
||||||
|
if (resp.ok){
|
||||||
|
document.positions = await resp.json();
|
||||||
|
yikes();
|
||||||
|
} else {
|
||||||
|
error(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function calcSums(){
|
function calcSums(){
|
||||||
let data = {}
|
let data = {}
|
||||||
@@ -69,6 +82,12 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<legend>
|
||||||
|
{t('positions')}
|
||||||
|
{#if editable}
|
||||||
|
<button onclick={() => position_select = true}>{t('add_object',{object:t('position')})}</button>
|
||||||
|
{/if}
|
||||||
|
</legend>
|
||||||
{#if document.positions}
|
{#if document.positions}
|
||||||
<table class="positions">
|
<table class="positions">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -98,3 +117,6 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if position_select}
|
||||||
|
<PositionSelector close={() => position_select=false} doc={document} onSelect={addPosition} />
|
||||||
|
{/if}
|
||||||
@@ -13,13 +13,8 @@
|
|||||||
|
|
||||||
let source = $state(0);
|
let source = $state(0);
|
||||||
|
|
||||||
function select(position){
|
|
||||||
close();
|
|
||||||
onSelect(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
function estimateSelected(estimate){
|
function estimateSelected(estimate){
|
||||||
select({
|
onSelect({
|
||||||
item_code : t('estimated_time'),
|
item_code : t('estimated_time'),
|
||||||
title : estimate.name,
|
title : estimate.name,
|
||||||
description : estimate.description.source,
|
description : estimate.description.source,
|
||||||
@@ -56,11 +51,11 @@
|
|||||||
};
|
};
|
||||||
if (tax) data['tax'] = tax;
|
if (tax) data['tax'] = tax;
|
||||||
|
|
||||||
select(data);
|
onSelect(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function timeSelected(time){
|
function timeSelected(time){
|
||||||
select({
|
onSelect({
|
||||||
item_code : t('timetrack'),
|
item_code : t('timetrack'),
|
||||||
title : time.subject,
|
title : time.subject,
|
||||||
description : time.description.source,
|
description : time.description.source,
|
||||||
@@ -100,6 +95,7 @@
|
|||||||
{:else if source == 1}
|
{:else if source == 1}
|
||||||
<EstimateList company_id={doc.company.id} onSelect={estimateSelected} />
|
<EstimateList company_id={doc.company.id} onSelect={estimateSelected} />
|
||||||
{:else}
|
{:else}
|
||||||
<TimeList company_id={doc.company.id} onSelect={timeSelected} />
|
<TimeList company_id={doc.company.id} hide={doc.positions} onSelect={timeSelected} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
<pre>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
import { api, target } from '../../urls.svelte.js';
|
import { api, post, target } 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';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
company_id,
|
company_id,
|
||||||
|
hide = {},
|
||||||
onSelect = (time) => {}
|
onSelect = (time) => {}
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
@@ -16,11 +17,7 @@
|
|||||||
async function loadProjects(){
|
async function loadProjects(){
|
||||||
const url = api('project/list');
|
const url = api('project/list');
|
||||||
let data = { company_id: company_id };
|
let data = { company_id: company_id };
|
||||||
const resp = await fetch(url,{
|
const resp = await post(url,data);
|
||||||
credentials : 'include',
|
|
||||||
method : 'POST',
|
|
||||||
body : JSON.stringify(data)
|
|
||||||
});
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
projects = await resp.json();
|
projects = await resp.json();
|
||||||
yikes();
|
yikes();
|
||||||
@@ -29,19 +26,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filter(newTimes, excluded_ids){
|
||||||
|
times = newTimes.filter(time => !excluded_ids.includes(time.id));
|
||||||
|
}
|
||||||
|
|
||||||
async function loadTimes(projectId){
|
async function loadTimes(projectId){
|
||||||
const url = api('time/list');
|
const url = api('time/list');
|
||||||
let data = { company_id: company_id, project_id: projectId };
|
let data = { company_id: company_id, project_id: projectId };
|
||||||
const resp = await fetch(url,{
|
const resp = await post(url,data);
|
||||||
credentials : 'include',
|
|
||||||
method : 'POST',
|
|
||||||
body : JSON.stringify(data)
|
|
||||||
});
|
|
||||||
if (resp.ok){
|
if (resp.ok){
|
||||||
times = await resp.json();
|
yikes();
|
||||||
} else {
|
let newTimes = await resp.json();
|
||||||
error(resp);
|
let present_times = Object.values(hide).filter(pos => pos.time_id).map(pos => pos.time_id)
|
||||||
}
|
filter(newTimes,present_times);
|
||||||
|
} else error(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function select(time){
|
||||||
|
filter(times,[time.id]);
|
||||||
|
onSelect(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(loadProjects);
|
onMount(loadProjects);
|
||||||
@@ -56,12 +59,13 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if times}
|
{#if times}
|
||||||
{#each times as time,idx2}
|
{#each times as time,idx2}
|
||||||
<div class="time" onclick={() => onSelect(time)}>
|
<div class="time" onclick={() => select(time)}>
|
||||||
<span class="duration">{(time.duration).toFixed(3)} {t('hours')}</span>
|
<span class="duration">{(time.duration).toFixed(3)} {t('hours')}</span>
|
||||||
<span class="subject">{time.subject}</span>
|
<span class="subject">{time.subject}</span>
|
||||||
<span class="start_time">{time.start_time}</span>
|
<span class="start_time">{new Date(time.start_time*1000).toUTCString()}</span>
|
||||||
<span class="description">{@html target(time.description.rendered)}</span>
|
<span class="description">{@html target(time.description.rendered)}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<hr/>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,13 +12,11 @@
|
|||||||
import MultilineEditor from '../../Components/MultilineEditor.svelte';
|
import MultilineEditor from '../../Components/MultilineEditor.svelte';
|
||||||
import Notes from '../notes/RelatedNotes.svelte';
|
import Notes from '../notes/RelatedNotes.svelte';
|
||||||
import PositionList from './PositionList.svelte';
|
import PositionList from './PositionList.svelte';
|
||||||
import PositionSelector from './PositionSelector.svelte';
|
|
||||||
import StateSelector from './StateSelector.svelte';
|
import StateSelector from './StateSelector.svelte';
|
||||||
import Tags from '../tags/TagList.svelte';
|
import Tags from '../tags/TagList.svelte';
|
||||||
import TemplateSelector from './TemplateSelector.svelte';
|
import TemplateSelector from './TemplateSelector.svelte';
|
||||||
import TypeSelector from './TypeSelector.svelte';
|
import TypeSelector from './TypeSelector.svelte';
|
||||||
|
|
||||||
|
|
||||||
let doc = $state(null);
|
let doc = $state(null);
|
||||||
let editable = $derived(doc.state == 1);
|
let editable = $derived(doc.state == 1);
|
||||||
let { id } = $props();
|
let { id } = $props();
|
||||||
@@ -27,16 +25,7 @@
|
|||||||
const router = useTinyRouter();
|
const router = useTinyRouter();
|
||||||
let sndDisabled = $state(false);
|
let sndDisabled = $state(false);
|
||||||
|
|
||||||
async function addPosition(selected){
|
|
||||||
const url = api(`document/${doc.id}/position`);
|
|
||||||
const resp = await post(url,selected);
|
|
||||||
if (resp.ok){
|
|
||||||
doc.positions = await resp.json();
|
|
||||||
yikes();
|
|
||||||
} else {
|
|
||||||
error(resp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function changeState(newVal){
|
async function changeState(newVal){
|
||||||
let success = false;
|
let success = false;
|
||||||
@@ -234,12 +223,7 @@
|
|||||||
<MarkdownEditor bind:value={doc.head} editable={editable} onSet={(val) => update('head',val)} />
|
<MarkdownEditor bind:value={doc.head} editable={editable} onSet={(val) => update('head',val)} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>
|
|
||||||
{t('positions')}
|
|
||||||
{#if editable}
|
|
||||||
<button onclick={() => position_select = true}>{t('add_object',{object:t('position')})}</button>
|
|
||||||
{/if}
|
|
||||||
</legend>
|
|
||||||
<PositionList bind:document={doc} submit={update} />
|
<PositionList bind:document={doc} submit={update} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@@ -262,6 +246,3 @@
|
|||||||
<Notes module="document" entity_id={id} />
|
<Notes module="document" entity_id={id} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if position_select}
|
|
||||||
<PositionSelector close={() => position_select=false} {doc} onSelect={addPosition} />
|
|
||||||
{/if}
|
|
||||||
|
|||||||
@@ -76,11 +76,9 @@
|
|||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{t('ID')}</td>
|
<td>
|
||||||
<td>{item.id}</td>
|
{t('ID')}
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
|
||||||
<td>{t('Code')}:</td>
|
|
||||||
<td>
|
<td>
|
||||||
<LineEditor type="span" editable={true} value={item.code} onSet={v => update('code',v)} />
|
<LineEditor type="span" editable={true} value={item.code} onSet={v => update('code',v)} />
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -88,8 +88,8 @@
|
|||||||
function onclick(evt) {
|
function onclick(evt) {
|
||||||
ignore(evt);
|
ignore(evt);
|
||||||
let task = getTask(evt);
|
let task = getTask(evt);
|
||||||
if (task.status <= 20) { // open
|
if (task.status == 20) { // open
|
||||||
update(task,60);
|
update(task,10);
|
||||||
} else update(task,20);
|
} else update(task,20);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
<legend>{t('state_complete')}</legend>
|
<legend>{t('state_complete')}</legend>
|
||||||
{#if sorted}
|
{#if sorted}
|
||||||
{#each sorted as task}
|
{#each sorted as task}
|
||||||
{#if task.status > 20 && match(task)}
|
{#if task.status < 20 && match(task)}
|
||||||
<div href={`/task/${task.id}/view`} title={task.description.source} task_id={task.id} {onclick} {oncontextmenu} {ontouchstart} {ontouchend} onmousedown={ontouchstart} onmouseup={ontouchend} >
|
<div href={`/task/${task.id}/view`} title={task.description.source} task_id={task.id} {onclick} {oncontextmenu} {ontouchstart} {ontouchend} onmousedown={ontouchstart} onmouseup={ontouchend} >
|
||||||
{task.name}
|
{task.name}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
84
legacy/src/main/resources/css/default/colors.css
Normal file
84
legacy/src/main/resources/css/default/colors.css
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
body{
|
||||||
|
color: orange;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tasks .pending>a{
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.completed>a,
|
||||||
|
.started>a{
|
||||||
|
color: #5bc500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canceled>a{
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr{
|
||||||
|
background-color: #52525270;
|
||||||
|
}
|
||||||
|
tr:nth-child(2n+1){
|
||||||
|
background-color: #a7a7a740;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button,
|
||||||
|
input,
|
||||||
|
button {
|
||||||
|
background-color: orange;
|
||||||
|
color: #303030;
|
||||||
|
}
|
||||||
|
.hover{
|
||||||
|
background-color: black;
|
||||||
|
border-color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.invoice textarea {
|
||||||
|
background-color: orange;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infos span{
|
||||||
|
background-color: #00ad00;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.errors span{
|
||||||
|
background-color: #ff9847;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warnings span{
|
||||||
|
background-color: #ffff00;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#announce{
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main_menu .button:hover {
|
||||||
|
color: orange;
|
||||||
|
background-color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:hover td{
|
||||||
|
background-color: #160202;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background-color: black;
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description img,
|
||||||
|
#preview img{
|
||||||
|
background: lightcyan;
|
||||||
|
}
|
||||||
584
legacy/src/main/resources/css/default/style.css
Normal file
584
legacy/src/main/resources/css/default/style.css
Normal file
@@ -0,0 +1,584 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "awesome";
|
||||||
|
src: url("../fontawesome-webfont.woff");
|
||||||
|
}
|
||||||
|
*{
|
||||||
|
max-width:100%;
|
||||||
|
min-width:auto;
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
body{
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
min-height: 60px;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:hover{
|
||||||
|
min-height: 400px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text],input[type=email]{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.connectors form input{
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img#logo{
|
||||||
|
position: fixed;
|
||||||
|
top: 10px;
|
||||||
|
right: 10px;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
#main_menu,
|
||||||
|
#main_menu form{
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main_menu .button {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-top: 7px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden{
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover:hover .hidden{
|
||||||
|
display: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emphasized{
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add_positions,
|
||||||
|
.requirements{
|
||||||
|
max-height: 60px;
|
||||||
|
max-width: 66%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.add_positions:hover,
|
||||||
|
.requirements:hover{
|
||||||
|
max-height: 999999px;
|
||||||
|
max-width: 999999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add_positions > ul > li{
|
||||||
|
max-height: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add_positions > ul > li:hover{
|
||||||
|
max-height: 999999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.add.document:hover {
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.add.document {
|
||||||
|
max-height: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.options label,
|
||||||
|
.add_positions label span,
|
||||||
|
.poll_status label,
|
||||||
|
.requirements label{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tasks .canceled a,
|
||||||
|
.children .inactive,
|
||||||
|
.requirements .inactive,
|
||||||
|
.tasks .inactive{
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tasks .navi a{
|
||||||
|
display: inline-table;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote a,
|
||||||
|
p a,
|
||||||
|
.description a{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
tr > *{
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.street:after,
|
||||||
|
label.location::after {
|
||||||
|
content: "\a ";
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll.evaluate table tr:nth-child(n+2) th,
|
||||||
|
.poll.evaluate table td{
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll .disabled{
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company div > fieldset,
|
||||||
|
.company > table{
|
||||||
|
margin-right: 10px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.time h2{
|
||||||
|
margin-right: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file label,
|
||||||
|
.document .dates label{
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
.document .header,
|
||||||
|
.document .tags{
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border-radius: 10px;
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contacts fieldset,
|
||||||
|
.document .customer,
|
||||||
|
.document .document_type,
|
||||||
|
.document .sender,
|
||||||
|
.document .court,
|
||||||
|
.document .dates,
|
||||||
|
.document .template,
|
||||||
|
fieldset.del_note,
|
||||||
|
fieldset.login_service_list,
|
||||||
|
fieldset.userlist,
|
||||||
|
fieldset.document.list{
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.document .dates label{
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button,
|
||||||
|
input,
|
||||||
|
button {
|
||||||
|
border: 0 none;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 2px;
|
||||||
|
padding: 3px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change_state,
|
||||||
|
td.connectors button[type="submit"],
|
||||||
|
.prop_action,
|
||||||
|
input[type="submit"] {
|
||||||
|
clear: both;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.symbol{
|
||||||
|
font-family: awesome;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main_menu .symbol{
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right{
|
||||||
|
float: right;
|
||||||
|
margin: 0 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tasks .project {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-abs {
|
||||||
|
position: absolute;
|
||||||
|
right: 5px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
.right-fix {
|
||||||
|
position: fixed;
|
||||||
|
right: 5px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
.hover {
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 5px;
|
||||||
|
max-height: 35px;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.hover:hover {
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover_h > a:nth-child(n+2){
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover_h:hover {
|
||||||
|
padding: 5px 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover_h:hover > a:nth-child(n+2){
|
||||||
|
display: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.document textarea {
|
||||||
|
font-weight: bold;
|
||||||
|
min-height: 90px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pos_price,
|
||||||
|
form.document input.price,
|
||||||
|
form.document input.amount{
|
||||||
|
max-width: 60px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.document .tax{
|
||||||
|
min-width: 70px;
|
||||||
|
}
|
||||||
|
form.document .tax input{
|
||||||
|
max-width: 40px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
td > h1{
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center,
|
||||||
|
.infos,
|
||||||
|
.errors,
|
||||||
|
.warnings{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infos span,
|
||||||
|
.errors span,
|
||||||
|
.warnings span{
|
||||||
|
margin: 5px 0 0;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags span{
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.bookmark .share,
|
||||||
|
.bookmark .tags{
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmark form .share{
|
||||||
|
height: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmark form .share:hover{
|
||||||
|
height: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.bookmark > fieldset{
|
||||||
|
max-height: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.bookmark > fieldset.tags{
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.bookmark > fieldset:hover{
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
.bookmark>fieldset>a{
|
||||||
|
word-wrap: break-word;
|
||||||
|
display: block;
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmark>fieldset>a.button{
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copytext{
|
||||||
|
position:fixed;
|
||||||
|
width: 100px;
|
||||||
|
left: -1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[src*="pos=right"] {
|
||||||
|
float:right;
|
||||||
|
margin: 5px 0 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[src*="pos=left"] {
|
||||||
|
float:left;
|
||||||
|
margin: 5px 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[src*="width=100"]{
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
img[src*="width=200"]{
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
img[src*="width=300"]{
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
img[src*="width=400"]{
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
img[src*="width=500"]{
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
img[src*="width=600"]{
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
img[src*="width=700"]{
|
||||||
|
max-width: 700px;
|
||||||
|
}
|
||||||
|
img[src*="width=800"]{
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
img[src*="width=900"]{
|
||||||
|
max-width: 900px;
|
||||||
|
}
|
||||||
|
img[src*="width=50%"]{
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[src*="width=33%"]{
|
||||||
|
max-width: 33%;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[src$="width=25%"]{
|
||||||
|
max-width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#announce{
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 3px 5px 0;
|
||||||
|
border-top-left-radius: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset.scrolling{
|
||||||
|
overflow: scroll;
|
||||||
|
max-height: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg#gantt{
|
||||||
|
max-width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .row{
|
||||||
|
fill: none;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .row:hover{
|
||||||
|
fill: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .duration{
|
||||||
|
fill:rgba(255,0,255,0.4);
|
||||||
|
stroke:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .schedule{
|
||||||
|
fill:none;
|
||||||
|
stroke-width:1;
|
||||||
|
stroke: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .start{
|
||||||
|
stroke-dasharray: 10,30,40;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .stop{
|
||||||
|
stroke-dasharray: 50,30;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg text{
|
||||||
|
stroke: none;
|
||||||
|
fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.search{
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.search input,
|
||||||
|
div.search label{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.search:hover input,
|
||||||
|
div.search:hover label{
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note td.code {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note td.code textarea {
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-index td .users{
|
||||||
|
max-height: 30px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-index tr:hover td .users{
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.easylist fieldset a.button {
|
||||||
|
width: 80%;
|
||||||
|
padding: 30px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#preview,
|
||||||
|
#preview-source{
|
||||||
|
display: inline-block;
|
||||||
|
max-width: calc(50% - 20px);
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
table #preview,
|
||||||
|
table #preview-source{
|
||||||
|
display: inherit;
|
||||||
|
max-width: unset;
|
||||||
|
vertical-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#preview.loading{
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.completed > a::before {
|
||||||
|
content: " ✓";
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width:1199px) {
|
||||||
|
*[hide="12"]{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
table.document input{
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px){
|
||||||
|
*[hide="9"]{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
table.document input{
|
||||||
|
max-width: 60px;
|
||||||
|
}
|
||||||
|
table.document .tax input,
|
||||||
|
table.document input.amount{
|
||||||
|
max-width: 25px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 800px){
|
||||||
|
*[hide="8"]{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px){
|
||||||
|
*[hide="7"]{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
fieldset.bookmark > fieldset{
|
||||||
|
max-height: 50px;
|
||||||
|
}
|
||||||
|
#preview,
|
||||||
|
#preview-source{
|
||||||
|
display: block;
|
||||||
|
max-width: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px){
|
||||||
|
*[hide="6"]{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.easylist fieldset a.button {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width: 500px){
|
||||||
|
*[hide="5"]{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width: 400px){
|
||||||
|
*[hide="4"]{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media print{
|
||||||
|
fieldset.note span.right,
|
||||||
|
#logo, #main_menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
fieldset.process, fieldset.database{
|
||||||
|
page-break-after: always;
|
||||||
|
}
|
||||||
|
.export>fieldset{
|
||||||
|
border: 0 none;
|
||||||
|
}
|
||||||
|
}
|
||||||
41
legacy/src/main/resources/css/default/svg_colors.css
Normal file
41
legacy/src/main/resources/css/default/svg_colors.css
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
.arrow{
|
||||||
|
stroke: orange;
|
||||||
|
}
|
||||||
|
circle, ellipse, rect{
|
||||||
|
stroke: black;
|
||||||
|
}
|
||||||
|
ellipse,
|
||||||
|
circle.process{
|
||||||
|
fill: rgba(255,255,255,0.5);
|
||||||
|
}
|
||||||
|
rect.terminal{
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
circle.connector{
|
||||||
|
fill: rgba(0,0,0,0.05);
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
circle.connector:hover{
|
||||||
|
fill: rgba(0,0,0,0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#backdrop{
|
||||||
|
fill: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow circle{
|
||||||
|
stroke: none;
|
||||||
|
fill: rgba(128,128,128,0.5);
|
||||||
|
}
|
||||||
|
.arrow text{
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow:hover circle{
|
||||||
|
fill: rgba(255,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.process text{
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
@@ -12,9 +12,18 @@ public class Constants {
|
|||||||
public static final String CONFIG_SMTP_USER = "umbrella.modules.message.smtp.user";
|
public static final String CONFIG_SMTP_USER = "umbrella.modules.message.smtp.user";
|
||||||
|
|
||||||
public static final String DEBUG_ADDREESS = "umbrella.modules.message.debug_address";
|
public static final String DEBUG_ADDREESS = "umbrella.modules.message.debug_address";
|
||||||
|
|
||||||
public static final String ENVELOPE_FROM = "mail.smtp.from";
|
public static final String ENVELOPE_FROM = "mail.smtp.from";
|
||||||
public static final String PORT = "mail.smtp.port";
|
|
||||||
|
public static final String SMTP_AUTH = "mail.smtp.auth";
|
||||||
|
public static final String SMTP_HOST = "mail.smtp.host";
|
||||||
|
public static final String SMTP_FROM = "mail.smtp.from";
|
||||||
|
public static final String SMTP_PORT = "mail.smtp.port";
|
||||||
|
public static final String SMTP_SSL = "mail.smtp.ssl.enable";
|
||||||
public static final String SSL = "mail.smtp.ssl.enable";
|
public static final String SSL = "mail.smtp.ssl.enable";
|
||||||
|
public static final String SUBMISSION = "submission";
|
||||||
|
|
||||||
|
public static final String PORT = "mail.smtp.port";
|
||||||
|
|
||||||
public static final String TABLE_ATTACHMENTS = "attachments";
|
public static final String TABLE_ATTACHMENTS = "attachments";
|
||||||
public static final String TABLE_MESSAGES = "messages";
|
public static final String TABLE_MESSAGES = "messages";
|
||||||
|
|||||||
@@ -93,10 +93,10 @@ public class MessageSystem extends BaseHandler implements PostBox, EventListener
|
|||||||
|
|
||||||
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();
|
||||||
@@ -326,11 +326,11 @@ public class MessageSystem extends BaseHandler implements PostBox, EventListener
|
|||||||
private Session session() {
|
private Session session() {
|
||||||
if (session == null){
|
if (session == null){
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.put(HOST, host);
|
props.put(SMTP_HOST, host);
|
||||||
props.put(PORT, port);
|
props.put(SMTP_PORT, port);
|
||||||
props.put(AUTH, true);
|
props.put(SMTP_AUTH, true);
|
||||||
props.put(SSL, true);
|
props.put(SMTP_SSL, true);
|
||||||
props.put(ENVELOPE_FROM,from);
|
props.put(SMTP_FROM,from);
|
||||||
session = Session.getInstance(props);
|
session = Session.getInstance(props);
|
||||||
}
|
}
|
||||||
return session;
|
return session;
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ public class CombinedMessage {
|
|||||||
public CombinedMessage(Translatable subjectForCombinedMessage, User receiver, User fallbackSender){
|
public CombinedMessage(Translatable subjectForCombinedMessage, User receiver, User fallbackSender){
|
||||||
LOG.log(DEBUG,"Creating combined message for {0}…",receiver);
|
LOG.log(DEBUG,"Creating combined message for {0}…",receiver);
|
||||||
this.subjectForCombinedMessage = subjectForCombinedMessage;
|
this.subjectForCombinedMessage = subjectForCombinedMessage;
|
||||||
this.fallbackSender = fallbackSender;
|
|
||||||
this.receiver = receiver;
|
this.receiver = receiver;
|
||||||
this.lang = receiver.language();
|
this.lang = receiver.language();
|
||||||
|
this.fallbackSender = fallbackSender;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addNote() {
|
public void addNote() {
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import static de.srsoftware.umbrella.core.constants.Field.PERMISSION;
|
|||||||
import static de.srsoftware.umbrella.core.constants.Field.SETTINGS;
|
import static de.srsoftware.umbrella.core.constants.Field.SETTINGS;
|
||||||
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.PROJECT;
|
import static de.srsoftware.umbrella.core.constants.Module.PROJECT;
|
||||||
import static de.srsoftware.umbrella.core.constants.Path.LIST;
|
import static de.srsoftware.umbrella.core.constants.Path.*;
|
||||||
import static de.srsoftware.umbrella.core.constants.Path.SEARCH;
|
|
||||||
import static de.srsoftware.umbrella.core.constants.Text.*;
|
import static de.srsoftware.umbrella.core.constants.Text.*;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
import static de.srsoftware.umbrella.core.model.Permission.*;
|
import static de.srsoftware.umbrella.core.model.Permission.*;
|
||||||
|
|||||||
@@ -226,7 +226,8 @@ public class StockModule extends BaseHandler implements StockService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean getChildLocations(UmbrellaUser user, long parentId, HttpExchange ex) throws IOException {
|
private boolean getChildLocations(UmbrellaUser user, long parentId, HttpExchange ex) throws IOException {
|
||||||
LOG.log(WARNING,"No security check implemented for {0}.getChildLocations(user, parentId, ex)!",getClass().getSimpleName()); // TODO check, that user is allowed to request that location
|
var owner = stockDb.loadLocation(parentId).owner();
|
||||||
|
if (!assigned(owner,user)) throw forbidden("You are not allowed to access items of {owner}", OWNER,owner);
|
||||||
return sendContent(ex, stockDb.listChildLocations(parentId).stream().sorted(comparing(l -> l.name().toLowerCase())).map(DbLocation::toMap));
|
return sendContent(ex, stockDb.listChildLocations(parentId).stream().sorted(comparing(l -> l.name().toLowerCase())).map(DbLocation::toMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,17 +289,19 @@ public class StockModule extends BaseHandler implements StockService {
|
|||||||
Field.LOCATIONS,userLocations.stream().map(DbLocation::toMap).toList()));
|
Field.LOCATIONS,userLocations.stream().map(DbLocation::toMap).toList()));
|
||||||
|
|
||||||
var companies = companyService().listCompaniesOf(user);
|
var companies = companyService().listCompaniesOf(user);
|
||||||
companies.values().stream().sorted(comparing(a -> a.name().toLowerCase())).forEach(company -> {
|
companies.values().stream().sorted(comparing(a -> a.name().toLowerCase()))
|
||||||
var locations = stockDb.listCompanyLocations(company);
|
.map(company -> Map.of(
|
||||||
result.add(Map.of(
|
PARENT, Map.of(Field.COMPANY, company.id()),
|
||||||
PARENT, Map.of(Field.COMPANY, company.id()),
|
NAME,company.name(),
|
||||||
NAME,company.name(),
|
Field.LOCATIONS,getCompanyLocations(company).stream().sorted(comparing(a -> a.name().toLowerCase())).map(DbLocation::toMap).toList()))
|
||||||
Field.LOCATIONS,locations.stream().sorted(comparing(a -> a.name().toLowerCase())).map(DbLocation::toMap).toList()));
|
.forEach(result::add);
|
||||||
|
|
||||||
});
|
|
||||||
return sendContent(ex, result);
|
return sendContent(ex, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<DbLocation> getCompanyLocations(Company company){
|
||||||
|
return stockDb.listCompanyLocations(company);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DbLocation loadLocation(long locationId) {
|
public DbLocation loadLocation(long locationId) {
|
||||||
return stockDb.loadLocation(locationId);
|
return stockDb.loadLocation(locationId);
|
||||||
@@ -465,8 +468,7 @@ public class StockModule extends BaseHandler implements StockService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Object> redefineMe(long company_id) {
|
public Collection<Item> getCompanyItems(long companyID) {
|
||||||
// TODO
|
return stockDb.listItemsOf(companyService().get(companyID));
|
||||||
return List.of();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user