@@ -0,0 +1,8 @@
|
||||
{{define "aside"}}
|
||||
<aside>
|
||||
{{with .Garden}}
|
||||
<strong>{{.Name}}</strong>
|
||||
{{with .Description}}<p>{{.}}</p>{{end}}
|
||||
{{end}}
|
||||
</aside>
|
||||
{{end}}
|
||||
@@ -0,0 +1,11 @@
|
||||
{{define "footer"}}
|
||||
<footer>
|
||||
<span>Gardomatic · {{.CurrentYear}}</span>
|
||||
<nav aria-label='Weitere Informationen'>
|
||||
<a href='https://git.kleiax.de/kleiax/Gardomatic'>Git</a>
|
||||
<a href='https://kleiax.de'>Kleiax</a>
|
||||
<a href='{{webPath "healthcheck"}}'>Systemstatus</a>
|
||||
<a href='{{webPath "privacy"}}'>Datenschutz</a>
|
||||
</nav>
|
||||
</footer>
|
||||
{{end}}
|
||||
@@ -0,0 +1,11 @@
|
||||
{{define "garden_fields"}}
|
||||
{{$form := .Form}}
|
||||
<input type='hidden' name='csrf_token' value='{{.CSRFToken}}'>
|
||||
<label for='name'>Name</label>
|
||||
<input id='name' name='name' value='{{$form.Name}}' required {{if .Autofocus}}autofocus{{end}}>
|
||||
{{with index $form.Errors "name"}}<p class='field-error'>{{.}}</p>{{end}}
|
||||
<label for='description'>Beschreibung</label>
|
||||
<textarea id='description' name='description' rows='3'>{{$form.Description}}</textarea>
|
||||
{{with index $form.Errors "description"}}<p class='field-error'>{{.}}</p>{{end}}
|
||||
{{template "image_editor" (dict "ImageData" $form.ImageData "ImageID" $form.ImageID "Images" .Images "GardenID" .GardenID)}}
|
||||
{{end}}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{define "header"}}
|
||||
<header class='site-header'>
|
||||
<h1>Gardomatic</h1>
|
||||
{{with .Garden}}<a class='site-header-garden' href='{{webPath "garden.dashboard" .ID}}'>{{.Name}}</a>{{end}}
|
||||
{{if .IsAuthenticated}}
|
||||
<details class='user-menu'>
|
||||
<summary aria-label='Benutzermenü öffnen'>
|
||||
<span class='burger-icon' aria-hidden='true'></span>
|
||||
</summary>
|
||||
<div class='user-menu-content'>
|
||||
{{if .IsActivated}}<a href='{{webPath "gardens"}}'>Gärten</a>{{end}}
|
||||
{{with .CurrentUser}}<a href='{{with $.Garden}}{{pathWithQuery (webPath "account") "garden" .ID}}{{else}}{{webPath "account"}}{{end}}'>Nutzer <span>{{.Name}}</span></a>{{end}}
|
||||
{{if .IsActivated}}<a href='{{with .Garden}}{{pathWithQuery (webPath "settings") "garden" .ID}}{{else}}{{webPath "settings"}}{{end}}'>Einstellungen</a>{{end}}
|
||||
{{if isAppAdmin .CurrentUser}}<a href='{{gardenAwarePath (webPath "admin") .Garden}}'>Admin</a>{{end}}
|
||||
<form action='{{webPath "logout"}}' method='POST'>
|
||||
<input type='hidden' name='csrf_token' value='{{.CSRFToken}}'>
|
||||
<button type='submit' class='link-button'>Abmelden</button>
|
||||
</form>
|
||||
</div>
|
||||
</details>
|
||||
{{end}}
|
||||
</header>
|
||||
{{end}}
|
||||
@@ -0,0 +1,37 @@
|
||||
{{define "image_editor"}}
|
||||
<fieldset class='image-editor' data-image-editor>
|
||||
<legend>Bild</legend>
|
||||
<input type='hidden' name='image_data' value='{{.ImageData}}' data-image-value>
|
||||
<input type='hidden' name='image_id' value='{{.ImageID}}' data-image-id>
|
||||
<div class='image-preview' data-image-preview><span {{if .ImageData}}hidden{{end}}>Noch kein Bild gewählt</span></div>
|
||||
<div class='image-actions'>
|
||||
<label class='button secondary image-file-button'>Bild hochladen<input type='file' accept='image/jpeg,image/png,image/webp' data-image-file></label>
|
||||
<button type='button' class='secondary' data-image-camera>Foto aufnehmen</button>
|
||||
{{if .Images}}<button type='button' class='secondary' data-image-library-open>Aus Bilderdatenbank</button>{{end}}
|
||||
<button type='button' class='secondary' data-image-remove {{if not .ImageData}}hidden{{end}}>Bild entfernen</button>
|
||||
</div>
|
||||
{{if .Images}}<dialog class='image-library-dialog' data-image-library-dialog><h3>Bild aus der Bilderdatenbank auswählen</h3><div class='image-picker-grid'>{{range .Images}}<button type='button' class='image-picker-item {{if eqInt $.ImageID .ID}}is-selected{{end}}' data-image-library-select data-image-id='{{.ID}}' data-image-url='/g/{{$.GardenID}}/images/{{.ID}}/data'><img src='/g/{{$.GardenID}}/images/{{.ID}}/data' alt='{{if .FileName}}{{.FileName}}{{else}}Bild auswählen{{end}}' loading='lazy'><span>{{if .FileName}}{{.FileName}}{{else}}{{.CreatedAt.Format "02.01.2006"}}{{end}}</span></button>{{end}}</div><div class='image-actions'><button type='button' class='secondary' data-image-library-cancel>Abbrechen</button></div></dialog>{{end}}
|
||||
<dialog class='image-dialog' data-image-dialog>
|
||||
<h3>Bild zuschneiden</h3>
|
||||
<div class='cropper-stage'><img alt='Vorschau zum Zuschneiden' data-cropper-image></div>
|
||||
<div class='image-actions'>
|
||||
<button type='button' class='secondary' data-image-rotate-left aria-label='Nach links drehen'>↶ Drehen</button>
|
||||
<button type='button' class='secondary' data-image-rotate-right aria-label='Nach rechts drehen'>↷ Drehen</button>
|
||||
<button type='button' data-image-apply disabled>Übernehmen</button>
|
||||
<button type='button' class='secondary' data-image-cancel>Abbrechen</button>
|
||||
</div>
|
||||
<p class='field-error' data-image-error aria-live='polite'></p>
|
||||
</dialog>
|
||||
<dialog class='camera-dialog' data-camera-dialog>
|
||||
<h3>Foto aufnehmen</h3>
|
||||
<video autoplay muted playsinline data-camera-video></video>
|
||||
<p class='field-error' data-camera-error aria-live='polite'></p>
|
||||
<div class='image-actions'>
|
||||
<button type='button' class='secondary' data-camera-switch>Kamera wechseln</button>
|
||||
<button type='button' data-camera-capture disabled>Foto aufnehmen</button>
|
||||
<button type='button' class='secondary' data-camera-cancel>Abbrechen</button>
|
||||
</div>
|
||||
</dialog>
|
||||
<p class='muted'>Das Bild wird im Verhältnis 3:2 zugeschnitten und für die Kacheldarstellung optimiert.</p>
|
||||
</fieldset>
|
||||
{{end}}
|
||||
@@ -0,0 +1,8 @@
|
||||
{{define "journal_photo_editor"}}
|
||||
<div class='journal-photo-editor' data-image-editor data-journal-photo-editor>
|
||||
<input type='hidden' name='journal_photo_data' value='' data-image-value>
|
||||
<button type='button' class='secondary' data-image-camera>Foto mit Gerät aufnehmen</button>
|
||||
<dialog class='image-dialog' data-image-dialog><h3>Foto zuschneiden</h3><div class='cropper-stage'><img alt='Vorschau zum Zuschneiden' data-cropper-image></div><div class='image-actions'><button type='button' class='secondary' data-image-rotate-left>↶ Drehen</button><button type='button' class='secondary' data-image-rotate-right>↷ Drehen</button><button type='button' data-image-apply disabled>Übernehmen</button><button type='button' class='secondary' data-image-cancel>Abbrechen</button></div><p class='field-error' data-image-error aria-live='polite'></p></dialog>
|
||||
<dialog class='camera-dialog' data-camera-dialog><h3>Foto aufnehmen</h3><video autoplay muted playsinline data-camera-video></video><p class='field-error' data-camera-error aria-live='polite'></p><div class='image-actions'><button type='button' class='secondary' data-camera-switch>Kamera wechseln</button><button type='button' data-camera-capture disabled>Foto aufnehmen</button><button type='button' class='secondary' data-camera-cancel>Abbrechen</button></div></dialog>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,27 @@
|
||||
{{define "nav"}}
|
||||
{{if .IsAuthenticated}}
|
||||
{{if .IsActivated}}
|
||||
{{with .Garden}}
|
||||
<nav aria-label='Gartennavigation'>
|
||||
<a href='{{webPath "garden.dashboard" .ID}}'>Übersicht</a>
|
||||
<a href='{{webPath "plants" .ID}}'>Im Garten</a>
|
||||
<a href='{{webPath "species" .ID}}'>Pflanzen</a>
|
||||
<a href='{{webPath "locations" .ID}}'>Orte</a>
|
||||
<a href='{{webPath "tasks" .ID}}'>Aufgaben</a>
|
||||
<a href='{{webPath "garden.journal" .ID}}'>Tagebuch</a>
|
||||
<a href='{{webPath "garden.pinboard" .ID}}'>Pinnwand</a>
|
||||
<a href='{{webPath "garden.images" .ID}}'>Bilder</a>
|
||||
<a class='nav-search' href='{{webPath "garden.search" .ID}}' aria-label='Suche öffnen' title='Suche'><span aria-hidden='true'></span></a>
|
||||
</nav>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<nav aria-label='Accountnavigation'>
|
||||
<a href='{{webPath "activate"}}'>Account aktivieren</a>
|
||||
</nav>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<nav aria-label='Accountnavigation'>
|
||||
<a href='{{webPath "login"}}'>Anmelden</a>
|
||||
</nav>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -0,0 +1 @@
|
||||
{{define "pagination"}}{{with .Pagination}}<nav class='pagination' aria-label='Seitennavigation'>{{with .PreviousURL}}<a href='{{.}}'>Zurück</a>{{end}}<span>Seite {{.Page}} von {{.TotalPages}}</span>{{with .NextURL}}<a href='{{.}}'>Weiter</a>{{end}}</nav>{{end}}{{end}}
|
||||
@@ -0,0 +1,37 @@
|
||||
{{define "role_editor"}}
|
||||
<section class='panel role-editor' id='{{.ID}}' data-role-editor>
|
||||
<h3>{{.Title}}</h3>
|
||||
<p>{{.Description}}</p>
|
||||
<label for='{{.ID}}-select'>Rolle</label>
|
||||
<select id='{{.ID}}-select' data-role-select>
|
||||
{{range $index, $role := .Roles}}<option value='role-{{$index}}'>{{$role.Label}}</option>{{end}}
|
||||
<option value='new'>Neu</option>
|
||||
</select>
|
||||
|
||||
{{range $index, $role := .Roles}}
|
||||
<div data-role-pane='role-{{$index}}' {{if neInt $index 0}}hidden{{end}}>
|
||||
{{if $role.Editable}}
|
||||
<form method='POST' action='{{gardenAwarePath $.UpdateAction $.Garden}}' class='role-editor-form'>
|
||||
<input type='hidden' name='csrf_token' value='{{$.CSRFToken}}'>
|
||||
<input type='hidden' name='name' value='{{$role.Name}}'>
|
||||
<input type='hidden' name='scope' value='{{$.Scope}}'>
|
||||
{{if $role.EditLabel}}<label>Bezeichnung<input name='label' value='{{$role.Label}}' required></label>{{else}}<h4>{{$role.Label}}</h4>{{end}}
|
||||
<fieldset><legend>Rechte</legend>{{range $.Permissions}}<label class='checkbox'><input type='checkbox' name='permissions' value='{{.Name}}' {{if containsString $role.Permissions .Name}}checked{{end}}> {{.Label}} <span class='muted'>{{.Name}}</span></label>{{end}}</fieldset>
|
||||
<div class='actions'><button>Speichern</button>{{if $role.Deletable}}<button class='danger' formaction='{{gardenAwarePath $.DeleteAction $.Garden}}'>Rolle löschen</button>{{end}}</div>
|
||||
</form>
|
||||
{{else}}<p class='status'>{{$role.Label}} besitzt unveränderliche Eigentümerrechte.</p>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div data-role-pane='new' {{if .Roles}}hidden{{end}}>
|
||||
<form method='POST' action='{{gardenAwarePath .CreateAction .Garden}}' class='role-editor-form'>
|
||||
<input type='hidden' name='csrf_token' value='{{.CSRFToken}}'>
|
||||
<input type='hidden' name='scope' value='{{.Scope}}'>
|
||||
<label>Interner Name<input name='name' placeholder='helfer' required></label>
|
||||
<label>Bezeichnung<input name='label' required></label>
|
||||
<fieldset><legend>Rechte</legend>{{range .Permissions}}<label class='checkbox'><input type='checkbox' name='permissions' value='{{.Name}}'> {{.Label}} <span class='muted'>{{.Name}}</span></label>{{end}}</fieldset>
|
||||
<button>Rolle anlegen</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
@@ -0,0 +1,8 @@
|
||||
{{define "season_range"}}
|
||||
<fieldset class='season-range'><legend>{{.Legend}}</legend><div class='form-grid season-range-grid'>
|
||||
<label>Monat von<select name='{{.Prefix}}_month_from'><option value='0'>Nicht angegeben</option>{{range months}}<option value='{{.Value}}' {{if eqInt $.Month .Value}}selected{{end}}>{{.Label}}</option>{{end}}</select></label>
|
||||
<label>Tag von<input type='number' min='1' max='31' name='{{.Prefix}}_day_from' value='{{if .Day}}{{.Day}}{{else}}1{{end}}'></label>
|
||||
<label>Zeitraum<input type='number' min='0' name='{{.Prefix}}_duration' value='{{.Duration}}'></label>
|
||||
<label>Einheit<select name='{{.Prefix}}_duration_unit'><option value='day' {{if eqString .Unit "day"}}selected{{end}}>Tage</option><option value='week' {{if eqString .Unit "week"}}selected{{end}}>Wochen</option><option value='month' {{if eqString .Unit "month"}}selected{{end}}>Monate</option></select></label>
|
||||
</div></fieldset>
|
||||
{{end}}
|
||||
@@ -0,0 +1,19 @@
|
||||
{{define "settings_nav"}}
|
||||
<aside class='settings-sidebar panel'>
|
||||
<nav aria-label='Einstellungsbereiche'>
|
||||
{{if eqString .Kind "admin"}}
|
||||
<a href='#lifecycle-settings'>Pflanzenlebensdauer</a>
|
||||
<a href='#mail-settings'>Mailversand</a>
|
||||
<a href='#environment-settings'>Umgebung</a>
|
||||
<a href='#users-settings'>Nutzer und Rechte</a>
|
||||
<a href='#roles-settings'>Rollen</a>
|
||||
<a href='#species-categories'>Artenkategorien</a>
|
||||
<a href='#task-priorities'>Aufgabenprioritäten</a>
|
||||
{{else}}
|
||||
<a href='#list-settings'>Seitengröße</a>
|
||||
<a href='#view-settings'>Ansichten</a>
|
||||
<a href='#editor-settings'>Texteingabe</a>
|
||||
{{end}}
|
||||
</nav>
|
||||
</aside>
|
||||
{{end}}
|
||||
@@ -0,0 +1,9 @@
|
||||
{{define "tag_editor"}}
|
||||
<label for='keywords'>Tags</label>
|
||||
<div class='tag-editor' data-tag-editor>
|
||||
<div class='tag-bubbles' data-tag-bubbles></div>
|
||||
<input id='keywords' name='keywords' value='{{.Form.Keywords}}' placeholder='Tag eingeben …' autocomplete='off' data-tag-input>
|
||||
<div class='tag-suggestions' data-tag-suggestions role='listbox' hidden>{{range .TagSuggestions}}<button type='button' data-tag-suggestion='{{.}}'>{{.}}</button>{{end}}</div>
|
||||
</div>
|
||||
<p class='muted'>Mit Enter oder Komma übernehmen. Bereits verwendete Tags werden vorgeschlagen.</p>
|
||||
{{end}}
|
||||
@@ -0,0 +1,11 @@
|
||||
{{define "task_fields"}}{{$form:=.Form}}{{$prefix:=.Prefix}}
|
||||
<label>Name<input name='{{$prefix}}title' value='{{$form.Title}}' required></label>
|
||||
<label>Beschreibung<textarea name='{{$prefix}}description' rows='4'>{{$form.Description}}</textarea></label>
|
||||
<label>Tags</label><div class='tag-editor' data-tag-editor><div class='tag-bubbles' data-tag-bubbles></div><input name='{{$prefix}}keywords' value='{{$form.Keywords}}' placeholder='Tag eingeben …' autocomplete='off' data-tag-input><div class='tag-suggestions' data-tag-suggestions role='listbox' hidden>{{range .TagSuggestions}}<button type='button' data-tag-suggestion='{{.}}'>{{.}}</button>{{end}}</div></div>
|
||||
{{if .ShowPlant}}<label>Pflanze (optional)<select name='{{$prefix}}plant_id' {{if .LockPlant}}disabled aria-disabled='true'{{end}}>{{if and .LockPlant .PendingPlantName}}<option value='0' selected>{{.PendingPlantName}} · wird beim Speichern angelegt</option>{{else}}<option value='0'>Keine</option>{{range .Plants}}<option value='{{.ID}}' {{if eqInt $form.PlantID .ID}}selected{{end}}>{{.Name}}</option>{{end}}{{end}}</select></label>{{end}}
|
||||
<label>Ort (optional)<select name='{{$prefix}}location_id'><option value='0'>Keiner</option>{{range .Locations}}<option value='{{.ID}}' {{if eqInt $form.LocationID .ID}}selected{{end}}>{{.Name}}</option>{{end}}</select></label>
|
||||
<div class='form-grid'><label>Fällig ab<input type='date' name='{{$prefix}}due_at_start' value='{{$form.DueAtStart}}'></label><label>Fällig bis<input type='date' name='{{$prefix}}due_at_end' value='{{$form.DueAtEnd}}'></label></div>
|
||||
<fieldset><legend>Wiederholung</legend><div class='form-grid'><label>Alle<input type='number' min='1' name='{{$prefix}}recurrence_interval' value='{{$form.RecurrenceInterval}}'></label><label>Einheit<select name='{{$prefix}}recurrence'><option value=''>Keine</option><option value='daily' {{if eqString $form.Recurrence "daily"}}selected{{end}}>Tage</option><option value='weekly' {{if eqString $form.Recurrence "weekly"}}selected{{end}}>Wochen</option><option value='monthly' {{if eqString $form.Recurrence "monthly"}}selected{{end}}>Monate</option><option value='yearly' {{if eqString $form.Recurrence "yearly"}}selected{{end}}>Jahre</option></select></label></div></fieldset>
|
||||
<label>Priorität<select name='{{$prefix}}priority'>{{range .TaskPriorities}}<option value='{{.Value}}' {{if eqInt $form.Priority .Value}}selected{{end}}>{{.Name}}</option>{{end}}</select></label>
|
||||
<label>Pflanzenstatus nach Erledigung<select name='{{$prefix}}status_on_completion'><option value=''>Nicht ändern</option>{{range plantStatuses}}<option value='{{.Value}}' {{if eqString $form.PlantStatusOnCompletion .Value}}selected{{end}}>{{.Label}}</option>{{end}}</select></label>
|
||||
{{end}}
|
||||
@@ -0,0 +1,4 @@
|
||||
{{define "view_toggle"}}<button type='button' class='view-toggle' data-view-toggle='{{.}}' aria-label='Zwischen Listen- und Kachelansicht wechseln' title='Ansicht wechseln'>
|
||||
<svg class='view-toggle-grid-icon' viewBox='0 0 24 24' aria-hidden='true'><rect x='3' y='3' width='7' height='7' rx='1'/><rect x='14' y='3' width='7' height='7' rx='1'/><rect x='3' y='14' width='7' height='7' rx='1'/><rect x='14' y='14' width='7' height='7' rx='1'/></svg>
|
||||
<svg class='view-toggle-list-icon' viewBox='0 0 24 24' aria-hidden='true'><rect x='3' y='4' width='4' height='4' rx='1'/><path d='M10 6h11'/><rect x='3' y='10' width='4' height='4' rx='1'/><path d='M10 12h11'/><rect x='3' y='16' width='4' height='4' rx='1'/><path d='M10 18h11'/></svg>
|
||||
</button>{{end}}
|
||||
Reference in New Issue
Block a user