Öffentliche Dateiansicht: Raw-Dateien, Tree, Releases und Issues sind ohne Login verfügbar.
internal/api/templates/logs.html Raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
{{define "logs"}}
<!DOCTYPE html>
<html lang="en" data-bs-theme="dark">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Privacy Guard · Logs</title>
  {{template "head" .}}
  {{template "styles" .}}
  <style>
    #log-box {
      height: calc(100vh - 230px);
      overflow-y: auto;
      background: #0d1117;
      border-radius: .375rem;
      padding: .75rem 1rem;
      font-family: monospace;
      font-size: .8rem;
      white-space: pre-wrap;
      word-break: break-all;
    }
  </style>
</head>
<body class="bg-body">

{{template "navbar" .}}

<div class="d-flex">
  {{template "sidebar" .}}

  <main class="flex-grow-1 p-4 overflow-auto">
    <div class="card">
      <div class="card-header d-flex align-items-center justify-content-between">
        <div class="d-flex align-items-center gap-3">
          <span class="fw-semibold">Live Log</span>
          {{if gt (len .Ports) 1}}
          <div class="btn-group btn-group-sm">
            {{range .Ports}}<a href="/logs?port={{.}}"
              class="btn btn-outline-secondary{{if eq . $.ActivePort}} active{{end}}">:{{.}}</a>{{end}}
          </div>
          {{end}}
        </div>
        <span class="text-success small htmx-indicator align-items-center gap-1">
          <span class="spinner-grow spinner-grow-sm"></span> live
        </span>
      </div>
      <div class="card-body p-0">
        <div id="log-box"
          data-tail-url="/ui/logs/tail?port={{.ActivePort}}">{{if .InitialLog}}{{.InitialLog}}{{else}}<span class="text-secondary">No log entries (Port: {{.ActivePort}})</span>{{end}}</div>
      </div>
      <div class="card-footer text-secondary small">
        Every 2 seconds · Max 10 MB / file · No content, no PII values
      </div>
    </div>
  </main>
</div>
<script>
  (function() {
    const box = document.getElementById('log-box');
    const indicator = document.querySelector('.htmx-indicator');
    if (!box) return;
    const url = box.getAttribute('data-tail-url');
    if (!url) return;

    async function refresh() {
      try {
        if (indicator) indicator.style.display = 'inline-flex';
        const res = await fetch(url, { credentials: 'same-origin', cache: 'no-store' });
        if (res.redirected) {
          window.location.href = res.url;
          return;
        }
        if (res.status === 401) {
          window.location.href = '/login';
          return;
        }
        box.innerHTML = await res.text();
        box.scrollTop = box.scrollHeight;
      } catch (_) {
      } finally {
        if (indicator) indicator.style.display = '';
      }
    }

    refresh();
    window.setInterval(refresh, 2000);
  })();
</script>
</body>
</html>
{{end}}