11// foundry.templ renders the admin Foundry VTT module management page.
2- // Allows admins to view and update the module version and see the install URL.
2+ // Allows admins to view module status, upload new versions, and trigger
3+ // redeployment to notify Foundry VTT clients of updates.
34
45package admin
56
67import (
8+ " fmt"
79 " github.com/keyxmakerx/chronicle/internal/templates/layouts"
810)
911
@@ -21,9 +23,26 @@ templ AdminFoundryModulePage(data FoundryModuleData) {
2123 <a href =" /admin" class =" btn-secondary text-sm" >Back</a >
2224 </div >
2325
24- // Current status.
26+ // Current status + redeploy .
2527 <div class =" card p-6" >
26- <h2 class =" text-lg font-semibold text-fg mb-4" >Module Status</h2 >
28+ <div class =" flex items-center justify-between mb-4" >
29+ <h2 class =" text-lg font-semibold text-fg" >Module Status</h2 >
30+ <form
31+ method =" POST"
32+ action =" /admin/foundry/redeploy"
33+ hx-post =" /admin/foundry/redeploy"
34+ >
35+ <input type =" hidden" name =" csrf_token" value ={ data.CSRFToken }/>
36+ <button
37+ type =" submit"
38+ class =" btn-primary text-sm inline-flex items-center gap-2"
39+ title =" Bump patch version to notify Foundry clients of an update"
40+ >
41+ <i class =" fa-solid fa-rotate" ></i >
42+ Redeploy
43+ </button >
44+ </form >
45+ </div >
2746 <div class =" grid grid-cols-1 sm:grid-cols-2 gap-4" >
2847 <div >
2948 <label class =" block text-xs font-medium text-fg-muted mb-1" >Current Version</label >
@@ -34,6 +53,10 @@ templ AdminFoundryModulePage(data FoundryModuleData) {
3453 <p class =" text-sm font-mono text-fg" >chronicle-sync</p >
3554 </div >
3655 </div >
56+ <p class =" text-xs text-fg-muted mt-3" >
57+ <i class =" fa-solid fa-circle-info mr-1" ></i >
58+ Redeploy bumps the patch version so Foundry VTT clients see an available update.
59+ </p >
3760 </div >
3861
3962 // Install URL.
@@ -64,13 +87,75 @@ templ AdminFoundryModulePage(data FoundryModuleData) {
6487 </p >
6588 </div >
6689
67- // Update version.
90+ // Upload module zip.
91+ <div class =" card p-6" >
92+ <h2 class =" text-lg font-semibold text-fg mb-4" >Upload Module</h2 >
93+ <p class =" text-sm text-fg-secondary mb-4" >
94+ Upload a new version of the module as a zip file. The zip should contain
95+ a <code class =" text-xs bg-surface-alt px-1 rounded" >module.json</code > and
96+ all module files. Manifest and download URLs will be rewritten automatically.
97+ </p >
98+ <form
99+ method =" POST"
100+ action =" /admin/foundry/upload"
101+ hx-post =" /admin/foundry/upload"
102+ hx-encoding =" multipart/form-data"
103+ class =" space-y-3"
104+ >
105+ <input type =" hidden" name =" csrf_token" value ={ data.CSRFToken }/>
106+ <div >
107+ <label for =" module_zip" class =" block text-sm font-medium text-fg-body mb-1" >Module Zip</label >
108+ <input
109+ type =" file"
110+ id =" module_zip"
111+ name =" module_zip"
112+ accept =" .zip"
113+ required
114+ class =" input w-full file:mr-4 file:py-1 file:px-3 file:rounded file:border-0 file:text-sm file:bg-accent file:text-accent-fg"
115+ />
116+ </div >
117+ <p class =" text-xs text-fg-muted" >Max 10 MB. Must contain a module.json file.</p >
118+ <button type =" submit" class =" btn-primary text-sm" >
119+ <i class =" fa-solid fa-upload mr-1" ></i >
120+ Upload & Replace
121+ </button >
122+ </form >
123+ </div >
124+
125+ // Module files.
126+ if len (data.Files ) > 0 {
127+ <div class =" card p-6" >
128+ <h2 class =" text-lg font-semibold text-fg mb-4" >
129+ Module Files
130+ <span class =" text-sm font-normal text-fg-muted ml-2" >{ fmt.Sprintf (" (%d files)" , len (data.Files )) }</span >
131+ </h2 >
132+ <div class =" overflow-x-auto" >
133+ <table class =" w-full text-sm" >
134+ <thead >
135+ <tr class =" border-b border-border" >
136+ <th class =" text-left text-xs font-medium text-fg-muted px-3 py-2" >File</th >
137+ <th class =" text-right text-xs font-medium text-fg-muted px-3 py-2" >Size</th >
138+ </tr >
139+ </thead >
140+ <tbody >
141+ for _ , f := range data.Files {
142+ <tr class =" border-b border-border/50" >
143+ <td class =" px-3 py-2 font-mono text-xs text-fg" >{ f.Path }</td >
144+ <td class =" px-3 py-2 text-xs text-fg-secondary text-right" >{ formatBytes (f.Size ) }</td >
145+ </tr >
146+ }
147+ </tbody >
148+ </table >
149+ </div >
150+ </div >
151+ }
152+
153+ // Update version (manual).
68154 <div class =" card p-6" >
69- <h2 class =" text-lg font-semibold text-fg mb-4" >Update Module Version</h2 >
155+ <h2 class =" text-lg font-semibold text-fg mb-4" >Set Version Manually </h2 >
70156 <p class =" text-sm text-fg-secondary mb-4" >
71- Bump the module version to notify Foundry VTT clients that an update is available.
72- Foundry checks the manifest URL periodically and shows an update badge when the
73- version changes.
157+ Override the module version to a specific value. Use this if you need
158+ to set an exact version rather than auto-bumping.
74159 </p >
75160 <form
76161 method =" POST"
@@ -108,7 +193,7 @@ templ AdminFoundryModulePage(data FoundryModuleData) {
108193 <ul class =" text-sm text-fg-secondary leading-relaxed space-y-1 list-disc ml-4" >
109194 <li >The module manifest and zip are served directly from this Chronicle instance.</li >
110195 <li >Foundry VTT fetches the manifest URL to check for updates.</li >
111- <li >When you bump the version, Foundry will show an update notification to all users .</li >
196+ <li >Upload a new zip to replace module files, then redeploy to notify clients .</li >
112197 <li >The module zip is generated on-the-fly from the <code class =" text-xs bg-surface-alt px-1 rounded" >foundry-module/</code > directory.</li >
113198 </ul >
114199 </div >
0 commit comments