Skip to content

Commit 44c8cbe

Browse files
committed
feat(vers): add version number to front
1 parent a3fbcee commit 44c8cbe

File tree

10 files changed

+68
-24
lines changed

10 files changed

+68
-24
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ APP_DNS=sign.your-domain.com
44
ACKIFY_BASE_URL=https://sign.your-domain.com
55
ACKIFY_ORGANISATION="Your Organization Name"
66
ACKIFY_LOG_LEVEL=info
7+
ACKIFY_LOG_FORMAT=classic
78

89
# Database Configuration
910
POSTGRES_USER=ackifyr

backend/cmd/community/main.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ import (
1616
"github.com/btouchard/ackify-ce/backend/pkg/web"
1717
)
1818

19+
// Build-time variables set via ldflags
20+
var (
21+
Version = "dev"
22+
Commit = "unknown"
23+
BuildDate = "unknown"
24+
)
25+
1926
//go:embed all:web/dist
2027
var frontend embed.FS
2128

@@ -27,9 +34,13 @@ func main() {
2734
log.Fatalf("Failed to load config: %v", err)
2835
}
2936

30-
logger.SetLevel(logger.ParseLevel(cfg.Logger.Level))
37+
logger.SetLevelAndFormat(logger.ParseLevel(cfg.Logger.Level), cfg.Logger.Format)
38+
logger.Logger.Info("Starting Ackify Community Edition",
39+
"version", Version,
40+
"commit", Commit,
41+
"build_date", BuildDate)
3142

32-
server, err := web.NewServer(ctx, cfg, frontend)
43+
server, err := web.NewServer(ctx, cfg, frontend, Version)
3344
if err != nil {
3445
log.Fatalf("Failed to create server: %v", err)
3546
}

backend/internal/infrastructure/config/config.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ type ServerConfig struct {
4949
}
5050

5151
type LoggerConfig struct {
52-
Level string
52+
Level string
53+
Format string // "classic" or "json"
5354
}
5455

5556
type MailConfig struct {
@@ -131,6 +132,7 @@ func Load() (*Config, error) {
131132
config.Server.ListenAddr = getEnv("ACKIFY_LISTEN_ADDR", ":8080")
132133

133134
config.Logger.Level = getEnv("ACKIFY_LOG_LEVEL", "info")
135+
config.Logger.Format = getEnv("ACKIFY_LOG_FORMAT", "classic")
134136

135137
// Parse admin emails
136138
adminEmailsStr := getEnv("ACKIFY_ADMIN_EMAILS", "")

backend/pkg/logger/logger.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,30 @@ import (
1010
var Logger *slog.Logger
1111

1212
func init() {
13-
SetLevel(slog.LevelInfo)
13+
SetLevelAndFormat(slog.LevelInfo, "classic")
1414
}
1515

1616
func SetLevel(level slog.Level) {
17-
Logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
17+
SetLevelAndFormat(level, "classic")
18+
}
19+
20+
func SetLevelAndFormat(level slog.Level, format string) {
21+
opts := &slog.HandlerOptions{
1822
Level: level,
19-
}))
23+
}
24+
25+
var handler slog.Handler
26+
switch strings.ToLower(strings.TrimSpace(format)) {
27+
case "json":
28+
handler = slog.NewJSONHandler(os.Stdout, opts)
29+
case "classic", "text":
30+
handler = slog.NewTextHandler(os.Stdout, opts)
31+
default:
32+
// Default to classic (text) format
33+
handler = slog.NewTextHandler(os.Stdout, opts)
34+
}
35+
36+
Logger = slog.New(handler)
2037
}
2138

2239
func ParseLevel(levelStr string) slog.Level {

backend/pkg/web/server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type Server struct {
3838
autoLogin bool
3939
}
4040

41-
func NewServer(ctx context.Context, cfg *config.Config, frontend embed.FS) (*Server, error) {
41+
func NewServer(ctx context.Context, cfg *config.Config, frontend embed.FS, version string) (*Server, error) {
4242
db, signer, i18nService, emailSender, err := initInfrastructure(ctx, cfg)
4343
if err != nil {
4444
return nil, fmt.Errorf("failed to initialize infrastructure: %w", err)
@@ -145,7 +145,7 @@ func NewServer(ctx context.Context, cfg *config.Config, frontend embed.FS) (*Ser
145145

146146
router.Get("/oembed", handlers.HandleOEmbed(cfg.App.BaseURL))
147147

148-
router.NotFound(EmbedFolder(frontend, "web/dist", cfg.App.BaseURL, signatureRepo))
148+
router.NotFound(EmbedFolder(frontend, "web/dist", cfg.App.BaseURL, version, signatureRepo))
149149

150150
httpServer := &http.Server{
151151
Addr: cfg.Server.ListenAddr,

backend/pkg/web/static.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ import (
1919

2020
// EmbedFolder returns an http.HandlerFunc that serves an embedded filesystem
2121
// with SPA fallback support (serves index.html for non-existent routes)
22-
// For index.html, it replaces __ACKIFY_BASE_URL__ placeholder with the actual base URL
22+
// For index.html, it replaces __ACKIFY_BASE_URL__ placeholder with the actual base URL,
23+
// __ACKIFY_VERSION__ with the application version,
2324
// and __META_TAGS__ with dynamic meta tags based on query parameters
24-
func EmbedFolder(fsEmbed embed.FS, targetPath string, baseURL string, signatureRepo *database.SignatureRepository) http.HandlerFunc {
25+
func EmbedFolder(fsEmbed embed.FS, targetPath string, baseURL string, version string, signatureRepo *database.SignatureRepository) http.HandlerFunc {
2526
return func(w http.ResponseWriter, r *http.Request) {
2627
fsys, err := fs.Sub(fsEmbed, targetPath)
2728
if err != nil {
@@ -60,7 +61,7 @@ func EmbedFolder(fsEmbed embed.FS, targetPath string, baseURL string, signatureR
6061
defer file.Close()
6162

6263
if shouldServeIndex || strings.HasSuffix(cleanPath, "index.html") {
63-
serveIndexTemplate(w, r, file, baseURL, signatureRepo)
64+
serveIndexTemplate(w, r, file, baseURL, version, signatureRepo)
6465
return
6566
}
6667

@@ -69,7 +70,7 @@ func EmbedFolder(fsEmbed embed.FS, targetPath string, baseURL string, signatureR
6970
}
7071
}
7172

72-
func serveIndexTemplate(w http.ResponseWriter, r *http.Request, file fs.File, baseURL string, signatureRepo *database.SignatureRepository) {
73+
func serveIndexTemplate(w http.ResponseWriter, r *http.Request, file fs.File, baseURL string, version string, signatureRepo *database.SignatureRepository) {
7374
content, err := io.ReadAll(file)
7475
if err != nil {
7576
logger.Logger.Error("Failed to read index.html", "error", err.Error())
@@ -78,6 +79,7 @@ func serveIndexTemplate(w http.ResponseWriter, r *http.Request, file fs.File, ba
7879
}
7980

8081
processedContent := strings.ReplaceAll(string(content), "__ACKIFY_BASE_URL__", baseURL)
82+
processedContent = strings.ReplaceAll(processedContent, "__ACKIFY_VERSION__", version)
8183

8284
metaTags := generateMetaTags(r, baseURL, signatureRepo)
8385
processedContent = strings.ReplaceAll(processedContent, "__META_TAGS__", metaTags)

webapp/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
__META_TAGS__
99
<script>
1010
window.ACKIFY_BASE_URL = '__ACKIFY_BASE_URL__';
11+
window.ACKIFY_VERSION = '__ACKIFY_VERSION__';
1112
</script>
1213
</head>
1314
<body>

webapp/src/components/AppLogo.vue

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,21 @@ import { computed } from 'vue'
55
interface Props {
66
size?: 'sm' | 'md' | 'lg'
77
showText?: boolean
8+
showVersion?: boolean
89
textClass?: string
910
}
1011
1112
const props = withDefaults(defineProps<Props>(), {
1213
size: 'md',
1314
showText: true,
15+
showVersion: false,
1416
textClass: ''
1517
})
1618
19+
const appVersion = computed(() => {
20+
return (window as any).ACKIFY_VERSION || ''
21+
})
22+
1723
const sizeClasses = computed(() => {
1824
switch (props.size) {
1925
case 'sm':
@@ -52,11 +58,18 @@ const sizeClasses = computed(() => {
5258
stroke-linejoin="round"
5359
/>
5460
</svg>
55-
<span
56-
v-if="showText"
57-
:class="[sizeClasses.text, textClass || 'font-bold text-foreground']"
58-
>
59-
Ackify
60-
</span>
61+
<div v-if="showText" class="flex flex-col">
62+
<span
63+
:class="[sizeClasses.text, textClass || 'font-bold text-foreground']"
64+
>
65+
Ackify
66+
</span>
67+
<span
68+
v-if="showVersion && appVersion"
69+
class="text-xs text-muted-foreground leading-none -mt-0.5"
70+
>
71+
{{ appVersion }}
72+
</span>
73+
</div>
6174
</div>
6275
</template>

webapp/src/components/layout/AppFooter.vue

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,8 @@ const { t } = useI18n()
1313
<div class="flex flex-col items-center justify-between gap-4 sm:flex-row sm:gap-6">
1414
<!-- Brand & Description -->
1515
<div class="flex items-center gap-3 text-center sm:text-left">
16-
<AppLogo size="sm" :show-text="false" />
17-
<div class="flex flex-col gap-1 sm:flex-row sm:items-center sm:gap-3">
18-
<span class="font-semibold text-base text-foreground leading-none">Ackify</span>
19-
<span class="text-sm text-muted-foreground leading-tight max-w-md">{{ t('footer.description') }}</span>
20-
</div>
16+
<AppLogo size="sm" :show-text="true" :show-version="true" />
17+
<span class="text-sm text-muted-foreground leading-tight max-w-md">{{ t('footer.description') }}</span>
2118
</div>
2219

2320
<!-- Links & Copyright -->

webapp/src/components/layout/AppHeader.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const closeUserMenu = () => {
6161
<!-- Logo -->
6262
<div class="flex items-center">
6363
<router-link to="/" class="focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 rounded-md">
64-
<AppLogo size="md" />
64+
<AppLogo size="md" :show-version="true" />
6565
</router-link>
6666
</div>
6767

0 commit comments

Comments
 (0)