mirror of
https://github.com/selfhosters-cc/container-census.git
synced 2026-01-24 15:39:19 -06:00
Backend changes: - Updated go.mod module path from github.com/container-census to github.com/selfhosters-cc to match correct GitHub organization - Updated all import paths across codebase to use new module name - This fixes ldflags injection of BuildTime during compilation - BuildTime now correctly shows in /api/health response Frontend changes: - Added build time badge next to version in header - Shows date and time in compact format (e.g., "🔨 12/11/2025 8:06 PM") - Hover shows full timestamp - Only displays if build_time is not "unknown" The build script already sets BuildTime via ldflags, but it was being ignored because the module path in go.mod didn't match the ldflags path. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
116 lines
2.5 KiB
Go
116 lines
2.5 KiB
Go
package graph
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"net/http"
|
|
|
|
"github.com/selfhosters-cc/container-census/internal/plugins"
|
|
)
|
|
|
|
//go:embed frontend/bundle.js
|
|
var bundleJS []byte
|
|
|
|
//go:embed frontend/styles.css
|
|
var stylesCSS []byte
|
|
|
|
type GraphPlugin struct {
|
|
deps plugins.PluginDependencies
|
|
}
|
|
|
|
func NewGraphPlugin() *GraphPlugin {
|
|
return &GraphPlugin{}
|
|
}
|
|
|
|
func (p *GraphPlugin) Info() plugins.PluginInfo {
|
|
return plugins.PluginInfo{
|
|
ID: "graph-visualizer",
|
|
Name: "Graph Visualizer",
|
|
Version: "1.0.0",
|
|
Description: "Visualize container relationships using an interactive network graph",
|
|
Author: "Container Census Team",
|
|
BuiltIn: true,
|
|
}
|
|
}
|
|
|
|
func (p *GraphPlugin) Init(ctx context.Context, deps plugins.PluginDependencies) error {
|
|
p.deps = deps
|
|
return nil
|
|
}
|
|
|
|
func (p *GraphPlugin) Start(ctx context.Context) error {
|
|
p.deps.Logger.Info("Graph Visualizer plugin started")
|
|
return nil
|
|
}
|
|
|
|
func (p *GraphPlugin) Stop(ctx context.Context) error {
|
|
p.deps.Logger.Info("Graph Visualizer plugin stopped")
|
|
return nil
|
|
}
|
|
|
|
func (p *GraphPlugin) Routes() []plugins.Route {
|
|
return []plugins.Route{
|
|
{
|
|
Path: "/graph-data",
|
|
Method: "GET",
|
|
Handler: p.handleGraphData,
|
|
},
|
|
{
|
|
Path: "/bundle.js",
|
|
Method: "GET",
|
|
Handler: p.serveBundleJS,
|
|
},
|
|
{
|
|
Path: "/styles.css",
|
|
Method: "GET",
|
|
Handler: p.serveStylesCSS,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (p *GraphPlugin) Tab() *plugins.TabDefinition {
|
|
return &plugins.TabDefinition{
|
|
ID: "graph",
|
|
Label: "Graph",
|
|
Icon: "🕸️",
|
|
Order: 15,
|
|
}
|
|
}
|
|
|
|
func (p *GraphPlugin) Badges() []plugins.BadgeProvider {
|
|
return nil
|
|
}
|
|
|
|
func (p *GraphPlugin) ContainerEnricher() plugins.ContainerEnricher {
|
|
return nil
|
|
}
|
|
|
|
func (p *GraphPlugin) Settings() *plugins.SettingsDefinition {
|
|
return nil
|
|
}
|
|
|
|
func (p *GraphPlugin) NotificationChannelFactory() plugins.ChannelFactory {
|
|
return nil
|
|
}
|
|
|
|
// serveBundleJS serves the embedded JavaScript bundle
|
|
func (p *GraphPlugin) serveBundleJS(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/javascript")
|
|
w.Header().Set("Cache-Control", "public, max-age=3600")
|
|
w.Write(bundleJS)
|
|
}
|
|
|
|
// serveStylesCSS serves the embedded CSS file
|
|
func (p *GraphPlugin) serveStylesCSS(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "text/css")
|
|
w.Header().Set("Cache-Control", "public, max-age=3600")
|
|
w.Write(stylesCSS)
|
|
}
|
|
|
|
// Register registers the graph plugin with the plugin manager
|
|
func Register(manager *plugins.Manager) {
|
|
manager.RegisterBuiltIn("graph-visualizer", func() plugins.Plugin {
|
|
return NewGraphPlugin()
|
|
})
|
|
}
|