Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package hawk-apiserver for openSUSE:Factory 
checked in at 2026-11-13 18:36:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/hawk-apiserver (Old)
 and      /work/SRC/openSUSE:Factory/.hawk-apiserver.new.1251 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "hawk-apiserver"

Fri Nov 13 18:36:47 2026 rev:20 rq:1397330 version:0.7.0+git.1794052406.f1b2139

Changes:
--------
--- /work/SRC/openSUSE:Factory/hawk-apiserver/hawk-apiserver.changes    
2026-11-07 23:33:24.632524232 +0100
+++ /work/SRC/openSUSE:Factory/.hawk-apiserver.new.1251/hawk-apiserver.changes  
2026-11-13 18:41:09.069077348 +0100
@@ -1,0 +2,6 @@
+Fri Nov 13 12:09:10 UTC 2026 - Aleksei Burlakov <[email protected]>
+
+- Version 0.7.0+git.1794052406.f1b2139:
+  * Dev: implement /cib/live/wizards (Wizards) menu
+
+-------------------------------------------------------------------

Old:
----
  hawk-apiserver-0.6.8+git.1794043145.c24a18d.tar.gz

New:
----
  hawk-apiserver-0.7.0+git.1794052406.f1b2139.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ hawk-apiserver.spec ++++++
--- /var/tmp/diff_new_pack.7C07uR/_old  2026-11-13 18:41:09.941114243 +0100
+++ /var/tmp/diff_new_pack.7C07uR/_new  2026-11-13 18:41:09.942114286 +0100
@@ -19,7 +19,7 @@
 %define www_base %{_datadir}/hawk
 
 Name:           hawk-apiserver
-Version:        0.6.8+git.1794043145.c24a18d
+Version:        0.7.0+git.1794052406.f1b2139
 Release:        0
 Summary:        Web server and API provider for Hawk
 License:        GPL-3.0-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.7C07uR/_old  2026-11-13 18:41:09.983116020 +0100
+++ /var/tmp/diff_new_pack.7C07uR/_new  2026-11-13 18:41:09.989116274 +0100
@@ -3,8 +3,8 @@
     <param name="url">https://github.com/ClusterLabs/hawk-apiserver</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="versionformat">0.6.8+git.%ct.%h</param>
-    <param name="revision">master</param>
+    <param name="versionformat">0.7.0+git.%ct.%h</param>
+    <param name="revision">0.7.0</param>
   </service>
   <service name="recompress" mode="disabled">
     <param name="file">hawk-apiserver-*.tar</param>

++++++ hawk-apiserver-0.6.8+git.1794043145.c24a18d.tar.gz -> 
hawk-apiserver-0.7.0+git.1794052406.f1b2139.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/api/constraint_types.go 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/api/constraint_types.go
--- old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/api/constraint_types.go     
2026-11-07 10:19:05.000000000 +0100
+++ new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/api/constraint_types.go     
2026-11-07 12:53:26.000000000 +0100
@@ -14,7 +14,6 @@
                {Name: "Location", Path: "locations", Icon: "globe", 
HelpFilter: "location"},
                {Name: "Colocation", Path: "colocations", Icon: "tasks", 
HelpFilter: "colocation"},
                {Name: "Order", Path: "orders", Icon: "sort-amount-down", 
HelpFilter: "order"},
-               {Name: "Ticket", Path: "tickets", Icon: "ticket", HelpFilter: 
"ticket"},
        }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/api/constraint_types_test.go 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/api/constraint_types_test.go
--- 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/api/constraint_types_test.go    
    2026-11-07 10:19:05.000000000 +0100
+++ 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/api/constraint_types_test.go    
    2026-11-07 12:53:26.000000000 +0100
@@ -16,7 +16,6 @@
                {Name: "Location", Path: "locations", Icon: "globe", 
HelpFilter: "location"},
                {Name: "Colocation", Path: "colocations", Icon: "tasks", 
HelpFilter: "colocation"},
                {Name: "Order", Path: "orders", Icon: "sort-amount-down", 
HelpFilter: "order"},
-               {Name: "Ticket", Path: "tickets", Icon: "ticket", HelpFilter: 
"ticket"},
        }, types)
        tmpl, err := template.ParseFiles("../templates/layout.html", 
"../templates/constraint_types.html")
        require.NoError(t, err)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/api/wizards.go 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/api/wizards.go
--- old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/api/wizards.go      
1970-01-01 01:00:00.000000000 +0100
+++ new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/api/wizards.go      
2026-11-07 12:53:26.000000000 +0100
@@ -0,0 +1,164 @@
+package api
+
+import (
+       "bufio"
+       "bytes"
+       "context"
+       "encoding/json"
+       "fmt"
+       "log"
+       "net/http"
+       "net/url"
+       "os/exec"
+       "regexp"
+       "sort"
+       "strings"
+       "unicode"
+)
+
+type wizardSummary struct {
+       Name      string          `json:"name"`
+       Category  *string         `json:"category"`
+       Shortdesc *string         `json:"shortdesc"`
+       Longdesc  json.RawMessage `json:"longdesc"`
+}
+type wizardLink struct {
+       Name       string
+       Title      string
+       Href       string
+       Paragraphs []string
+       HelpID     string
+}
+type wizardCategory struct {
+       Title   string
+       Icon    string
+       ID      string
+       Wizards []wizardLink
+}
+
+func wizardDescription(raw json.RawMessage) string {
+       var text string
+       if json.Unmarshal(raw, &text) == nil {
+               return text
+       }
+       var wrapped struct {
+               Content string `json:"__content__"`
+       }
+       _ = json.Unmarshal(raw, &wrapped)
+       return wrapped.Content
+}
+
+// Match Wizard.wizard_ok and parse_brief, then WizardHelper's grouping.
+func wizardCategories(data []byte) ([]wizardCategory, error) {
+       scanner := bufio.NewScanner(bytes.NewReader(data))
+       scanner.Buffer(make([]byte, 4096), 4<<20)
+       groups := map[string][]wizardLink{}
+       workflows := map[string]bool{"60-nfsserver": true, "mariadb": true, 
"ocfs2-single": true, "webserver": true}
+       for scanner.Scan() {
+               var summary wizardSummary
+               if err := json.Unmarshal(scanner.Bytes(), &summary); err != nil 
{
+                       log.Printf("Error listing scripts: %s", scanner.Text())
+                       continue
+               }
+               if summary.Name == "" || summary.Shortdesc == nil {
+                       continue
+               }
+               category := "basic"
+               if summary.Category != nil {
+                       category = 
strings.ToLower(strings.TrimSpace(*summary.Category))
+                       if category == "script" || (category == "wizard" && 
workflows[summary.Name]) {
+                               continue
+                       }
+               }
+               category = strings.NewReplacer("/", " ", "\\", " ", ":", " 
").Replace(category)
+               description := 
strings.ReplaceAll(wizardDescription(summary.Longdesc), "\r\n", "\n")
+               paragraphs := []string{}
+               for _, paragraph := range strings.Split(description, "\n\n") {
+                       if strings.TrimSpace(paragraph) != "" {
+                               paragraphs = append(paragraphs, 
strings.ReplaceAll(paragraph, "\n", " "))
+                       }
+               }
+               groups[category] = append(groups[category], wizardLink{Name: 
summary.Name, Title: strings.TrimSpace(*summary.Shortdesc), Href: 
"/cib/live/wizards/" + url.PathEscape(summary.Name), Paragraphs: paragraphs})
+       }
+       if err := scanner.Err(); err != nil {
+               return nil, err
+       }
+       names := make([]string, 0, len(groups))
+       for category := range groups {
+               names = append(names, category)
+       }
+       sort.Strings(names)
+       categories := []wizardCategory{}
+       for i, name := range names {
+               title := strings.Join(strings.Fields(name), " ")
+               words := strings.Fields(title)
+               for j, word := range words {
+                       letters := []rune(word)
+                       letters[0] = unicode.ToUpper(letters[0])
+                       words[j] = string(letters)
+               }
+               title = strings.Join(words, " ")
+               if name == "wizard" {
+                       title = "Legacy Wizards"
+               }
+               icon := "magic"
+               switch name {
+               case "database":
+                       icon = "database"
+               case "fencing", "stonith":
+                       icon = "plug"
+               case "file system":
+                       icon = "hard-drive"
+               case "nfs":
+                       icon = "globe"
+               case "server":
+                       icon = "server"
+               case "wizard":
+                       icon = "list"
+               }
+               items := groups[name]
+               sort.SliceStable(items, func(i, j int) bool { return 
items[i].Name < items[j].Name })
+               for j := range items {
+                       items[j].HelpID = fmt.Sprintf("wizard-help-%d-%d", i, j)
+               }
+               categories = append(categories, wizardCategory{Title: title, 
Icon: icon, ID: regexp.MustCompile(` +`).ReplaceAllString(name, "_"), Wizards: 
items})
+       }
+       return categories, nil
+}
+
+func listWizards(ctx context.Context) ([]byte, error) {
+       // Match CrmScript.run: crmsh parses a quoted JSON command document.
+       cmd := exec.CommandContext(ctx, "/usr/sbin/crm", "-f", "/dev/stdin")
+       cmd.Stdin = strings.NewReader(`script json "[\"list\"]"` + "\n")
+       var stderr bytes.Buffer
+       cmd.Stderr = &stderr
+       out, err := cmd.Output()
+       if err != nil {
+               return nil, fmt.Errorf("%s: %w", 
strings.TrimSpace(stderr.String()), err)
+       }
+       return out, nil
+}
+
+func WizardsHandler(w http.ResponseWriter, r *http.Request) { serveWizards(w, 
r, listWizards) }
+func serveWizards(w http.ResponseWriter, r *http.Request, list 
func(context.Context) ([]byte, error)) {
+       if r.URL.Path != "/cib/live/wizards" && r.URL.Path != 
"/cib/live/wizards/" {
+               http.NotFound(w, r)
+               return
+       }
+       if r.Method != http.MethodGet && r.Method != http.MethodHead {
+               w.Header().Set("Allow", "GET, HEAD")
+               http.Error(w, "Method not allowed", 405)
+               return
+       }
+       data, err := list(r.Context())
+       if err != nil {
+               http.Error(w, "Unable to load wizards: "+err.Error(), 500)
+               return
+       }
+       categories, err := wizardCategories(data)
+       if err != nil {
+               http.Error(w, "Unable to load wizards: "+err.Error(), 500)
+               return
+       }
+       renderTemplate(w, "wizards", map[string]any{"Title": "Use a wizard", 
"Categories": categories})
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/api/wizards_test.go 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/api/wizards_test.go
--- old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/api/wizards_test.go 
1970-01-01 01:00:00.000000000 +0100
+++ new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/api/wizards_test.go 
2026-11-07 12:53:26.000000000 +0100
@@ -0,0 +1,74 @@
+package api
+
+import (
+       "bytes"
+       "context"
+       "fmt"
+       "html/template"
+       "net/http/httptest"
+       "testing"
+
+       "github.com/stretchr/testify/require"
+)
+
+func TestWizardCategories(t *testing.T) {
+       data := []byte(`{"name":"z","category":" DATABASE ","shortdesc":" Last 
","longdesc":"Line one\nline two\n\nSecond paragraph"}
+{"name":"a","category":"database","shortdesc":"First","longdesc":{"__content__":"Wrapped
 description"}}
+{"name":"default","shortdesc":"Basic"}
+{"name":"script","category":" Script ","shortdesc":"Hidden"}
+{"name":"mariadb","category":"wizard","shortdesc":"Hidden workflow"}
+{"name":"60-nfsserver","category":"wizard","shortdesc":"Hidden workflow"}
+{"name":"ocfs2-single","category":"wizard","shortdesc":"Hidden workflow"}
+{"name":"webserver","category":"wizard","shortdesc":"Hidden workflow"}
+{"name":"legacy","category":"wizard","shortdesc":"Legacy"}
+{"name":"filesystem","category":"File/System: Test","shortdesc":"Filesystem"}
+{"name":"missing-title"}
+{"error":"bad script"}
+`)
+       categories, err := wizardCategories(data)
+       require.NoError(t, err)
+       require.Len(t, categories, 4)
+       require.Equal(t, "Basic", categories[0].Title)
+       require.Equal(t, "basic", categories[0].ID)
+       require.Equal(t, "Database", categories[1].Title)
+       require.Equal(t, "database", categories[1].Icon)
+       require.Equal(t, "a", categories[1].Wizards[0].Name)
+       require.Equal(t, []string{"Wrapped description"}, 
categories[1].Wizards[0].Paragraphs)
+       require.Equal(t, "Last", categories[1].Wizards[1].Title)
+       require.Equal(t, []string{"Line one line two", "Second paragraph"}, 
categories[1].Wizards[1].Paragraphs)
+       require.Equal(t, "File System Test", categories[2].Title)
+       require.Equal(t, "file_system_test", categories[2].ID)
+       require.Equal(t, "Legacy Wizards", categories[3].Title)
+       require.Equal(t, "/cib/live/wizards/legacy", 
categories[3].Wizards[0].Href)
+}
+
+func TestWizardsTemplate(t *testing.T) {
+       categories, err := 
wizardCategories([]byte(`{"name":"test","category":"database","shortdesc":"A 
wizard","longdesc":"<script>unsafe</script>"}`))
+       require.NoError(t, err)
+       tmpl, err := template.ParseFiles("../templates/wizards.html")
+       require.NoError(t, err)
+       var body bytes.Buffer
+       require.NoError(t, tmpl.ExecuteTemplate(&body, "content", 
map[string]any{"Categories": categories}))
+       for _, value := range []string{`href="/cib/live/wizards/test"`, 
`aria-expanded="false"`, `<span class="wizard-category resource-type-link"`, 
`href="#database"`, `id="database"`, `data-toggle="collapse"`, `Database`, `A 
wizard`, `&lt;script&gt;unsafe&lt;/script&gt;`} {
+               require.Contains(t, body.String(), value)
+       }
+       require.NotContains(t, body.String(), "<script>unsafe</script>")
+}
+
+func TestWizardsHandler(t *testing.T) {
+       for _, tt := range []struct {
+               method, path string
+               status       int
+       }{
+               {"POST", "/cib/live/wizards", 405},
+               {"GET", "/cib/live/wizards/test", 404},
+       } {
+               response := httptest.NewRecorder()
+               serveWizards(response, httptest.NewRequest(tt.method, tt.path, 
nil), func(context.Context) ([]byte, error) { t.Fatal("unexpected command"); 
return nil, nil })
+               require.Equal(t, tt.status, response.Code)
+       }
+       response := httptest.NewRecorder()
+       serveWizards(response, httptest.NewRequest("GET", "/cib/live/wizards", 
nil), func(context.Context) ([]byte, error) { return nil, fmt.Errorf("crmsh 
unavailable") })
+       require.Equal(t, 500, response.Code)
+       require.Contains(t, response.Body.String(), "Unable to load wizards")
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/main.go 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/main.go
--- old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/main.go     2026-11-07 
10:19:05.000000000 +0100
+++ new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/main.go     2026-11-07 
12:53:26.000000000 +0100
@@ -128,6 +128,14 @@
                routehandler.ServeHTTP(w, r) // if not exactly "/cib/live/" --> 
Ruby fallback
        })
        // Register BOTH /cib/live/foo and /cib/live/foo/ to avoid conflicts 
with Ruby
+       mux.HandleFunc("/cib/live/wizards", authMiddleware(api.WizardsHandler))
+       mux.HandleFunc("/cib/live/wizards/", func(w http.ResponseWriter, r 
*http.Request) {
+               if r.URL.Path == "/cib/live/wizards/" {
+                       authMiddleware(api.WizardsHandler)(w, r)
+                       return
+               }
+               routehandler.ServeHTTP(w, r)
+       })
        mux.HandleFunc("/cib/live/commands", 
authMiddleware(api.CommandsHandler))
        mux.HandleFunc("/cib/live/commands/", 
authMiddleware(api.CommandsHandler))
        mux.HandleFunc("/cib/live/orders/new", 
authMiddleware(api.OrderNewHandler))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/static/css/wizards.css 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/static/css/wizards.css
--- old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/static/css/wizards.css      
1970-01-01 01:00:00.000000000 +0100
+++ new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/static/css/wizards.css      
2026-11-07 12:53:26.000000000 +0100
@@ -0,0 +1,8 @@
+.wizards [hidden] { display: none !important; }
+.wizard-category { width: 100%; cursor: pointer; }
+.wizard-chevron { margin-left: auto; margin-right: 20px; }
+.wizard-list { margin: 20px 15px 0; }
+.wizard-list .wizard-link { display: flex; align-items: center; margin-bottom: 
14px; padding: 10px; border: 1px solid #ddd; border-radius: 4px; background: 
#fff; color: #444; font-size: 15px; }
+.wizard-list .wizard-link:hover, .wizard-list .wizard-link:focus { background: 
linear-gradient(to bottom right, #fff, #e0e0e0); }
+.wizard-link > i { margin-left: auto; padding-left: 15px; }
+.wizard-link:hover > i, .wizard-link:focus > i { color: #00c081; }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/static/js/wizards.js 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/static/js/wizards.js
--- old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/static/js/wizards.js        
1970-01-01 01:00:00.000000000 +0100
+++ new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/static/js/wizards.js        
2026-11-07 12:53:26.000000000 +0100
@@ -0,0 +1,40 @@
+function showWizardHelp(id) {
+    document.querySelectorAll(".wizard-help").forEach(section => {
+        section.hidden = section.id !== id;
+    });
+}
+
+function toggleWizardCategory(button) {
+    const expanded = button.getAttribute("aria-expanded") !== "true";
+    document.querySelectorAll(".wizard-category").forEach(category => {
+        const active = category === button && expanded;
+        category.setAttribute("aria-expanded", String(active));
+        const list = 
document.getElementById(category.getAttribute("aria-controls"));
+        list.hidden = !active;
+        list.classList.toggle("in", active);
+        category.querySelector(".wizard-chevron").className = `fa 
fa-chevron-${active ? "up" : "down"} wizard-chevron`;
+    });
+}
+
+document.querySelectorAll(".wizard-category").forEach(button => {
+    button.addEventListener("click", event => {
+        // Handle the Ruby-compatible collapse markup here, without Bootstrap
+        // also toggling the same category through its delegated handler.
+        event.preventDefault();
+        event.stopPropagation();
+        toggleWizardCategory(button);
+    });
+    button.addEventListener("keydown", event => {
+        if (event.key === "Enter" || event.key === " ") {
+            event.preventDefault();
+            button.click();
+        }
+    });
+});
+document.querySelectorAll("[data-wizard-help]").forEach(link => {
+    link.addEventListener("mouseenter", () => 
showWizardHelp(link.dataset.wizardHelp));
+    link.addEventListener("focus", () => 
showWizardHelp(link.dataset.wizardHelp));
+});
+document.getElementById("monitoringMenu").classList.remove("in");
+document.getElementById("configurationMenu").classList.add("in");
+document.querySelector('a[href="/cib/live/wizards"]').setAttribute("aria-current",
 "page");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/templates/constraint_types.html 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/templates/constraint_types.html
--- 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/templates/constraint_types.html 
    2026-11-07 10:19:05.000000000 +0100
+++ 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/templates/constraint_types.html 
    2026-11-07 12:53:26.000000000 +0100
@@ -51,18 +51,6 @@
     <p>To create an order constraint, specify an ID, select the resources 
between which to define the constraint, and add a score. The score determines 
the location relationship between the resources: The constraint is mandatory if 
the score is greater than zero, otherwise it is only a suggestion. The default 
value is INFINITY. Keeping the option <code>Symmetrical</code> set to 
<code>Yes</code> (default) defines that the resources are stopped in reverse 
order.</p>
     <p>An example for use of an order constraint is a Web service (e.g. 
Apache) that depends on a certain IP address. Configure resources for the IP 
address and the Web service, then add an order constraint that defines that the 
IP address is started before Apache is started.</p>
     </section>
-    <section id="help-tickets" class="resource-type-help">
-    <h3>Ticket</h3>
-    <p>Tickets are a special type of constraint used for Geo clustering. A 
ticket grants the right to run certain resources on a specific cluster site.</p>
-    <p>To create a ticket constraint, specify a constraint ID, enter a 
ticket&#x27;s ID and add the resources that you want to depend on this ticket. 
Additionally, you can set a loss-policy to define what should happen to the 
resources if the ticket is revoked. The attribute <code>loss-policy</code> can 
have the following values:</p>
-    <ul>
-      <li><code>fence</code>: Fence the nodes that are running the relevant 
resources.</li>
-      <li><code>stop</code>: Stop the relevant resources.</li>
-      <li><code>freeze</code>: Do nothing to the relevant resources.</li>
-      <li><code>demote</code>: Demote relevant promoted resources.</li>
-    </ul>
-    <p>An example for a ticket constraint would be a primitive resource 
<code>rsc1</code> that depends on <code>ticketA</code>. If you set 
<code>loss-policy=&quot;fence&quot;</code>, the node that runs 
<code>rsc1</code> would be fenced in case <code>ticketA</code> is revoked from 
the cluster site this node belongs to.</p>
-    </section>
   </aside>
 </div>
 {{ end }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/templates/wizards.html 
new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/templates/wizards.html
--- old/hawk-apiserver-0.6.8+git.1794043145.c24a18d/templates/wizards.html      
1970-01-01 01:00:00.000000000 +0100
+++ new/hawk-apiserver-0.7.0+git.1794052406.f1b2139/templates/wizards.html      
2026-11-07 12:53:26.000000000 +0100
@@ -0,0 +1,32 @@
+{{ define "content" }}
+<link rel="stylesheet" href="/static/css/primitive_edit.css">
+<link rel="stylesheet" href="/static/css/resource_types.css">
+<link rel="stylesheet" href="/static/css/wizards.css">
+<script src="/static/js/wizards.js" defer></script>
+<div class="edit-layout resource-types wizards">
+  <div class="edit-left">
+    <h1><i class="fa fa-magic" aria-hidden="true"></i> Wizards</h1>
+    <ul class="nav nav-pills nav-stacked resource-type-list wizard-categories 
nav-bighelp nav-topspace">
+      {{ range .Categories }}
+      <li class="toggable">
+        <span class="wizard-category resource-type-link" role="button" 
tabindex="0" href="#{{ .ID }}" data-toggle="collapse" 
data-parent=".nav-bighelp" aria-expanded="false" aria-controls="{{ .ID }}">
+          <span class="resource-type-icon" aria-hidden="true"><i class="fa 
fa-{{ .Icon }}"></i></span>
+          <span class="resource-type-name">{{ .Title }}</span>
+          <i class="fa fa-chevron-down wizard-chevron" aria-hidden="true"></i>
+        </span>
+        <ul class="nav nav-pills nav-stacked wizard-list collapse" id="{{ .ID 
}}" hidden>
+          {{ range .Wizards }}
+          <li><a href="{{ .Href }}" class="wizard-link" aria-describedby="{{ 
.HelpID }}" data-wizard-help="{{ .HelpID }}"><span>{{ .Title }}</span><i 
class="fa fa-circle-plus" aria-hidden="true"></i></a></li>
+          {{ end }}
+        </ul>
+      </li>
+      {{ end }}
+    </ul>
+  </div>
+  <aside class="edit-right" aria-label="Wizard help">
+    {{ range .Categories }}{{ range .Wizards }}
+    <section id="{{ .HelpID }}" class="wizard-help" hidden><h2>{{ .Title 
}}</h2>{{ range .Paragraphs }}<p>{{ . }}</p>{{ end }}</section>
+    {{ end }}{{ end }}
+  </aside>
+</div>
+{{ end }}

++++++ vendor.tar.gz ++++++

Reply via email to