Compare commits

...

10 Commits

Author SHA1 Message Date
1059164b4a bugfix:
All checks were successful
Build Docker Image / Docker-Build (push) Successful in 2m36s
Build Docker Image / Clean-Registry (push) Successful in 0s
markdown rendering glitched when several @startuml…@enduml sections were present in one document

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-22 20:46:43 +01:00
f438bea4cc Merge branch 'bugfix/plantuml'
All checks were successful
Build Docker Image / Docker-Build (push) Successful in 2m25s
Build Docker Image / Clean-Registry (push) Successful in 0s
2026-01-20 23:14:46 +01:00
9394ca597c fixed another bug
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-20 22:52:30 +01:00
53fe79fbbd fixed image heights when scaling width
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-20 22:44:30 +01:00
d62534b3eb fixed plantuml permissions
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-20 22:20:17 +01:00
18e8e3ffd1 removed obsolete warning
All checks were successful
Build Docker Image / Docker-Build (push) Successful in 2m32s
Build Docker Image / Clean-Registry (push) Successful in 0s
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-19 22:29:57 +01:00
ae55a76ca7 Merge branch 'feature/translation' 2026-01-16 17:07:25 +01:00
cf485055a6 improved file module GUI: now pushing a notification when markdown was copied
All checks were successful
Build Docker Image / Docker-Build (push) Successful in 2m31s
Build Docker Image / Clean-Registry (push) Successful in 1s
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-16 15:48:56 +01:00
968e5bfb95 improved file module GUI: files and directories are now sorted
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-16 09:25:32 +01:00
6de5f1f660 working on translations
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
2026-01-15 22:51:23 +01:00
18 changed files with 311 additions and 230 deletions

View File

@@ -22,8 +22,9 @@ 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
USER 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
CMD java -jar jar/backend.jar

View File

@@ -35,7 +35,7 @@ import org.json.JSONObject;
public class Util {
public static final System.Logger LOG = System.getLogger("Util");
private static final Pattern UML_PATTERN = Pattern.compile("@start(\\w+)(.*)@end(\\1)",Pattern.DOTALL);
private static final Pattern UML_PATTERN = Pattern.compile("@start(\\w+)(.*?)@end(\\1)",Pattern.DOTALL);
private static File plantumlJar = null;
private static final JParsedown MARKDOWN = new JParsedown();
public static final String SHA1 = "SHA-1";
@@ -79,7 +79,7 @@ public class Util {
try {
if (plantumlJar != null && plantumlJar.exists()) {
var matcher = UML_PATTERN.matcher(source);
if (matcher.find()) {
while (matcher.find()) {
var uml = matcher.group(0).trim();
var start = matcher.start(0);
var end = matcher.end(0);
@@ -96,6 +96,7 @@ public class Util {
byte[] out = is.readAllBytes();
var svg = new String(out, UTF_8);
source = source.substring(0, start) + svg + source.substring(end);
matcher = UML_PATTERN.matcher(source);
}
}
}

View File

@@ -31,19 +31,16 @@ public class Path {
public static final String REDIRECT = "redirect";
public static final String SEARCH = "search";
public static final String SERVICE = "service";
public static final String SETTINGS = "settings";
public static final String STATES = "states";
public static final String STARTED = "started";
public static final String STATE = "state";
public static final String STOP = "stop";
public static final String SUBMIT = "submit";
public static final String TAGGED = "tagged";
public static final String TOKEN = "token";
public static final String USER = "user";
public static final String USES = "uses";
public static final String VIEW = "view";
}

View File

@@ -5,8 +5,9 @@ package de.srsoftware.umbrella.core.constants;
* This is a collection of messages that appear throughout the project
*/
public class Text {
public static final String BOOLEAN = "Boolean";
public static final String BOOKMARK = "bookmark";
public static final String BOOLEAN = "Boolean";
public static final String COMPANIES = "companies";
public static final String COMPANY = "company";
public static final String COMPANY_WITH_ID = "company ({id})";
@@ -15,41 +16,51 @@ public class Text {
public static final String CONTACT_WITH_ID = "contact ({id})";
public static final String CUSTOMER = "customer";
public static final String CUSTOMER_SETTINGS = "customer settings";
public static final String DOCUMENT = "document";
public static final String DOCUMENTS = "documents";
public static final String DOCUMENT_TYPE_ID = "document type id";
public static final String DOCUMENT_WITH_ID = "document ({id})";
public static final String INVALID_DB_CODE = "Encountered invalid dbCode: {code}";
public static final String ITEM = "item";
public static final String ITEMS = "items";
public static final String LOCATION = "location";
public static final String LOCATIONS = "locations";
public static final String LOGIN_SERVICE = "login service";
public static final String LONG = "Long";
public static final String NOTE = "note";
public static final String NOTE_WITH_ID = "note ({id})";
public static final String NUMBER = "number";
public static final String PATH = "path";
public static final String PROJECT = "project";
public static final String PROPERTIES = "properties";
public static final String PROJECT_WITH_ID = "project ({id})";
public static final String PROPERTIES = "properties";
public static final String PROPERTY = "property";
public static final String SENDER = "sender";
public static final String SESSION = "session";
public static final String SERVICE_WITH_ID = "service ({id})";
public static final String SESSION = "session";
public static final String SETTINGS = "settings";
public static final String STRING = "string";
public static final String TABLE_WITH_NAME = "table {name}";
public static final String TAGS = "tags";
public static final String TASK = "task";
public static final String TASKS = "tasks";
public static final String TIME_WITH_ID = "time ({id})";
public static final String TYPE = "type";
public static final String UNIT = "unit";
public static final String USER_WITH_ID = "user ({id})";
public static final String WIKI_PAGE = "wiki page";
public static final String WIKI_PAGES = "wiki pages";
public static final String UNIT = "unit";
public static final String T_UNIT_PRICE = "unit price";
public static final String UNIT_PRICE = "unit price";
public static final String USER = "user";
public static final String USERS = "users";

View File

@@ -24,6 +24,7 @@ import static de.srsoftware.umbrella.core.constants.Field.SENDER;
import static de.srsoftware.umbrella.core.constants.Field.STATE;
import static de.srsoftware.umbrella.core.constants.Field.TYPE;
import static de.srsoftware.umbrella.core.constants.Field.UNIT;
import static de.srsoftware.umbrella.core.constants.Field.UNIT_PRICE;
import static de.srsoftware.umbrella.core.constants.Field.USER;
import static de.srsoftware.umbrella.core.constants.Path.*;
import static de.srsoftware.umbrella.core.constants.Text.*;

View File

@@ -15,6 +15,7 @@ import static de.srsoftware.umbrella.core.constants.Field.NUMBER;
import static de.srsoftware.umbrella.core.constants.Field.SENDER;
import static de.srsoftware.umbrella.core.constants.Field.TYPE;
import static de.srsoftware.umbrella.core.constants.Field.UNIT;
import static de.srsoftware.umbrella.core.constants.Field.UNIT_PRICE;
import static de.srsoftware.umbrella.core.constants.Text.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
import static de.srsoftware.umbrella.core.model.Document.DEFAULT_THOUSANDS_SEPARATOR;

View File

@@ -2,13 +2,14 @@
import { onMount } from 'svelte';
import { useTinyRouter } from 'svelte-tiny-router';
import { api } from '../../urls.svelte';
import { error, yikes } from '../../warn.svelte';
import { error, warn, yikes } from '../../warn.svelte';
import { t } from '../../translations.svelte';
import { user } from '../../user.svelte';
const image_extensions = ['jpg','jpeg','gif','png','svg','webp'];
const router = useTinyRouter();
let children = $state({});
let new_dir = $state(null);
let files = $state();
let parent = $state(false);
@@ -17,23 +18,6 @@
let delete_allowed = $state(false);
let available = $derived.by(isAvailable);
function isAvailable(){
if (!new_dir) return false;
if (children){
if (children.dirs) {
for (let key of Object.values(children.dirs)){
if (key == new_dir) return false;
}
}
if (children.files) {
for (let key of Object.values(children.files)){
if (key == new_dir) return false;
}
}
}
return true;
}
async function create_dir(ev){
ev.preventDefault();
ev.stopPropagation();
@@ -74,13 +58,30 @@
async function handleDirectory(res){
let json = await res.json();
children.dirs = json.dirs ? json.dirs : {};
children.files = json.files ? json.files : {};
children.dirs = json.dirs ? val_sort(json.dirs) : {};
children.files = json.files ? val_sort(json.files) : {};
children.title = json.title ? json.title : path;
delete_allowed = json.delete;
yikes();
}
function isAvailable(){
if (!new_dir) return false;
if (children){
if (children.dirs) {
for (let key of Object.values(children.dirs)){
if (key == new_dir) return false;
}
}
if (children.files) {
for (let key of Object.values(children.files)){
if (key == new_dir) return false;
}
}
}
return true;
}
function is_image(file){
let parts = file.toLowerCase().split('.');
let ext = parts.pop();
@@ -90,12 +91,15 @@
async function loadChildren(p){
p = p.substring(6);
if (p == '') p = '/';
children = { dirs : {}, files : {}, title : p};
children = { dirs : [], files : [], title : p};
path = p;
if (p == '/'){
children.dirs[`/user/${user.id}`] = t('my_files');
children.dirs['/project'] = t('projects')
children.dirs['/company'] = t('companies');
children.dirs = [
{ path : `/user/${user.id}`, name : t('my files') },
{ path : '/project', name : t('projects')},
{ path : '/company', name : t('companies')},
]
parent = false;
form = false;
} else {
@@ -114,8 +118,12 @@
function markdown(file){
let parts = file.split('/');
let md = `![${parts.pop()}](/api/files${file})`;
let path = `/api/files${file}`;
path = encodeURI(path);
let md = `![${parts.pop()}](${path})`;
navigator.clipboard.writeText(md);
warn(t('Markdown has been copied to clipboard!'));
setTimeout(yikes, 2500);
}
function onclick(ev){
@@ -153,6 +161,12 @@
return false;
}
function val_sort(map){
return Object.entries(map)
.map(item => ({name:item[1],path:item[0]}))
.sort((a,b) => a.name.localeCompare(b.name));
}
onMount(() => loadChildren(window.location.pathname));
</script>
@@ -166,12 +180,12 @@
</li>
{/if}
{#if children?.dirs}
{#each Object.entries(children.dirs) as [k,v]}
{#each children.dirs as dir}
<li class="dir">
<span class="symbol"></span>
<a href={'/files'+k} {onclick}>{v}</a>
<a href={'/files'+dir.path} {onclick}>{dir.name}</a>
{#if delete_allowed}
<button class="symbol" onclick={e => dropDir(`/api/files${k}`,v)}></button>
<button class="symbol" onclick={e => dropDir(`/api/files${dir.path}`,dir.name)}></button>
{/if}
</li>
{/each}
@@ -186,15 +200,15 @@
</li>
{/if}
{#if children.files}
{#each Object.entries(children.files) as [k,v]}
{#each children.files as file}
<li class="file">
<span class="symbol"></span>
<a href={`/api/files${k}`} target="_blank">{v}</a>
{#if is_image(k)}
<button class="symbol" title={'markdown_code'} onclick={e => markdown(k)}></button>
<a href={`/api/files${file.path}`} target="_blank">{file.name}</a>
{#if is_image(file.path)}
<button class="symbol" title={'markdown_code'} onclick={e => markdown(file.path)}></button>
{/if}
{#if delete_allowed}
<button class="symbol" title={t('delete_object',{'object':t('file')})} onclick={e => dropFile(`/api/files${k}`,v)}></button>
<button class="symbol" title={t('delete_object',{'object':t('file')})} onclick={e => dropFile(`/api/files${file.path}`,file.name)}></button>
{/if}
</li>
{/each}

View File

@@ -15,5 +15,5 @@ export async function warn(msg){
export function yikes(){
messages.error = null;
messages.warn = null;
messages.warning = null;
}

View File

@@ -7,8 +7,8 @@ import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.ModuleRegistry.companyService;
import static de.srsoftware.umbrella.core.ModuleRegistry.translator;
import static de.srsoftware.umbrella.core.constants.Field.*;
import static de.srsoftware.umbrella.core.constants.Text.T_UNIT_PRICE;
import static de.srsoftware.umbrella.core.constants.Text.UNIT;
import static de.srsoftware.umbrella.core.constants.Text.UNIT_PRICE;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.databaseException;
import static de.srsoftware.umbrella.stock.Constants.TABLE_ITEMS;
import static java.lang.System.Logger.Level.DEBUG;
@@ -75,7 +75,7 @@ public class ItemDb {
LOG.log(DEBUG, " using location: {0}",location.resolve().name());
var stockItem = new Item(0,company,0,location,code,name,description);
var props = stockItem.properties();
var keyUnitPrice = translator().translate(lang,T_UNIT_PRICE);
var keyUnitPrice = translator().translate(lang, Text.UNIT_PRICE);
var keyUnit = translator().translate(lang, Text.UNIT);
var keyTax = translator().translate(lang,TAX_RATE);
var keyLegacyId = translator().translate(lang,"legacy_id");

View File

@@ -40,7 +40,6 @@ public class Translations extends PathHandler implements Translator {
}
private JSONObject loadTranslations(String lang) throws IOException {
LOG.log(WARNING,"loadTranslations({0}) not implemented!",lang);
var filename = lang + ".json";
URL url = getClass().getClassLoader().getResource(filename);
if (url == null) return new JSONObject();

View File

@@ -14,6 +14,7 @@
"basic_data": "Basis-Daten",
"bookmark": "Lesezeichen",
"bookmarks": "Lesezeichen",
"Boolean": "Boolean",
"by": "von",
"cancel": "abbrechen",
@@ -30,6 +31,7 @@
"confirm_state": "Status wirklich ändern?",
"companies": "Firmen",
"company": "Firma",
"company ({id})": "Firma ({id})",
"company_optional": "Firma (optional)",
"confirmation": "Bestätigung",
"complete": "abschließen",
@@ -53,6 +55,7 @@
"customer_address": "Adresse",
"customer_email": "Emailadresse des Kunden",
"customer_id": "Kundennummer",
"customer settings": "Kunden-Einstellungen",
"custom_tag_colors": "Nutzerdefinierte Tag-Farben",
"data_sent": "Daten übermittelt",
@@ -72,6 +75,8 @@
"document": "Dokument",
"document_list": "Dokumente",
"documents": "Dokumente",
"document type id": "Dokumenten-Typ-ID",
"document ({id})": "Dokument ({id})",
"do_login" : "anmelden",
"do_open" : "öffnen",
"do_send" : "versenden",
@@ -87,6 +92,7 @@
"edit_service": "Login-Service \"{name}\" bearbeiten",
"email": "E-Mail",
"email_or_username": "Email oder Nutzername",
"Encountered invalid dbCode: {code}": "Ungültiger dbCode aufgetreten: {code}",
"end": "Ende",
"estimated_time": "geschätzte Zeit",
"estimated_times": "geschätzte Zeiten",
@@ -167,12 +173,16 @@
"local_court": "Amtsgericht",
"locality": "Ort",
"location": "Ort",
"locations": "Orte",
"login" : "Anmeldung",
"login service": "Login-Service",
"login_services": "Login-Services",
"logout": "Abmelden",
"logout_user": "{user} abmelden",
"Long": "Ganzzahl",
"markdown_code": "Markdown-Code",
"Markdown has been copied to clipboard!": "Markdown wurde in die Zwischenablage kopiert!",
"markdown_supported": "Markdown & <a target=\"_blank\" href=\"https://plantuml.com\">Plantuml</a> nutzbar!",
"MANAGE_LOGIN_SERVICES": "Login-Services verwalten",
"member": "Mitarbeiter",
@@ -205,6 +215,7 @@
"month": "Monat",
"move_to_top": "nach ganz oben bewegen",
"must_not_be_empty": "darf nicht leer sein",
"my files": "Meine Dateien",
"name": "Name",
"net_price": "Nettopreis",
@@ -218,6 +229,7 @@
"no_project_for_id": "Kein Projekt mit ID {0} gefunden!",
"no_task_for_id": "Keine Aufgabe mit ID {0} gefunden!",
"note": "Notiz",
"note ({id})": "Notiz ({id})",
"notes": "Notizen",
"not_recent_version": "Die ist nicht die neuste Version dieser Seite!",
"number": "Nummer",
@@ -230,6 +242,7 @@
"page": "Seite",
"parent_task": "übergeordnete Aufgabe",
"password" : "Passwort",
"path": "Pfad",
"permission": {
"EDIT": "lesen/schreiben",
"OWNER": "Besitzer"
@@ -250,7 +263,10 @@
"priority": "Priorität",
"processing_code": "Code wird verarbeitet…",
"project": "Projekt",
"project ({id})": "Projekt ({id})",
"projects": "Projekte",
"properties": "Eigenschaften",
"property": "Eigenschaft",
"record": "Eintrag",
"region": "Bundesland",
@@ -274,6 +290,8 @@
"sender_tax_id": "Steuernummer",
"sent_email": "Email gesendet",
"service": "Service",
"service ({id})": "Service ({id})",
"session": "Sitzung",
"settings" : "Einstellungen",
"share_with": "Teilen mit:",
"show": "anzeigen",
@@ -301,12 +319,14 @@
},
"stock": "Inventar",
"street": "Straße",
"string": "Text",
"subject": "Betreff",
"subtask": "Unteraufgabe",
"subtasks": "Unteraufgaben",
"succeeding_document": "Nachfolge-Dokument",
"sum_of_records": "Summe der ausgewählten Einträge",
"table {name}": "Tabelle {name}",
"tag_name": "Tag-Name",
"tag_uses": "Verwendung des Tags „{tag}“",
"tags": "Tags",
@@ -319,6 +339,7 @@
"tax_rate": "Steuersatz",
"template": "Vorlage",
"theme": "Design",
"time ({id})": "Zeit ({id})",
"times": "Zeiten",
"timetracking": "Zeiterfassung",
"title_not_available": "„{title}“ ist als Seitenname nicht mehr verfügbar!",
@@ -333,6 +354,7 @@
"unexpected_item_id_format": "Alte Artikel-ID sollte die Form tt:zz:zz haben, habe aber {0} gefunden!",
"unit": "Einheit",
"unit price": "Preis/Einheit",
"unit_price": "Preis/Einheit",
"unknown_item_location": "Artikel {0} von {1} {2} ist verknüpft mit unbekanntem Lagerort {3}!",
"unlink": "Trennen",
@@ -340,6 +362,7 @@
"UPDATE_USERS" : "Nutzer aktualisieren",
"upload_file": "Datei hochladen",
"user": "Benutzer",
"user ({id})": "Benutzer ({id})",
"user_list": "Benutzer-Liste",
"user_module" : "Umbrella User-Verwaltung",
"users": "Benutzer",
@@ -351,6 +374,8 @@
"welcome" : "Willkommen, {0}",
"wiki": "Wiki",
"wikis": "Wiki-Seiten",
"wiki page": "Wiki-Seite",
"wiki pages": "Wiki-Seiten",
"wiki_pages": "Wiki-Seiten",
"value": "Wert",

View File

@@ -14,6 +14,7 @@
"basic_data": "basic data",
"bookmark": "bookmark",
"bookmarks": "bookmarks",
"Boolean": "Boolean",
"by": "by",
"cancel": "cancel",
@@ -30,6 +31,7 @@
"confirm_state": "Really change state?",
"companies": "companies",
"company": "company",
"company ({id})": "company ({id})",
"company_optional": "company (optional)",
"confirmation": "confirmation",
"complete": "complete",
@@ -53,6 +55,7 @@
"customer_address": "address",
"customer_email": "customer email address",
"customer_id": "customer ID",
"customer settings": "customer settings",
"custom_tag_colors": "custom tag colors",
"data_sent": "data sent",
@@ -72,6 +75,8 @@
"document": "document",
"document_list": "document list",
"documents": "documents",
"document type id": "document type id",
"document ({id})":"document ({id})",
"do_login" : "do login",
"do_open" : "open",
"do_send" : "send",
@@ -87,6 +92,7 @@
"edit_service": "edit login service \"{name}\"",
"email": "email",
"email_or_username": "email or username",
"Encountered invalid dbCode: {code}": "Encountered invalid dbCode: {code}",
"end": "end",
"estimated_time": "estimated duration",
"estimated_times": "estimated durations",
@@ -167,12 +173,16 @@
"local_court": "local court",
"locality": "locality",
"location": "location",
"locations": "locations",
"login" : "login",
"login service": "login service",
"login_services": "login service",
"logout": "logout",
"logout_user": "logout {user}",
"Long": "Long",
"markdown_code": "Markdown-Code",
"Markdown has been copied to clipboard!": "Markdown has been copied to clipboard!",
"markdown_supported": "Markdown & <a target=\"_blank\" href=\"https://plantuml.com\">Plantuml</a> supported!",
"MANAGE_LOGIN_SERVICES": "manage login services",
"member": "member",
@@ -205,6 +215,7 @@
"month": "month",
"move_to_top": "move to top level",
"must_not_be_empty": "must not be empty",
"my files": "my files",
"name": "Name",
"net_price": "net price",
@@ -218,6 +229,7 @@
"no_project_for_id": "No project found for id {0}",
"no_task_for_id": "No task found for id {0}",
"note": "note",
"note ({id})":"note ({id})",
"notes": "notes",
"not_recent_version": "This is not the current version of this page!",
"number": "number",
@@ -230,6 +242,7 @@
"page": "page",
"parent_task": "parent task",
"password" : "password",
"path": "path",
"permission": {
"EDIT": "read/write",
"OWNER": "owner"
@@ -250,7 +263,10 @@
"priority": "priority",
"processing_code": "processing code…",
"project": "project",
"project ({id})": "project ({id})",
"projects": "projects",
"properties": "properties",
"property": "property",
"record": "record",
"region": "region",
@@ -274,6 +290,8 @@
"sender_tax_id": "tax ID",
"sent_email": "email sent",
"service": "service",
"service ({id})": "service ({id})",
"session": "session",
"settings" : "settings",
"share_with": "share with:",
"show": "show",
@@ -301,12 +319,14 @@
},
"stock": "stock",
"street": "street",
"string": "string",
"subject": "subject",
"subtask": "subtask",
"subtasks": "subtasks",
"succeeding_document": "succeeding document",
"sum_of_records": "sum of records",
"table {name}": "table {name}",
"tag_name": "tag name",
"tag_uses": "usage of tag „{tag}“",
"tags": "tags",
@@ -319,13 +339,14 @@
"tax_rate": "tax rate",
"template": "template",
"theme": "design",
"time ({id})": "time ({id})",
"times": "times",
"timetracking": "time tracking",
"title_not_available": "„{title}“ is not available as page name!",
"title_or_desc": "title/description",
"toggle_objects": "toggle {objects}",
"tutorial": "tutorial",
"type": "document type",
"type": "type",
"type_confirmation": "confirmation",
"type_invoice": "invoice",
"type_offer": "offer",
@@ -333,6 +354,7 @@
"unexpected_item_id_format": "Expected old item ID to be of the form ss:dd:dd, encountered {0}!",
"unit": "unit",
"unit price": "unit price",
"unit_price": "price/unit",
"unknown_item_location": "Item {0} of {1} {2} refers to location {3}, which is unknown!",
"unlink": "unlink",
@@ -340,14 +362,20 @@
"UPDATE_USERS" : "update users",
"upload_file": "upload file",
"user": "user",
"user ({id})": "user ({id})",
"user_list": "user list",
"user_module" : "Umbrella user management",
"users": "users",
"user_created_entity": "{user} created \"{entity}\"",
"user_deleted_entity": "{user} deleted \"{entity}\"",
"user_updated_entity": "{user} updated \"{entity}\"",
"website": "website",
"welcome" : "Welcome, {0}",
"wiki": "Wiki",
"wikis": "wiki pages",
"wiki page": "wiki page",
"wiki pages": "wiki pages",
"wiki_pages": "wiki pages",
"value": "value",

View File

@@ -57,8 +57,9 @@ footer {
margin: 5px;
}
img {
img, svg {
max-width: 100%;
height: auto !important;
}
nav {

View File

@@ -57,8 +57,9 @@ footer {
margin: 5px;
}
img {
img, svg {
max-width: 100%;
height: auto !important;
}
nav {

View File

@@ -57,8 +57,9 @@ footer {
margin: 5px;
}
img {
img, svg {
max-width: 100%;
height: auto !important;
}
nav {