Explorar o código

docs: move Antora site content into repo (#1012)

James Read hai 1 mes
pai
achega
a39a660530
Modificáronse 100 ficheiros con 473 adicións e 1 borrados
  1. 34 0
      .github/workflows/docs-antora.yml
  2. 3 1
      .gitignore
  3. 1 0
      CONTRIBUTING.adoc
  4. 2 0
      README.md
  5. 15 0
      docs/antora.yml
  6. 40 0
      docs/modules/ROOT/check_chevron_links.py
  7. 24 0
      docs/modules/ROOT/check_no_h1.py
  8. 25 0
      docs/modules/ROOT/check_unnavigable.py
  9. 15 0
      docs/modules/ROOT/examples/action_customization/icons/config.yaml
  10. 9 0
      docs/modules/ROOT/examples/k8s_configmap.yml
  11. 37 0
      docs/modules/ROOT/examples/k8s_deployment.yml
  12. 21 0
      docs/modules/ROOT/examples/k8s_ingress.yml
  13. 19 0
      docs/modules/ROOT/examples/reverse-proxies/etc/npm-docker-compose.yml
  14. 25 0
      docs/modules/ROOT/examples/reverse-proxies/etc/reverse_proxy_nginx_dns.conf
  15. 48 0
      docs/modules/ROOT/examples/solutions/container-control-panel/config/config.yaml
  16. 2 0
      docs/modules/ROOT/examples/solutions/container-control-panel/config/containers.json
  17. 32 0
      docs/modules/ROOT/examples/solutions/directory-actions/config.yaml
  18. 28 0
      docs/modules/ROOT/examples/solutions/heating-control-panel/configs/config.yaml
  19. 2 0
      docs/modules/ROOT/examples/solutions/heating-control-panel/configs/heating.yaml
  20. 35 0
      docs/modules/ROOT/examples/solutions/primitive-password/password.js
  21. 36 0
      docs/modules/ROOT/examples/solutions/systemd-control-panel/config/config.yaml
  22. 4 0
      docs/modules/ROOT/examples/solutions/systemd-control-panel/config/systemd_units.json
  23. 10 0
      docs/modules/ROOT/examples/solutions/wol/config.yaml
  24. 6 0
      docs/modules/ROOT/examples/solutions/wol/config_docker.yaml
  25. BIN=BIN
      docs/modules/ROOT/images/action-button-iconify.png
  26. BIN=BIN
      docs/modules/ROOT/images/action-confirmation.png
  27. BIN=BIN
      docs/modules/ROOT/images/additionalNavigationLinks.png
  28. BIN=BIN
      docs/modules/ROOT/images/arg-datetime.png
  29. BIN=BIN
      docs/modules/ROOT/images/arg-suggestions-chrome.png
  30. BIN=BIN
      docs/modules/ROOT/images/arg-suggestions-firefox.png
  31. BIN=BIN
      docs/modules/ROOT/images/args-choices-entities.png
  32. BIN=BIN
      docs/modules/ROOT/images/args-choices-exec.png
  33. BIN=BIN
      docs/modules/ROOT/images/args-multiline-text.png
  34. BIN=BIN
      docs/modules/ROOT/images/args1.png
  35. BIN=BIN
      docs/modules/ROOT/images/args2.png
  36. BIN=BIN
      docs/modules/ROOT/images/args3.png
  37. BIN=BIN
      docs/modules/ROOT/images/args4.png
  38. BIN=BIN
      docs/modules/ROOT/images/authentik_login.png
  39. BIN=BIN
      docs/modules/ROOT/images/authentik_login2.png
  40. BIN=BIN
      docs/modules/ROOT/images/authentik_login3.png
  41. BIN=BIN
      docs/modules/ROOT/images/authentik_new_app.png
  42. BIN=BIN
      docs/modules/ROOT/images/authentik_provider_config.png
  43. BIN=BIN
      docs/modules/ROOT/images/authentik_provider_secrets.png
  44. BIN=BIN
      docs/modules/ROOT/images/authentik_select_oauth2.png
  45. BIN=BIN
      docs/modules/ROOT/images/blocked.png
  46. BIN=BIN
      docs/modules/ROOT/images/dashboard-display.png
  47. BIN=BIN
      docs/modules/ROOT/images/dashboard-heating-control-panel.png
  48. BIN=BIN
      docs/modules/ROOT/images/dashboard.png
  49. BIN=BIN
      docs/modules/ROOT/images/defaultUiHideNav.png
  50. BIN=BIN
      docs/modules/ROOT/images/defaultUiWithNav.png
  51. BIN=BIN
      docs/modules/ROOT/images/diagnostics.png
  52. BIN=BIN
      docs/modules/ROOT/images/directory-actions-screenshot.png
  53. BIN=BIN
      docs/modules/ROOT/images/exampleIcons.png
  54. BIN=BIN
      docs/modules/ROOT/images/executionButtons.png
  55. BIN=BIN
      docs/modules/ROOT/images/executionDialog.png
  56. BIN=BIN
      docs/modules/ROOT/images/fieldset.png
  57. BIN=BIN
      docs/modules/ROOT/images/flashyButton.png
  58. BIN=BIN
      docs/modules/ROOT/images/folders.png
  59. BIN=BIN
      docs/modules/ROOT/images/gitops.png
  60. BIN=BIN
      docs/modules/ROOT/images/hacs-custom-repo.png
  61. BIN=BIN
      docs/modules/ROOT/images/hacs-download.png
  62. BIN=BIN
      docs/modules/ROOT/images/hacs-dropdown.png
  63. BIN=BIN
      docs/modules/ROOT/images/hacs-search.png
  64. BIN=BIN
      docs/modules/ROOT/images/hass-add-integration.png
  65. BIN=BIN
      docs/modules/ROOT/images/hass-buttons.png
  66. BIN=BIN
      docs/modules/ROOT/images/hass-configure-integration.png
  67. BIN=BIN
      docs/modules/ROOT/images/hass-devices-and-services.png
  68. BIN=BIN
      docs/modules/ROOT/images/hassButtonSetup.png
  69. BIN=BIN
      docs/modules/ROOT/images/hassConfigYaml.png
  70. BIN=BIN
      docs/modules/ROOT/images/hassFileEditor.png
  71. BIN=BIN
      docs/modules/ROOT/images/hassFileEditorConfig.png
  72. BIN=BIN
      docs/modules/ROOT/images/hello-world.png
  73. BIN=BIN
      docs/modules/ROOT/images/iconify.png
  74. BIN=BIN
      docs/modules/ROOT/images/icons/Discord.png
  75. BIN=BIN
      docs/modules/ROOT/images/icons/GitHub.png
  76. BIN=BIN
      docs/modules/ROOT/images/icons/OliveTinLogo.png
  77. BIN=BIN
      docs/modules/ROOT/images/maxRate.png
  78. BIN=BIN
      docs/modules/ROOT/images/mrGreenAction.png
  79. BIN=BIN
      docs/modules/ROOT/images/mre.png
  80. BIN=BIN
      docs/modules/ROOT/images/mrgreen.gif
  81. BIN=BIN
      docs/modules/ROOT/images/npm.png
  82. BIN=BIN
      docs/modules/ROOT/images/page-title.png
  83. BIN=BIN
      docs/modules/ROOT/images/pocketid.png
  84. BIN=BIN
      docs/modules/ROOT/images/popupOutputOnly.png
  85. BIN=BIN
      docs/modules/ROOT/images/portDiagram.png
  86. BIN=BIN
      docs/modules/ROOT/images/sidebar.png
  87. BIN=BIN
      docs/modules/ROOT/images/snapshot-archive.png
  88. BIN=BIN
      docs/modules/ROOT/images/snapshot-download.png
  89. BIN=BIN
      docs/modules/ROOT/images/snapshots.png
  90. BIN=BIN
      docs/modules/ROOT/images/solution-k8s-hosted.png
  91. BIN=BIN
      docs/modules/ROOT/images/solution-systemd-control-panel.png
  92. BIN=BIN
      docs/modules/ROOT/images/solutions/container-control-panel/preview.png
  93. BIN=BIN
      docs/modules/ROOT/images/solutions/wol/preview.png
  94. BIN=BIN
      docs/modules/ROOT/images/ssh-diagram.png
  95. BIN=BIN
      docs/modules/ROOT/images/stream-deck/config.png
  96. BIN=BIN
      docs/modules/ROOT/images/stream-deck/inputs.png
  97. BIN=BIN
      docs/modules/ROOT/images/stream-deck/marketplace.png
  98. BIN=BIN
      docs/modules/ROOT/images/stream-deck/panel.png
  99. BIN=BIN
      docs/modules/ROOT/images/timeoutLogs.png
  100. BIN=BIN
      docs/modules/ROOT/images/topbar.png

+ 34 - 0
.github/workflows/docs-antora.yml

@@ -0,0 +1,34 @@
+name: Antora docs
+on:
+  push:
+    paths:
+      - 'docs/**'
+      - 'local-antora-playbook.yml'
+      - 'local-antora-playbook-ci.yml'
+      - '.github/workflows/docs-antora.yml'
+  pull_request:
+    paths:
+      - 'docs/**'
+      - 'local-antora-playbook.yml'
+      - 'local-antora-playbook-ci.yml'
+      - '.github/workflows/docs-antora.yml'
+
+jobs:
+  antora:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Install Node.js
+        uses: actions/setup-node@v4
+        with:
+          node-version: '20'
+
+      - name: Install Antora toolchain
+        run: npm i antora@3.1.14 asciidoctor-kroki@0.18.1 @asciidoctor/tabs@1.0.0-beta.6
+
+      - name: Generate docs site (smoke)
+        run: npx antora local-antora-playbook-ci.yml --log-level info

+ 3 - 1
.gitignore

@@ -19,4 +19,6 @@ OliveTin
 integration-tests/configs/authRequireGuestsToLogin/sessions.yaml
 webui
 webui.dev
-sessions.yaml
+sessions.yaml
+docs/build/
+build/

+ 1 - 0
CONTRIBUTING.adoc

@@ -58,6 +58,7 @@ make
 The project layout is reasonably straightforward;
 
 * See the `Makefile` for common targets. This project was originally created on top of Fedora, but it should be usable on Debian/your faveourite distro with minor changes (if any).
+* End-user documentation (AsciiDoc for link:https://docs.olivetin.app[docs.olivetin.app]) lives in `docs/` as an Antora component; the published site is built from the separate link:https://github.com/OliveTin/docs.olivetin.app[docs.olivetin.app] repository.
 * The API is defined in protobuf+Connect RPC - you will need to `make proto`.
 * The Go daemon is built from the `cmd` and `internal` directories mostly.
 * The webui is just a single page application with a bit of Javascript in the `webui` directory. This can happily be hosted on another webserver.

+ 2 - 0
README.md

@@ -20,6 +20,8 @@
 
 All documentation can be found at [docs.olivetin.app](https://docs.olivetin.app). This includes installation and usage guide, etc.
 
+The AsciiDoc sources for that site live in this repository under [`docs/`](docs/) (Antora component). The [docs.olivetin.app](https://github.com/OliveTin/docs.olivetin.app) repository contains the Antora playbook, theme supplemental files, and the workflow that publishes GitHub Pages.
+
 ## Use cases
 
 **Safely** give access to commands, for less technical people;

+ 15 - 0
docs/antora.yml

@@ -0,0 +1,15 @@
+---
+name: ROOT
+title: OliveTin
+version: ''
+display_version: 'Version 3k'
+start_page: index.adoc
+asciidoc:
+  attributes:
+    source-language: asciidoc@
+    table-caption: false
+    toclevels: 2
+nav:
+- modules/ROOT/nav.adoc
+
+

+ 40 - 0
docs/modules/ROOT/check_chevron_links.py

@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+
+import glob
+import re
+
+nav_file = open('nav.adoc', 'r')
+nav_string = nav_file.read()
+
+adoc_files = glob.glob('pages/**/*.adoc', recursive=True)
+
+filelist = dict()
+
+for file in adoc_files:
+    with open(file, 'r') as handle:
+        content = handle.read()
+
+        matches = re.findall(r'<<(.*?),?([\w\- ]+)>>', content)
+
+        for match in matches:
+            m = match
+
+            if match[0] == "":
+                m = match[1]
+            else:
+                m = match[0]
+
+            if content.count("#" + m) != 1:
+                if file not in filelist:
+                    filelist[file] = list()
+
+                filelist[file].append(m)
+
+
+print("Files:", len(filelist))
+
+for file in filelist.keys():
+    print(file)
+
+    for match in filelist[file]:
+        print("\t", match)

+ 24 - 0
docs/modules/ROOT/check_no_h1.py

@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+
+import glob
+import re
+
+adoc_files = glob.glob('pages/**/*.adoc', recursive=True)
+
+filelist = list()
+
+for file in adoc_files:
+    with open(file, 'r') as handle:
+        content = handle.read()
+
+        matches = re.findall('^= ', content, re.MULTILINE)
+
+        if len(matches) == 0:
+            filelist.append(file)
+
+
+print("Files:", len(filelist))
+
+for file in filelist:
+    print(file)
+

+ 25 - 0
docs/modules/ROOT/check_unnavigable.py

@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+# find .adoc files that are not navigable from the nav.adoc file
+
+import glob
+
+nav_file = open('nav.adoc', 'r')
+nav_string = nav_file.read()
+
+adoc_files = glob.glob('pages/**/*.adoc', recursive=True)
+
+unnavigable_files = []
+
+for file in adoc_files:
+    filename = file.replace("pages/", "")
+
+    if filename not in nav_string:
+        unnavigable_files.append(filename)
+
+
+unnavigable_files = sorted(unnavigable_files)
+
+print("Unnavigable files:", len(unnavigable_files))
+for file in unnavigable_files:
+    print(file)

+ 15 - 0
docs/modules/ROOT/examples/action_customization/icons/config.yaml

@@ -0,0 +1,15 @@
+actions:
+  - title: Unicode (emoji) alias icon
+    shell: echo "Hello!"
+    icon: smile
+
+  - title: Unicode (emoji) icon
+    shell: echo "Hello!"
+    icon: "&#128526;"
+
+  - title: Iconify Icon
+    icon: <iconify-icon icon="ant-design:bug-filled"></iconify-icon>
+
+  - title: HTML Image (jpg/png/gif/etc) icon
+    shell: echo "Hello!"
+    icon: '<img src = "custom-webui/icons/mrgreen.gif" style = "width: 1em;" />'

+ 9 - 0
docs/modules/ROOT/examples/k8s_configmap.yml

@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: olivetin-config
+data:
+  config.yaml: |
+    actions:
+      - title: "Hello world!"
+        shell: echo 'Hello World!'

+ 37 - 0
docs/modules/ROOT/examples/k8s_deployment.yml

@@ -0,0 +1,37 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata: 
+    name: olivetin
+spec: 
+  replicas: 1
+  selector: 
+    matchLabels:
+      app: olivetin
+  template:
+    metadata:
+      labels:
+        app: olivetin
+    spec:
+      containers: 
+        - name: olivetin
+          image: docker.io/jamesread/olivetin:latest
+          ports:
+            - containerPort: 1337
+          volumeMounts:
+            - name: olivetin-config
+              mountPath: "/config"
+              readOnly: true
+
+          livenessProbe:
+            exec:
+              command: 
+                - curl 
+                - localhost:1337
+            initialDelaySeconds: 5
+            periodSeconds: 30
+
+      volumes:
+        - name: olivetin-config
+          configMap: 
+            name: olivetin-config
+

+ 21 - 0
docs/modules/ROOT/examples/k8s_ingress.yml

@@ -0,0 +1,21 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata: 
+  name: olivetin-ingress
+spec:
+  defaultBackend: 
+    service: 
+      name: olivetin
+      port:
+        number: 1337
+  rules:
+    - host: olivetin.apps.ocp.teratan.net
+      http:
+        paths:
+          - path: /
+            pathType: Prefix
+            backend:
+              service:
+                name: olivetin
+                port:
+                  number: 1337

+ 19 - 0
docs/modules/ROOT/examples/reverse-proxies/etc/npm-docker-compose.yml

@@ -0,0 +1,19 @@
+services:
+  app:
+    image: 'jc21/nginx-proxy-manager:latest'
+    restart: unless-stopped
+    ports:
+      - '80:80'
+      - '81:81'
+      - '443:443'
+    volumes:
+      - ./data:/data
+      - ./letsencrypt:/etc/letsencrypt
+  olivetin:
+    container_name: olivetin
+    image: jamesread/olivetin
+    volumes:
+      - ./OliveTin:/config # replace host path or volume as needed
+    ports:
+      - "1337:1337"
+    restart: unless-stopped

+ 25 - 0
docs/modules/ROOT/examples/reverse-proxies/etc/reverse_proxy_nginx_dns.conf

@@ -0,0 +1,25 @@
+server {
+    listen 443 ssl;
+
+    ssl_certificate "/etc/nginx/conf.d/server.crt";
+    ssl_certificate_key "/etc/nginx/conf.d/server.key";
+
+    access_log  /var/log/nginx/ot.access.log  main;
+    error_log /var/log/nginx/ot.error.log notice;
+
+    server_name olivetin.example.com;
+
+    location / {
+        proxy_pass http://localhost:1337/;
+        proxy_redirect http://localhost:1337/ http://localhost/OliveTin/;
+    }
+
+    location /websocket {
+        proxy_set_header Upgrade "websocket";
+        proxy_set_header Connection "upgrade";
+        proxy_pass http://localhost:1337/websocket;
+        proxy_read_timeout 600s;
+        proxy_send_timeout 600s;
+    }
+}
+

+ 48 - 0
docs/modules/ROOT/examples/solutions/container-control-panel/config/config.yaml

@@ -0,0 +1,48 @@
+# This config has two actions which are applied to all "container" entities 
+# found in the entity file.
+#
+# Docs: http://localhost/docs.olivetin.app/docs/entities.html
+actions:
+  - title: Start {{ container.Names }}
+    icon: box
+    shell: docker start {{ container.Names }}
+    entity: container
+    triggers:
+      - Update container entity file
+
+  - title: Stop {{ container.Names }}
+    icon: box
+    shell: docker stop {{ container.Names }}
+    entity: container
+    triggers:
+      - Update container entity file
+
+  # This is a hidden action, that is run on startup, and every 5 minutes, and 
+  # when the above start/stop commands are run (see the `triggers` property).
+
+  - title: Update container entity file
+    shell: 'docker ps -a --format json > /etc/OliveTin/entities/containers.json'
+    hidden: true
+    execOnStartup: true
+    execOnCron: '*/5 * * * *'
+
+# Docs: http://docs.olivetin.app/entities.html
+entities:
+  - file: /etc/OliveTin/entities/containers.json
+    name: container
+
+# The only way to properly use entities, are to use them with a `fieldset` on
+# a dashboard.
+dashboards:
+  # This is the second dashboard.
+  - title: My Containers
+    contents:
+      - title: 'Container {{ container.Names }} ({{ container.Image }})'
+        entity: container
+        type: fieldset
+        contents:
+          - type: display
+            title: |
+              {{ container.RunningFor }} <br /><br /><strong>{{ container.State }}</strong>
+          - title: 'Start {{ container.Names }}'
+          - title: 'Stop {{ container.Names }}'

+ 2 - 0
docs/modules/ROOT/examples/solutions/container-control-panel/config/containers.json

@@ -0,0 +1,2 @@
+{"Command":"\"/bin/bash\"","CreatedAt":"2024-02-28 22:33:35 +0000 GMT","ID":"fcf468e18a0e","Image":"fedora","Labels":"maintainer=Clement Verna \u003ccverna@fedoraproject.org\u003e","LocalVolumes":"0","Mounts":"","Names":"minecraft","Networks":"bridge","Ports":"","RunningFor":"3 minutes ago","Size":"0B","State":"created","Status":"Created"}
+{"Command":"\"/bin/bash\"","CreatedAt":"2024-02-23 23:18:57 +0000 GMT","ID":"442dd6fe316a","Image":"fedora","Labels":"maintainer=Clement Verna \u003ccverna@fedoraproject.org\u003e","LocalVolumes":"0","Mounts":"","Names":"brave_shirley","Networks":"bridge","Ports":"","RunningFor":"4 days ago","Size":"0B","State":"created","Status":"Created"}

+ 32 - 0
docs/modules/ROOT/examples/solutions/directory-actions/config.yaml

@@ -0,0 +1,32 @@
+actions:
+  - title: check log directory
+    hidden: true
+    shell: |
+      function addDirectory {
+        COUNT=$(ls -l $1 | wc -l)
+        echo "- directory: $1" >> /etc/OliveTin/entities/directories.yaml
+        echo "  count: $COUNT" >> /etc/OliveTin/entities/directories.yaml
+      }
+
+      truncate -s 0 /etc/OliveTin/entities/directories.yaml
+      addDirectory /var/log/
+      addDirectory /home/xconspirisist/logs
+    execOnStartup: true
+    execOnCron: "* * * * *"
+
+  - title: clean {{ log_directory.directory }} ({{log_directory.count }} files)
+    shell: |
+      echo "Removing all files in {{ log_directory.directory }}"
+    entity: log_directory
+
+entities:
+  - name: log_directory
+    file: /etc/OliveTin/entities/directories.yaml
+
+dashboards:
+  - title: Log Actions
+    contents:
+      - entity: log_directory
+        type: fieldset
+        contents:
+          - title: clean {{ log_directory.directory }} ({{log_directory.count }} files)

+ 28 - 0
docs/modules/ROOT/examples/solutions/heating-control-panel/configs/config.yaml

@@ -0,0 +1,28 @@
+logLevel: "INFO"
+
+actions:
+  - title: Turn heating up
+    icon: '&#128316;'
+    shell: /opt/heating.sh up
+
+  - title: Turn heating down
+    icon: '&#128317;'
+    shell: /opt/heating.sh down
+
+entities:
+  - file: /etc/OliveTin/entities/heating.yaml
+    name: heating
+
+dashboards:
+  - title: Heating Control Panel
+    contents:
+      - title: "{{ heater.title }}"
+        entity: heating
+        type: fieldset
+        contents:
+          - type: display
+            title: |
+              <span class = "icon">&#127777;</span> <br />{{ heating.temperature }}
+
+          - title: Turn heating up
+          - title: Turn heating down

+ 2 - 0
docs/modules/ROOT/examples/solutions/heating-control-panel/configs/heating.yaml

@@ -0,0 +1,2 @@
+- title: Main heater
+  temperature: 20 degrees

+ 35 - 0
docs/modules/ROOT/examples/solutions/primitive-password/password.js

@@ -0,0 +1,35 @@
+const myPassword = 'sekrit'
+
+const domMain = document.getElementsByTagName('main')[0]
+domMain.style.display = 'none'
+
+const domPassword = document.createElement('input')
+const domLogin = document.createElement('button')
+
+function checkPassword () {
+  if (domPassword.value === myPassword) {
+    domMain.style.display = 'block'
+    domPassword.remove()
+    domLogin.remove()
+  } else {
+    window.alert('Incorrect password. Please try again.')
+  }
+}
+
+function setupPasswordForm () {
+  domPassword.setAttribute('type', 'password')
+  domPassword.addEventListener('keydown', (e) => {
+    if (e.key === 'Enter') {
+      checkPassword()
+    }
+  })
+
+  domLogin.innerText = 'Login'
+  domLogin.onclick = checkPassword
+
+  const domHeader = document.querySelector('header')
+  domHeader.appendChild(domPassword)
+  domHeader.appendChild(domLogin)
+}
+
+document.addEventListener('DOMContentLoaded', setupPasswordForm)

+ 36 - 0
docs/modules/ROOT/examples/solutions/systemd-control-panel/config/config.yaml

@@ -0,0 +1,36 @@
+actions:
+  - title: Stop {{ systemd_unit.unit }}
+    shell: systemctl stop {{ systemd_unit.unit }}
+    icon: <iconify-icon icon="zondicons:hand-stop"></iconify-icon>
+    entity: systemd_unit
+    triggers:
+      - Update services file
+
+  - title: Start {{ systemd_unit.unit }}
+    shell: systemctl start {{ systemd_unit.unit }}
+    icon: <iconify-icon icon="ic:round-directions-run"></iconify-icon>
+    entity: systemd_unit
+    triggers:
+      - Update services file
+
+  - title: Update services file
+    shell: systemctl list-units -a -o json --no-pager | jq -c 'map(select (.unit | contains ("upsilon", "podman", "boot.mount"))) | .[]'  > /etc/OliveTin/entities/systemd_units.json
+    hidden: true
+    execOnStartup: true
+
+entities:
+  - file: /etc/OliveTin/entities/systemd_units.json
+    name: systemd_unit
+
+dashboards:
+  - title: My Services
+    contents:
+      - title: '{{ systemd_unit.description }}'
+        type: fieldset
+        entity: systemd_unit
+        contents:
+          - title: 'Status: {{ systemd_unit.sub }}'
+            type: display
+
+          - title: Start {{ systemd_unit.unit }}
+          - title: Stop {{ systemd_unit.unit }}

+ 4 - 0
docs/modules/ROOT/examples/solutions/systemd-control-panel/config/systemd_units.json

@@ -0,0 +1,4 @@
+{"unit":"boot.mount","load":"loaded","active":"active","sub":"mounted","description":"/boot"}
+{"unit":"podman.service","load":"loaded","active":"inactive","sub":"dead","description":"Podman API Service"}
+{"unit":"upsilon-drone.service","load":"loaded","active":"active","sub":"running","description":"upsilon-drone"}
+{"unit":"podman.socket","load":"loaded","active":"active","sub":"listening","description":"Podman API Socket"}

+ 10 - 0
docs/modules/ROOT/examples/solutions/wol/config.yaml

@@ -0,0 +1,10 @@
+actions:
+  - title: WakeOnLan Server1
+    shell: ether-wake A8:5E:45:E4:FF:2A
+    icon: ping
+
+  - title: Install ether-wake on startup
+    shell: microdnf install -y net-tools
+    hidden: true
+    execOnStartup: true
+    timeout: 120

+ 6 - 0
docs/modules/ROOT/examples/solutions/wol/config_docker.yaml

@@ -0,0 +1,6 @@
+  - title: WakeOnLan Server1
+    # The r0gger/docker-wake-on-lan is a minimal container for WOL
+    # that can be run on the host network.
+    # It is not required to run the OliveTin container on the host network.
+    shell: |
+     docker run --rm --name wake-on-lan --net=host -e MAC='A8:5E:45:E4:FF:2A' r0gger/docker-wake-on-lan

BIN=BIN
docs/modules/ROOT/images/action-button-iconify.png


BIN=BIN
docs/modules/ROOT/images/action-confirmation.png


BIN=BIN
docs/modules/ROOT/images/additionalNavigationLinks.png


BIN=BIN
docs/modules/ROOT/images/arg-datetime.png


BIN=BIN
docs/modules/ROOT/images/arg-suggestions-chrome.png


BIN=BIN
docs/modules/ROOT/images/arg-suggestions-firefox.png


BIN=BIN
docs/modules/ROOT/images/args-choices-entities.png


BIN=BIN
docs/modules/ROOT/images/args-choices-exec.png


BIN=BIN
docs/modules/ROOT/images/args-multiline-text.png


BIN=BIN
docs/modules/ROOT/images/args1.png


BIN=BIN
docs/modules/ROOT/images/args2.png


BIN=BIN
docs/modules/ROOT/images/args3.png


BIN=BIN
docs/modules/ROOT/images/args4.png


BIN=BIN
docs/modules/ROOT/images/authentik_login.png


BIN=BIN
docs/modules/ROOT/images/authentik_login2.png


BIN=BIN
docs/modules/ROOT/images/authentik_login3.png


BIN=BIN
docs/modules/ROOT/images/authentik_new_app.png


BIN=BIN
docs/modules/ROOT/images/authentik_provider_config.png


BIN=BIN
docs/modules/ROOT/images/authentik_provider_secrets.png


BIN=BIN
docs/modules/ROOT/images/authentik_select_oauth2.png


BIN=BIN
docs/modules/ROOT/images/blocked.png


BIN=BIN
docs/modules/ROOT/images/dashboard-display.png


BIN=BIN
docs/modules/ROOT/images/dashboard-heating-control-panel.png


BIN=BIN
docs/modules/ROOT/images/dashboard.png


BIN=BIN
docs/modules/ROOT/images/defaultUiHideNav.png


BIN=BIN
docs/modules/ROOT/images/defaultUiWithNav.png


BIN=BIN
docs/modules/ROOT/images/diagnostics.png


BIN=BIN
docs/modules/ROOT/images/directory-actions-screenshot.png


BIN=BIN
docs/modules/ROOT/images/exampleIcons.png


BIN=BIN
docs/modules/ROOT/images/executionButtons.png


BIN=BIN
docs/modules/ROOT/images/executionDialog.png


BIN=BIN
docs/modules/ROOT/images/fieldset.png


BIN=BIN
docs/modules/ROOT/images/flashyButton.png


BIN=BIN
docs/modules/ROOT/images/folders.png


BIN=BIN
docs/modules/ROOT/images/gitops.png


BIN=BIN
docs/modules/ROOT/images/hacs-custom-repo.png


BIN=BIN
docs/modules/ROOT/images/hacs-download.png


BIN=BIN
docs/modules/ROOT/images/hacs-dropdown.png


BIN=BIN
docs/modules/ROOT/images/hacs-search.png


BIN=BIN
docs/modules/ROOT/images/hass-add-integration.png


BIN=BIN
docs/modules/ROOT/images/hass-buttons.png


BIN=BIN
docs/modules/ROOT/images/hass-configure-integration.png


BIN=BIN
docs/modules/ROOT/images/hass-devices-and-services.png


BIN=BIN
docs/modules/ROOT/images/hassButtonSetup.png


BIN=BIN
docs/modules/ROOT/images/hassConfigYaml.png


BIN=BIN
docs/modules/ROOT/images/hassFileEditor.png


BIN=BIN
docs/modules/ROOT/images/hassFileEditorConfig.png


BIN=BIN
docs/modules/ROOT/images/hello-world.png


BIN=BIN
docs/modules/ROOT/images/iconify.png


BIN=BIN
docs/modules/ROOT/images/icons/Discord.png


BIN=BIN
docs/modules/ROOT/images/icons/GitHub.png


BIN=BIN
docs/modules/ROOT/images/icons/OliveTinLogo.png


BIN=BIN
docs/modules/ROOT/images/maxRate.png


BIN=BIN
docs/modules/ROOT/images/mrGreenAction.png


BIN=BIN
docs/modules/ROOT/images/mre.png


BIN=BIN
docs/modules/ROOT/images/mrgreen.gif


BIN=BIN
docs/modules/ROOT/images/npm.png


BIN=BIN
docs/modules/ROOT/images/page-title.png


BIN=BIN
docs/modules/ROOT/images/pocketid.png


BIN=BIN
docs/modules/ROOT/images/popupOutputOnly.png


BIN=BIN
docs/modules/ROOT/images/portDiagram.png


BIN=BIN
docs/modules/ROOT/images/sidebar.png


BIN=BIN
docs/modules/ROOT/images/snapshot-archive.png


BIN=BIN
docs/modules/ROOT/images/snapshot-download.png


BIN=BIN
docs/modules/ROOT/images/snapshots.png


BIN=BIN
docs/modules/ROOT/images/solution-k8s-hosted.png


BIN=BIN
docs/modules/ROOT/images/solution-systemd-control-panel.png


BIN=BIN
docs/modules/ROOT/images/solutions/container-control-panel/preview.png


BIN=BIN
docs/modules/ROOT/images/solutions/wol/preview.png


BIN=BIN
docs/modules/ROOT/images/ssh-diagram.png


BIN=BIN
docs/modules/ROOT/images/stream-deck/config.png


BIN=BIN
docs/modules/ROOT/images/stream-deck/inputs.png


BIN=BIN
docs/modules/ROOT/images/stream-deck/marketplace.png


BIN=BIN
docs/modules/ROOT/images/stream-deck/panel.png


BIN=BIN
docs/modules/ROOT/images/timeoutLogs.png


BIN=BIN
docs/modules/ROOT/images/topbar.png


Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio