v0.7.98-beta - het heet nu gewoon een app
Some checks failed
Deploy server-up (dev) / deploy (push) Failing after 15m46s
Some checks failed
Deploy server-up (dev) / deploy (push) Failing after 15m46s
- "stack" heet in de interface voortaan "app": 24 teksten per taal plus de terugvalteksten in de pagina. Je installeerde een app uit de App Store en kreeg een stack; dat moest je maar net weten - code, API-paden, mapnamen en .serverup.json houden `stack` — dat leest niemand, en hernoemen zou opgeslagen gegevens en URL's breken - de aparte sectie "Overige containers" is verdwenen. Handmatig gestarte containers staan nu tussen de rest met het label "Handmatig gestart", met starten, stoppen en logs. De zoekterm geldt voor allebei; een categoriefilter laat ze vallen, want ze hebben geen categorie - de waarschuwing bij backups zei nog dat appdata er niet in zit; sinds v0.7.88 zit die er juist wel in, met een databasedump erbij Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
This commit is contained in:
parent
842615a562
commit
299ccf507c
6 changed files with 164 additions and 92 deletions
22
CHANGELOG.md
22
CHANGELOG.md
|
|
@ -1,3 +1,25 @@
|
|||
# v0.7.98-beta — Het heet nu gewoon een app
|
||||
|
||||
Je installeerde een **app** uit de **App Store** en kreeg een **stack**. Dat
|
||||
moest je maar net weten. In de interface heet alles nu een app: 24 teksten per
|
||||
taal plus de terugvalteksten in de pagina zelf.
|
||||
|
||||
De code, de API-paden (`/api/stacks/…`), de mapnamen en `.serverup.json` houden
|
||||
`stack`. Dat zijn geen woorden die iemand leest, en ze hernoemen zou opgeslagen
|
||||
gegevens en URL's breken zonder dat er iets duidelijker van wordt.
|
||||
|
||||
**De tweede lijst is verdwenen.** "Overige containers" stond als aparte sectie
|
||||
onderaan, met een eigen kop, een eigen uitleg en een eigen vormgeving. Wie zijn
|
||||
apps kwijt was moest weten dat die lijst bestond. Handmatig gestarte containers
|
||||
staan nu gewoon tussen de rest, als kaart, met het label **Handmatig gestart**.
|
||||
Er is minder mee te doen — starten, stoppen, logs — maar ze zijn wel te vinden.
|
||||
De zoekterm werkt op allebei; een categoriefilter laat ze vallen, want ze hébben
|
||||
geen categorie.
|
||||
|
||||
Onderweg gevonden: de waarschuwing bij backups zei nog dat een backup *"niet de
|
||||
Docker-volumes met de eigenlijke appdata"* bevat. Sinds v0.7.88 zit de appdata er
|
||||
juist wél in, met een dump van elke database erbij. Die tekst klopt nu.
|
||||
|
||||
# v0.7.97-beta — Repo's bijwerken werkte niet meer
|
||||
|
||||
**`fatal: Cannot rebase onto multiple branches.`** Het bijwerken van een
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.7.97-beta
|
||||
0.7.98-beta
|
||||
|
|
|
|||
|
|
@ -221,12 +221,12 @@ tailwind.config = {
|
|||
</button>
|
||||
<button class="stat-card text-left hover:shadow-soft2 transition" @click="goto('stacks')">
|
||||
<div class="stat-icon bg-ac/10 text-ac dark:text-ac-dark"><span class="mdi mdi-folder-multiple-outline"></span></div>
|
||||
<div class="min-w-0"><div class="stat-value" x-text="stacks.length"></div><div class="stat-label">Stacks</div></div>
|
||||
<div class="min-w-0"><div class="stat-value" x-text="stacks.length"></div><div class="stat-label">Apps</div></div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3 mb-3">
|
||||
<h2 class="text-sm font-bold text-wh dark:text-wh-dark uppercase tracking-wide" x-text="t('stacks')">Stacks</h2>
|
||||
<h2 class="text-sm font-bold text-wh dark:text-wh-dark uppercase tracking-wide" x-text="t('stacks')">Apps</h2>
|
||||
<button @click="loadDashboard()" class="btn-icon ml-auto w-9 h-9"><span class="mdi mdi-refresh"></span></button>
|
||||
</div>
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4" x-show="stacks.length > 0">
|
||||
|
|
@ -240,7 +240,7 @@ tailwind.config = {
|
|||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<div x-show="stacks.length === 0" class="empty"><span class="mdi mdi-server-network"></span><p x-text="t('no_stacks')">Geen stacks</p></div>
|
||||
<div x-show="stacks.length === 0" class="empty"><span class="mdi mdi-server-network"></span><p x-text="t('no_stacks')">Geen apps</p></div>
|
||||
</section>
|
||||
|
||||
<!-- ══ Stacks ══ -->
|
||||
|
|
@ -296,7 +296,8 @@ tailwind.config = {
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4" x-show="filteredStacks.length > 0">
|
||||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-4"
|
||||
x-show="filteredStacks.length || filteredLos.length">
|
||||
<template x-for="s in filteredStacks" :key="s.name">
|
||||
<div class="card card-hover flex flex-col border-l-4"
|
||||
:style="'border-left-color:' + cat((s.categories || [])[0] || 'overig').color">
|
||||
|
|
@ -437,48 +438,52 @@ tailwind.config = {
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div x-show="filteredStacks.length === 0" class="empty"><span class="mdi mdi-server-network"></span><p x-text="t('no_stacks')">Geen stacks gevonden</p></div>
|
||||
|
||||
<!-- Containers die niet bij een door Server Up beheerde stack horen.
|
||||
Zonder dit blok tellen ze wel mee op het dashboard maar zijn ze
|
||||
nergens terug te vinden. -->
|
||||
<div x-show="unmanaged.length" class="mt-8">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="mdi mdi-cube-outline text-t2 dark:text-t2-dark"></span>
|
||||
<h3 class="text-sm font-bold text-wh dark:text-wh-dark" x-text="t('other_containers')">Overige containers</h3>
|
||||
<span class="badge badge-dim" x-text="unmanaged.length"></span>
|
||||
<button class="btn-icon ml-auto w-9 h-9" @click="loadHostContainers()"><span class="mdi mdi-refresh"></span></button>
|
||||
</div>
|
||||
<p class="text-xs text-t2 dark:text-t2-dark mb-3" x-text="t('other_containers_hint')"></p>
|
||||
<div class="card divide-y divide-bd dark:divide-bd-dark">
|
||||
<template x-for="c in unmanaged" :key="c.id">
|
||||
<div class="px-4 py-3 flex flex-wrap items-center gap-2">
|
||||
<span class="w-2.5 h-2.5 rounded-full shrink-0" :class="c.running ? 'bg-ok' : 'bg-dm dark:bg-dm-dark'"></span>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="text-sm font-semibold text-wh dark:text-wh-dark truncate" x-text="c.name"></div>
|
||||
<div class="text-[10px] font-mono text-dm dark:text-dm-dark truncate">
|
||||
<span x-text="c.image"></span><span x-show="c.ports"> · </span><span x-text="c.ports"></span>
|
||||
</div>
|
||||
<!-- Handmatig gestarte containers staan in dezelfde lijst. Ze horen
|
||||
niet bij een app die Server Up heeft aangemaakt, dus er is minder
|
||||
mee te doen — maar ze apart onderaan zetten maakte ze onvindbaar
|
||||
en gaf ze een tweederangs plek die niemand hielp. -->
|
||||
<template x-for="c in filteredLos" :key="c.id">
|
||||
<div class="card card-hover flex flex-col border-l-4 border-l-bd dark:border-l-bd-dark">
|
||||
<div class="px-4 py-3.5 flex items-center gap-2.5 border-b border-bd dark:border-bd-dark">
|
||||
<span class="w-8 h-8 rounded-lg bg-s2 dark:bg-s2-dark grid place-items-center text-base shrink-0">📦</span>
|
||||
<span class="w-2.5 h-2.5 rounded-full shrink-0"
|
||||
:class="c.running ? 'bg-ok shadow-[0_0_8px_#22c55e]' : 'bg-dm dark:bg-dm-dark'"></span>
|
||||
<span class="font-semibold text-wh dark:text-wh-dark text-sm flex-1 truncate" x-text="c.name"></span>
|
||||
<span x-show="c.self" class="badge badge-info" x-text="t('this_app')">deze app</span>
|
||||
<span class="badge" :class="c.running ? 'badge-ok' : 'badge-dim'"
|
||||
x-text="c.running ? t('running') : t('stopped')"></span>
|
||||
</div>
|
||||
<div class="p-4 flex flex-col gap-3 flex-1">
|
||||
<div class="flex flex-wrap gap-1 items-center">
|
||||
<span class="badge badge-dim" x-text="t('manual_started')">Handmatig gestart</span>
|
||||
<span x-show="c.project" class="badge badge-dim" x-text="c.project"></span>
|
||||
</div>
|
||||
<div class="text-[11px] font-mono text-dm dark:text-dm-dark break-all">
|
||||
<span x-text="c.image"></span>
|
||||
<template x-if="c.ports"><span> · <span x-text="c.ports"></span></span></template>
|
||||
</div>
|
||||
<span class="badge badge-dim" x-show="c.project" x-text="c.project"></span>
|
||||
<span class="badge badge-info" x-show="c.self" x-text="t('this_app')">deze app</span>
|
||||
<template x-if="!c.self">
|
||||
<div class="flex gap-1.5">
|
||||
<button class="btn-sm !h-8 !px-2" :title="c.running ? t('stop') : t('start')"
|
||||
<div class="flex flex-wrap gap-1.5 mt-auto">
|
||||
<button class="btn-sm flex-1 min-w-[84px]" :class="c.running ? 'btn-danger' : 'btn-primary'"
|
||||
@click="hostContainerAction(c.name, c.running ? 'stop' : 'start')">
|
||||
<span class="mdi" :class="c.running ? 'mdi-stop' : 'mdi-play'"></span>
|
||||
<span x-text="c.running ? t('stop') : t('start')"></span>
|
||||
</button>
|
||||
<button class="btn-sm !h-8 !px-2" :title="t('restart')"
|
||||
<button class="btn-sm" :title="t('restart')"
|
||||
@click="hostContainerAction(c.name, 'restart')"><span class="mdi mdi-restart"></span></button>
|
||||
<button class="btn-sm !h-8 !px-2" :title="t('logs')"
|
||||
<button class="btn-sm" :title="t('logs')"
|
||||
@click="openHostLogs(c.name)"><span class="mdi mdi-text-box-outline"></span></button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div x-show="!filteredStacks.length && !filteredLos.length" class="empty"><span class="mdi mdi-server-network"></span><p x-text="t('no_stacks')">Geen apps gevonden</p></div>
|
||||
<p x-show="filteredLos.length" class="text-xs text-t2 dark:text-t2-dark mt-4"
|
||||
x-text="t('manual_hint')"></p>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- ══ App Store ══ -->
|
||||
|
|
@ -920,7 +925,7 @@ tailwind.config = {
|
|||
</p>
|
||||
<div class="grid sm:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="form-label" x-text="t('backup_keep')">Aantal per stack</label>
|
||||
<label class="form-label" x-text="t('backup_keep')">Aantal per app</label>
|
||||
<input type="number" min="0" class="form-input" x-model.number="settings.BACKUP_KEEP" @change="autoSave()">
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -1679,7 +1684,7 @@ tailwind.config = {
|
|||
sm:h-auto sm:max-h-[88vh] sm:rounded-2xl">
|
||||
<div class="modal-head">
|
||||
<span class="mdi mdi-download-outline text-ac dark:text-ac-dark shrink-0"></span>
|
||||
<span class="min-w-0 truncate" x-text="install.mode === 'edit' ? t('stack_settings') : t('install_stack')">Stack installeren</span>
|
||||
<span class="min-w-0 truncate" x-text="install.mode === 'edit' ? t('stack_settings') : t('install_stack')">App installeren</span>
|
||||
<span x-show="install.format === 'boilerplate'" class="badge badge-info hidden sm:inline-flex">Boilerplate</span>
|
||||
<!-- Op een telefoon vult deze modal het scherm, dus er is geen
|
||||
achtergrond meer om op te tikken. Zonder deze knop kom je er niet uit. -->
|
||||
|
|
@ -2090,7 +2095,7 @@ tailwind.config = {
|
|||
<!-- Legacy fields -->
|
||||
<template x-if="install.format === 'compose' && !install.loading">
|
||||
<div class="space-y-4">
|
||||
<div><label class="form-label">Stack</label><input class="form-input" :value="install.stack" readonly></div>
|
||||
<div><label class="form-label">App</label><input class="form-input" :value="install.stack" readonly></div>
|
||||
<div x-show="install.mode !== 'edit'">
|
||||
<label class="form-label" x-text="t('instance_name')">Instantie naam</label>
|
||||
<input class="form-input" x-model="install.instance">
|
||||
|
|
@ -2166,7 +2171,7 @@ tailwind.config = {
|
|||
<div x-show="modal==='remove'" class="modal max-w-md">
|
||||
<div class="modal-head"><span class="mdi mdi-delete-alert-outline text-er"></span> <span x-text="t('remove_stack')">Verwijderen</span></div>
|
||||
<div class="modal-body">
|
||||
<p class="text-sm mb-4 text-t2 dark:text-t2-dark">Stack: <strong class="text-wh dark:text-wh-dark" x-text="install.stack"></strong></p>
|
||||
<p class="text-sm mb-4 text-t2 dark:text-t2-dark">App: <strong class="text-wh dark:text-wh-dark" x-text="install.stack"></strong></p>
|
||||
<div class="flex flex-col gap-2">
|
||||
<button class="btn" @click="doRemove('stack')"><span class="mdi mdi-stop-circle-outline"></span> <span x-text="t('remove_stack_only')">Stop + volumes</span></button>
|
||||
<button class="btn btn-danger" @click="doRemove('all')"><span class="mdi mdi-delete-outline"></span> <span x-text="t('remove_all')">Verwijder alles</span></button>
|
||||
|
|
@ -2310,7 +2315,7 @@ tailwind.config = {
|
|||
<div x-show="wizardStapId() === 'welkom'">
|
||||
<p class="text-sm">Doorloop deze korte wizard om Server Up te configureren.</p>
|
||||
<ul class="text-sm mt-4 space-y-2 text-t2 dark:text-t2-dark">
|
||||
<li class="flex gap-2"><span class="mdi mdi-check-circle text-ok"></span> Beheer Docker stacks via één UI</li>
|
||||
<li class="flex gap-2"><span class="mdi mdi-check-circle text-ok"></span> Beheer je Docker-apps via één UI</li>
|
||||
<li class="flex gap-2"><span class="mdi mdi-check-circle text-ok"></span> Installeer apps uit je eigen repo of de Boilerplates</li>
|
||||
<li class="flex gap-2"><span class="mdi mdi-check-circle text-ok"></span> Modules toevoegen voor MQTT, Home Assistant, etc.</li>
|
||||
</ul>
|
||||
|
|
@ -2323,7 +2328,7 @@ tailwind.config = {
|
|||
<div x-show="wizardStapId() === 'repos'">
|
||||
<p class="text-sm mb-3">Server Up start met deze repos. Je kunt later meer toevoegen via Instellingen → Git Repositories.</p>
|
||||
<ul class="text-sm space-y-2.5">
|
||||
<li class="flex items-start gap-2"><span class="mdi mdi-check-circle text-ok mt-0.5"></span><span><strong>bes-r/server-up</strong> — eigen stacks & modules <span class="text-dm dark:text-dm-dark">(submap: apps / modules)</span></span></li>
|
||||
<li class="flex items-start gap-2"><span class="mdi mdi-check-circle text-ok mt-0.5"></span><span><strong>bes-r/server-up</strong> — eigen apps & modules <span class="text-dm dark:text-dm-dark">(submap: apps / modules)</span></span></li>
|
||||
<li class="flex items-start gap-2"><span class="mdi mdi-check-circle text-ok mt-0.5"></span><span><strong>ChristianLempa/boilerplates-library</strong> — community templates <span class="text-dm dark:text-dm-dark">(submap: compose)</span></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -2333,7 +2338,7 @@ tailwind.config = {
|
|||
<span class="mdi mdi-server text-2xl"></span><span class="font-semibold">Al een server</span><span class="text-[10px] text-center opacity-70">Gitea / Forgejo of andere git</span>
|
||||
</button>
|
||||
<button @click="wizard.git.choice = 'install'" :class="wizard.git.choice === 'install' ? 'border-ac text-ac dark:text-ac-dark bg-ac/5' : 'border-bd dark:border-bd-dark text-t2 dark:text-t2-dark'" class="flex flex-col items-center gap-1.5 rounded-xl border p-3 text-xs transition cursor-pointer hover:border-ac">
|
||||
<span class="mdi mdi-download-circle-outline text-2xl"></span><span class="font-semibold">Installeer Forgejo</span><span class="text-[10px] text-center opacity-70">Forgejo als stack</span>
|
||||
<span class="mdi mdi-download-circle-outline text-2xl"></span><span class="font-semibold">Installeer Forgejo</span><span class="text-[10px] text-center opacity-70">Forgejo als app</span>
|
||||
</button>
|
||||
<button @click="wizard.git.choice = 'skip'" :class="wizard.git.choice === 'skip' ? 'border-ac text-ac dark:text-ac-dark bg-ac/5' : 'border-bd dark:border-bd-dark text-t2 dark:text-t2-dark'" class="flex flex-col items-center gap-1.5 rounded-xl border p-3 text-xs transition cursor-pointer hover:border-ac">
|
||||
<span class="mdi mdi-skip-next-circle-outline text-2xl"></span><span class="font-semibold">Overslaan</span><span class="text-[10px] text-center opacity-70">Later toe te voegen</span>
|
||||
|
|
@ -3011,6 +3016,17 @@ function app() {
|
|||
return !q || (s.name || '').toLowerCase().includes(q);
|
||||
});
|
||||
},
|
||||
// Containers die niet bij een app horen die Server Up heeft aangemaakt.
|
||||
// Ze staan in dezelfde lijst en volgen dus dezelfde zoekterm. Een
|
||||
// categoriefilter laat ze wél vallen: ze hebben geen categorieën, dus ze
|
||||
// horen niet bij "alleen Media" te blijven staan.
|
||||
get filteredLos() {
|
||||
if (this.stackCat) return [];
|
||||
const q = this.stackQuery.toLowerCase();
|
||||
return this.unmanaged.filter(c =>
|
||||
!q || (c.name || '').toLowerCase().includes(q)
|
||||
|| (c.image || '').toLowerCase().includes(q));
|
||||
},
|
||||
// Categorieën van de geïnstalleerde stacks, met hun aantal.
|
||||
get stackCategories() {
|
||||
const telling = {};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"flag": "🇬🇧"
|
||||
},
|
||||
"dashboard": "Dashboard",
|
||||
"stacks": "Stacks",
|
||||
"stacks": "Apps",
|
||||
"app_store": "App Store",
|
||||
"images": "Docker Images",
|
||||
"audit": "Audit Log",
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
"language": "Language",
|
||||
"git": "Git",
|
||||
"docker": "Docker",
|
||||
"no_stacks": "No stacks found",
|
||||
"no_stacks": "No apps found",
|
||||
"no_images": "No images found",
|
||||
"no_repos": "No repositories",
|
||||
"add_repo": "Add repository",
|
||||
|
|
@ -55,10 +55,10 @@
|
|||
"repo_url": "Git URL",
|
||||
"repo_branch": "Branch",
|
||||
"repo_subdir": "Subdirectory",
|
||||
"install_stack": "Install stack",
|
||||
"install_stack": "Install app",
|
||||
"instance_name": "Instance name",
|
||||
"instance_hint": "Change for multiple installations",
|
||||
"remove_stack": "Remove stack",
|
||||
"remove_stack": "Remove app",
|
||||
"remove_stack_only": "Stop containers + volumes",
|
||||
"remove_all": "Stop + remove all files",
|
||||
"prune_images": "Remove all unused images?",
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
"wizard_paths": "Set paths",
|
||||
"wizard_paths_sub": "Where should your Docker projects be stored?",
|
||||
"wizard_git": "Git repositories",
|
||||
"wizard_git_sub": "Synchronise your stacks and modules.",
|
||||
"wizard_git_sub": "Synchronise your apps and modules.",
|
||||
"wizard_done": "All done!",
|
||||
"wizard_done_sub": "Setup complete. Change anything later in Settings.",
|
||||
"prev": "Previous",
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
"trusted_proxies_hint": "One per line, IP or CIDR. The header is only trusted from these addresses — without this list anyone could impersonate an administrator.",
|
||||
"proxy_lockout_confirm": "In 'Reverse proxy' mode the local login is disabled. Are you sure your proxy works?",
|
||||
"networks": "Networks",
|
||||
"networks_hint": "A macvlan or ipvlan network gives a stack its own IP address on your LAN instead of ports on the host. No more port conflicts, and you can firewall per app. Note: the Docker host itself cannot reach macvlan containers without a shim interface.",
|
||||
"networks_hint": "A macvlan or ipvlan network gives a app its own IP address on your LAN instead of ports on the host. No more port conflicts, and you can firewall per app. Note: the Docker host itself cannot reach macvlan containers without a shim interface.",
|
||||
"add_network": "Add network",
|
||||
"network": "Network",
|
||||
"no_networks": "No networks yet.",
|
||||
|
|
@ -167,8 +167,8 @@
|
|||
"ports_on_host": "Ports on the host (default)",
|
||||
"own_ip": "own IP",
|
||||
"ip_address": "IP address",
|
||||
"own_ip_hint": "The stack gets this address on your LAN. Port mappings are dropped — the app is reachable on its own port. The Docker host itself cannot reach a macvlan container without a shim interface (see docs/netwerken.md).",
|
||||
"no_networks_hint": "Want to give stacks their own IP? Add a network first under Settings → Networks.",
|
||||
"own_ip_hint": "The app gets this address on your LAN. Port mappings are dropped — the app is reachable on its own port. The Docker host itself cannot reach a macvlan container without a shim interface (see docs/netwerken.md).",
|
||||
"no_networks_hint": "Want to give apps their own IP? Add a network first under Settings → Networks.",
|
||||
"generate_value": "Generate a random value",
|
||||
"port_taken": "Port {port} is already in use — {suggested} suggested.",
|
||||
"channel": "Channel",
|
||||
|
|
@ -196,25 +196,25 @@
|
|||
"backups": "Backups",
|
||||
"no_backups": "No backups yet",
|
||||
"restore": "Restore",
|
||||
"restore_confirm": "Restore backup {file}?\n\nThe current files of this stack will be replaced and the stack restarted.",
|
||||
"restore_confirm": "Restore backup {file}?\n\nThe current files of this app will be replaced and the app restarted.",
|
||||
"delete_backup_confirm": "Delete this backup?",
|
||||
"backup_scope_warning": "A backup contains the stack's compose and .env files, not the Docker volumes holding the actual app data. See docs/backups.md.",
|
||||
"backup_scope_warning": "A backup contains the app's compose and .env files, the appdata next to them, and a dump of every database it uses. Docker volumes the app creates itself are not included. See docs/backups.md.",
|
||||
"backup_retention": "Retention",
|
||||
"backup_keep": "Backups to keep per stack",
|
||||
"backup_keep": "Backups to keep per app",
|
||||
"backup_max_age": "Maximum age (days, 0 = no limit)",
|
||||
"backup_schedule": "Scheduled backups",
|
||||
"backup_schedule_off": "Off",
|
||||
"backup_schedule_daily": "Daily",
|
||||
"backup_schedule_weekly": "Weekly",
|
||||
"backup_schedule_hour": "Around which hour",
|
||||
"backup_before_update": "Automatically back up before updating a stack",
|
||||
"backup_before_remove": "Automatically back up before removing a stack",
|
||||
"backup_before_update": "Automatically back up before updating a app",
|
||||
"backup_before_remove": "Automatically back up before removing a app",
|
||||
"check_updates": "Check for updates",
|
||||
"stack_update_check": "Check daily whether newer images are available",
|
||||
"role_admin": "Administrator",
|
||||
"role_operator": "Operator",
|
||||
"role_viewer": "Read-only",
|
||||
"roles_hint": "An administrator may do everything. An operator manages stacks, containers and backups, but not settings, users, repositories or networks. Read-only cannot change anything.",
|
||||
"roles_hint": "An administrator may do everything. An operator manages apps, containers and backups, but not settings, users, repositories or networks. Read-only cannot change anything.",
|
||||
"proxy_role": "Role for proxy users",
|
||||
"proxy_role_hint": "Anyone signing in through the reverse proxy without their own account gets this role.",
|
||||
"no_permission": "Your role does not allow this action",
|
||||
|
|
@ -241,10 +241,8 @@
|
|||
"range_count": "{count} addresses",
|
||||
"already_added": "already added",
|
||||
"detect_empty": "No network with a default route was found on this server. Fill in the details below manually.",
|
||||
"wizard_hint": "Run the wizard again to adjust paths and repositories. Your existing stacks are left untouched.",
|
||||
"wizard_hint": "Run the wizard again to adjust paths and repositories. Your existing apps are left untouched.",
|
||||
"of_which_managed": "of which {n} via Server Up",
|
||||
"other_containers": "Other containers",
|
||||
"other_containers_hint": "These containers run on this host but do not belong to a stack managed by Server Up — started manually, for example, or from before you began using Server Up. They do count towards the dashboard figures.",
|
||||
"this_app": "this app",
|
||||
"advanced_options": "Advanced options",
|
||||
"what_does_this_do": "What does this setting do?",
|
||||
|
|
@ -252,15 +250,15 @@
|
|||
"enter_manually": "Enter manually…",
|
||||
"no_connectable_app": "No {app} is installed yet. Install it first, or enter the address manually.",
|
||||
"connect_apps": "Connect to other apps",
|
||||
"connect_apps_hint": "Put this stack on the shared network '{net}' so it can reach other apps by name and vice versa. Without this, every stack stands alone.",
|
||||
"connect_apps_hint": "Put this app on the shared network '{net}' so it can reach other apps by name and vice versa. Without this, every app stands alone.",
|
||||
"filter_on_category": "Filter by this category",
|
||||
"categories": "Categories",
|
||||
"stack_settings": "Settings",
|
||||
"reconfigure_warning": "The stack is rebuilt from its template. Manual changes to the compose file will be lost — a backup is made first automatically.",
|
||||
"reconfigure_confirm": "Save settings for {stack}?\n\nA backup is made first, then the stack is rebuilt and restarted.",
|
||||
"reconfigure_warning": "The app is rebuilt from its template. Manual changes to the compose file will be lost — a backup is made first automatically.",
|
||||
"reconfigure_confirm": "Save settings for {stack}?\n\nA backup is made first, then the app is rebuilt and restarted.",
|
||||
"connect_to_apps": "Connect to other apps",
|
||||
"connected_to_apps": "Already connected to other apps",
|
||||
"connect_stack_confirm": "Put {stack} on the shared network '{net}'?\n\nThe stack will be restarted.",
|
||||
"connect_stack_confirm": "Put {stack} on the shared network '{net}'?\n\nThe app will be restarted.",
|
||||
"all_time": "All time",
|
||||
"last_day": "24 hours",
|
||||
"last_week": "7 days",
|
||||
|
|
@ -371,7 +369,7 @@
|
|||
"audit_cat_notify": "Notifications",
|
||||
"audit_cat_pangolin": "Pangolin",
|
||||
"audit_cat_repos": "Repositories",
|
||||
"audit_cat_stacks": "Stacks",
|
||||
"audit_cat_stacks": "Apps",
|
||||
"audit_cat_store": "App store",
|
||||
"audit_cat_update": "Updates",
|
||||
"audit_cat_wizard": "Wizard",
|
||||
|
|
@ -429,7 +427,7 @@
|
|||
"col_action": "Action",
|
||||
"col_status": "Status",
|
||||
"col_ref": "Subject",
|
||||
"open_stack": "Go to stack",
|
||||
"open_stack": "Go to app",
|
||||
"more": "More",
|
||||
"ok": "OK",
|
||||
"failed": "Failed",
|
||||
|
|
@ -462,7 +460,10 @@
|
|||
"apply_all": "Apply to all",
|
||||
"path_unusable": "This path cannot be used",
|
||||
"paths_changed": "The folders have changed",
|
||||
"paths_move_hint": "The setting is saved, but your data is still in the old place and every stack still points there. Moving copies everything first, updates the stacks, and only then clears out the old folders.",
|
||||
"paths_move_hint": "The setting is saved, but your data is still in the old place and every app still points there. Moving copies everything first, updates the apps, and only then clears out the old folders.",
|
||||
"move_data": "Move data",
|
||||
"move_data_confirm": "Move {n} folder(s)? Stacks are stopped, data is copied and verified, and only then is the old cleared out."
|
||||
"move_data_confirm": "Move {n} folder(s)? Apps are stopped, data is copied and verified, and only then is the old cleared out.",
|
||||
"manual_started": "Started manually",
|
||||
"manual_hint": "These apps run on this host but were not created by Server Up — started manually, or from before you began using Server Up. You can start, stop and view their logs here.",
|
||||
"containers_n": "{n} containers"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"flag": "🇳🇱"
|
||||
},
|
||||
"dashboard": "Dashboard",
|
||||
"stacks": "Stacks",
|
||||
"stacks": "Apps",
|
||||
"app_store": "App Store",
|
||||
"images": "Docker Images",
|
||||
"audit": "Audit Log",
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
"language": "Taal",
|
||||
"git": "Git",
|
||||
"docker": "Docker",
|
||||
"no_stacks": "Geen stacks gevonden",
|
||||
"no_stacks": "Geen apps gevonden",
|
||||
"no_images": "Geen images gevonden",
|
||||
"no_repos": "Geen repositories",
|
||||
"add_repo": "Repository toevoegen",
|
||||
|
|
@ -55,10 +55,10 @@
|
|||
"repo_url": "Git URL",
|
||||
"repo_branch": "Branch",
|
||||
"repo_subdir": "Submap",
|
||||
"install_stack": "Stack installeren",
|
||||
"install_stack": "App installeren",
|
||||
"instance_name": "Instantie naam",
|
||||
"instance_hint": "Wijzig voor meerdere installaties",
|
||||
"remove_stack": "Stack verwijderen",
|
||||
"remove_stack": "App verwijderen",
|
||||
"remove_stack_only": "Stop containers + volumes",
|
||||
"remove_all": "Stop + verwijder alle bestanden",
|
||||
"prune_images": "Alle ongebruikte images verwijderen?",
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
"wizard_paths": "Mappen instellen",
|
||||
"wizard_paths_sub": "Waar worden je Docker-projecten opgeslagen?",
|
||||
"wizard_git": "Git repositories",
|
||||
"wizard_git_sub": "Synchroniseer je stacks en modules.",
|
||||
"wizard_git_sub": "Synchroniseer je apps en modules.",
|
||||
"wizard_done": "Klaar!",
|
||||
"wizard_done_sub": "Setup is voltooid. Wijzig alles later via Instellingen.",
|
||||
"prev": "Vorige",
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
"trusted_proxies_hint": "Eén per regel, IP of CIDR. Alleen vanaf deze adressen wordt de header vertrouwd — zonder deze lijst kan iedereen zich voordoen als beheerder.",
|
||||
"proxy_lockout_confirm": "In modus 'Reverse proxy' vervalt de lokale login. Weet je zeker dat je proxy werkt?",
|
||||
"networks": "Netwerken",
|
||||
"networks_hint": "Met een macvlan- of ipvlan-netwerk krijgt een stack een eigen IP-adres in je LAN in plaats van poorten op de host. Geen poortconflicten meer, en je kunt per app firewallen. Let op: de Docker-host zelf bereikt macvlan-containers niet zonder shim-interface.",
|
||||
"networks_hint": "Met een macvlan- of ipvlan-netwerk krijgt een app een eigen IP-adres in je LAN in plaats van poorten op de host. Geen poortconflicten meer, en je kunt per app firewallen. Let op: de Docker-host zelf bereikt macvlan-containers niet zonder shim-interface.",
|
||||
"add_network": "Netwerk toevoegen",
|
||||
"network": "Netwerk",
|
||||
"no_networks": "Nog geen netwerken.",
|
||||
|
|
@ -167,8 +167,8 @@
|
|||
"ports_on_host": "Poorten op de host (standaard)",
|
||||
"own_ip": "eigen IP",
|
||||
"ip_address": "IP-adres",
|
||||
"own_ip_hint": "De stack krijgt dit adres in het LAN. Poortmappings vervallen — de app is bereikbaar op zijn eigen poort. De Docker-host zelf kan een macvlan-container niet bereiken zonder shim-interface (zie docs/netwerken.md).",
|
||||
"no_networks_hint": "Wil je stacks een eigen IP geven? Voeg eerst een netwerk toe bij Instellingen → Netwerken.",
|
||||
"own_ip_hint": "De app krijgt dit adres in het LAN. Poortmappings vervallen — de app is bereikbaar op zijn eigen poort. De Docker-host zelf kan een macvlan-container niet bereiken zonder shim-interface (zie docs/netwerken.md).",
|
||||
"no_networks_hint": "Wil je apps een eigen IP geven? Voeg eerst een netwerk toe bij Instellingen → Netwerken.",
|
||||
"generate_value": "Genereer een willekeurige waarde",
|
||||
"port_taken": "Poort {port} is al in gebruik — {suggested} voorgesteld.",
|
||||
"channel": "Kanaal",
|
||||
|
|
@ -196,25 +196,25 @@
|
|||
"backups": "Backups",
|
||||
"no_backups": "Nog geen backups",
|
||||
"restore": "Terugzetten",
|
||||
"restore_confirm": "Backup {file} terugzetten?\n\nDe huidige bestanden van deze stack worden vervangen en de stack wordt herstart.",
|
||||
"restore_confirm": "Backup {file} terugzetten?\n\nDe huidige bestanden van deze app worden vervangen en de app wordt herstart.",
|
||||
"delete_backup_confirm": "Deze backup verwijderen?",
|
||||
"backup_scope_warning": "Een backup bevat de compose- en .env-bestanden van de stack, niet de Docker-volumes met de eigenlijke appdata. Zie docs/backups.md.",
|
||||
"backup_scope_warning": "Een backup bevat de compose- en .env-bestanden van de app, de appdata ernaast, en een dump van elke database die erbij hoort. Docker-volumes die de app zelf aanmaakt gaan niet mee. Zie docs/backups.md.",
|
||||
"backup_retention": "Bewaarbeleid",
|
||||
"backup_keep": "Aantal backups per stack",
|
||||
"backup_keep": "Aantal backups per app",
|
||||
"backup_max_age": "Maximale leeftijd (dagen, 0 = geen limiet)",
|
||||
"backup_schedule": "Geplande backups",
|
||||
"backup_schedule_off": "Uit",
|
||||
"backup_schedule_daily": "Dagelijks",
|
||||
"backup_schedule_weekly": "Wekelijks",
|
||||
"backup_schedule_hour": "Rond welk uur",
|
||||
"backup_before_update": "Automatisch een backup vóór het bijwerken van een stack",
|
||||
"backup_before_remove": "Automatisch een backup vóór het verwijderen van een stack",
|
||||
"backup_before_update": "Automatisch een backup vóór het bijwerken van een app",
|
||||
"backup_before_remove": "Automatisch een backup vóór het verwijderen van een app",
|
||||
"check_updates": "Updates controleren",
|
||||
"stack_update_check": "Dagelijks controleren of er nieuwere images zijn",
|
||||
"role_admin": "Beheerder",
|
||||
"role_operator": "Operator",
|
||||
"role_viewer": "Alleen lezen",
|
||||
"roles_hint": "Beheerder mag alles. Operator beheert stacks, containers en backups, maar niet de instellingen, gebruikers, repo's of netwerken. Alleen lezen kan niets wijzigen.",
|
||||
"roles_hint": "Beheerder mag alles. Operator beheert apps, containers en backups, maar niet de instellingen, gebruikers, repo's of netwerken. Alleen lezen kan niets wijzigen.",
|
||||
"proxy_role": "Rol voor proxy-gebruikers",
|
||||
"proxy_role_hint": "Iedereen die via de reverse proxy binnenkomt en geen eigen account heeft, krijgt deze rol.",
|
||||
"no_permission": "Je rol geeft geen toegang tot deze actie",
|
||||
|
|
@ -241,10 +241,8 @@
|
|||
"range_count": "{count} adressen",
|
||||
"already_added": "al toegevoegd",
|
||||
"detect_empty": "Er is geen netwerk met een default route gevonden op deze server. Vul de gegevens hieronder handmatig in.",
|
||||
"wizard_hint": "Doorloop de wizard opnieuw om paden en repositories aan te passen. Je bestaande stacks blijven staan.",
|
||||
"wizard_hint": "Doorloop de wizard opnieuw om paden en repositories aan te passen. Je bestaande apps blijven staan.",
|
||||
"of_which_managed": "waarvan {n} via Server Up",
|
||||
"other_containers": "Overige containers",
|
||||
"other_containers_hint": "Deze containers draaien op deze host maar horen niet bij een stack die Server Up beheert — bijvoorbeeld handmatig gestart of van vóór je Server Up ging gebruiken. Ze tellen wel mee in de cijfers op het dashboard.",
|
||||
"this_app": "deze app",
|
||||
"advanced_options": "Geavanceerde opties",
|
||||
"what_does_this_do": "Wat doet deze instelling?",
|
||||
|
|
@ -252,15 +250,15 @@
|
|||
"enter_manually": "Handmatig invullen…",
|
||||
"no_connectable_app": "Er is nog geen {app} geïnstalleerd. Installeer die eerst, of vul het adres handmatig in.",
|
||||
"connect_apps": "Verbinden met andere apps",
|
||||
"connect_apps_hint": "Zet deze stack op het gedeelde netwerk '{net}', zodat hij andere apps op hun naam kan bereiken en andersom. Zonder dit staat elke stack op zichzelf.",
|
||||
"connect_apps_hint": "Zet deze app op het gedeelde netwerk '{net}', zodat hij andere apps op hun naam kan bereiken en andersom. Zonder dit staat elke app op zichzelf.",
|
||||
"filter_on_category": "Filter op deze categorie",
|
||||
"categories": "Categorieën",
|
||||
"stack_settings": "Instellingen",
|
||||
"reconfigure_warning": "De stack wordt opnieuw opgebouwd uit het sjabloon. Handmatige wijzigingen in het compose-bestand gaan daarbij verloren — er wordt eerst automatisch een backup gemaakt.",
|
||||
"reconfigure_confirm": "Instellingen van {stack} opslaan?\n\nEr wordt eerst een backup gemaakt; daarna wordt de stack opnieuw opgebouwd en herstart.",
|
||||
"reconfigure_warning": "De app wordt opnieuw opgebouwd uit het sjabloon. Handmatige wijzigingen in het compose-bestand gaan daarbij verloren — er wordt eerst automatisch een backup gemaakt.",
|
||||
"reconfigure_confirm": "Instellingen van {stack} opslaan?\n\nEr wordt eerst een backup gemaakt; daarna wordt de app opnieuw opgebouwd en herstart.",
|
||||
"connect_to_apps": "Koppelen aan andere apps",
|
||||
"connected_to_apps": "Al gekoppeld aan andere apps",
|
||||
"connect_stack_confirm": "{stack} op het gedeelde netwerk '{net}' zetten?\n\nDe stack wordt daarna herstart.",
|
||||
"connect_stack_confirm": "{stack} op het gedeelde netwerk '{net}' zetten?\n\nDe app wordt daarna herstart.",
|
||||
"all_time": "Altijd",
|
||||
"last_day": "24 uur",
|
||||
"last_week": "7 dagen",
|
||||
|
|
@ -371,7 +369,7 @@
|
|||
"audit_cat_notify": "Meldingen",
|
||||
"audit_cat_pangolin": "Pangolin",
|
||||
"audit_cat_repos": "Repositories",
|
||||
"audit_cat_stacks": "Stacks",
|
||||
"audit_cat_stacks": "Apps",
|
||||
"audit_cat_store": "App Store",
|
||||
"audit_cat_update": "Bijwerken",
|
||||
"audit_cat_wizard": "Wizard",
|
||||
|
|
@ -429,7 +427,7 @@
|
|||
"col_action": "Actie",
|
||||
"col_status": "Status",
|
||||
"col_ref": "Betreft",
|
||||
"open_stack": "Naar de stack",
|
||||
"open_stack": "Naar de app",
|
||||
"more": "Meer",
|
||||
"ok": "Gelukt",
|
||||
"failed": "Mislukt",
|
||||
|
|
@ -462,7 +460,10 @@
|
|||
"apply_all": "Alles overnemen",
|
||||
"path_unusable": "Dit pad is niet bruikbaar",
|
||||
"paths_changed": "De mappen zijn gewijzigd",
|
||||
"paths_move_hint": "De instelling is opgeslagen, maar je data staat nog op de oude plek en elke stack wijst daar nog naartoe. Verplaatsen kopieert eerst alles, werkt de stacks bij, en ruimt de oude mappen pas daarna op.",
|
||||
"paths_move_hint": "De instelling is opgeslagen, maar je data staat nog op de oude plek en elke app wijst daar nog naartoe. Verplaatsen kopieert eerst alles, werkt de apps bij, en ruimt de oude mappen pas daarna op.",
|
||||
"move_data": "Data verplaatsen",
|
||||
"move_data_confirm": "{n} map(pen) verplaatsen? De stacks worden gestopt, de data wordt gekopieerd en gecontroleerd, en pas daarna wordt het oude opgeruimd."
|
||||
"move_data_confirm": "{n} map(pen) verplaatsen? De apps worden gestopt, de data wordt gekopieerd en gecontroleerd, en pas daarna wordt het oude opgeruimd.",
|
||||
"manual_started": "Handmatig gestart",
|
||||
"manual_hint": "Deze apps draaien op deze host maar zijn niet door Server Up aangemaakt — handmatig gestart, of van vóór je Server Up ging gebruiken. Je kunt ze hier starten, stoppen en hun logs bekijken.",
|
||||
"containers_n": "{n} containers"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -397,6 +397,38 @@ check('balk staat halverwege', c.job.progress.pct === 50);
|
|||
|
||||
c.rpc = poortRpc;
|
||||
|
||||
// ── Eén lijst voor beheerde en handmatig gestarte apps ────────────────────
|
||||
// Ze stonden in twee lijsten onder elkaar, waarvan de tweede een kop, een
|
||||
// uitleg en een eigen vormgeving had. Wie zijn apps kwijt was, moest weten
|
||||
// dat er een tweede lijst bestond.
|
||||
c.stacks = [{name: 'sonarr', categories: ['media']},
|
||||
{name: 'vaultwarden', categories: ['tools']}];
|
||||
c.hostContainers = {containers: [
|
||||
{id: '1', name: 'oude-nginx', image: 'nginx:alpine', managed: false},
|
||||
{id: '2', name: 'sonarr', image: 'lscr.io/sonarr', managed: true},
|
||||
]};
|
||||
c.stackQuery = ''; c.stackCat = '';
|
||||
check('beheerde apps staan in de lijst', c.filteredStacks.length === 2);
|
||||
check('handmatig gestarte apps ook', c.filteredLos.length === 1);
|
||||
check('en niet dubbel', c.filteredLos[0].name === 'oude-nginx');
|
||||
|
||||
c.stackQuery = 'nginx';
|
||||
check('de zoekterm geldt voor allebei',
|
||||
c.filteredStacks.length === 0 && c.filteredLos.length === 1);
|
||||
c.stackQuery = 'sonarr';
|
||||
check('een beheerde app blijft over', c.filteredStacks.length === 1);
|
||||
check('en de handmatige valt af', c.filteredLos.length === 0);
|
||||
|
||||
c.stackQuery = 'lscr';
|
||||
check('zoeken kan ook op image', c.filteredLos.length === 0);
|
||||
c.stackQuery = 'alpine';
|
||||
check('van een handmatig gestarte app', c.filteredLos.length === 1);
|
||||
|
||||
// Een categoriefilter hoort ze te laten vallen: ze hébben geen categorie.
|
||||
c.stackQuery = ''; c.stackCat = 'media';
|
||||
check('categoriefilter laat handmatige apps vallen', c.filteredLos.length === 0);
|
||||
check('en houdt de beheerde over', c.filteredStacks.length === 1);
|
||||
|
||||
// Een leeg of onzinnig veld hoort geen verzoek te sturen.
|
||||
c.install.values.port = 0;
|
||||
gevraagd = [];
|
||||
|
|
|
|||
Loading…
Reference in a new issue