Update features on home page
This commit is contained in:
parent
474f25007b
commit
82f21abcff
3 changed files with 101 additions and 13 deletions
|
|
@ -54,6 +54,10 @@ func init() {
|
||||||
func DeclareRoutes(cfg *config.Config, router *gin.Engine) {
|
func DeclareRoutes(cfg *config.Config, router *gin.Engine) {
|
||||||
appConfig := map[string]interface{}{}
|
appConfig := map[string]interface{}{}
|
||||||
|
|
||||||
|
if cfg.ReportRetention > 0 {
|
||||||
|
appConfig["report_retention"] = cfg.ReportRetention
|
||||||
|
}
|
||||||
|
|
||||||
if appcfg, err := json.MarshalIndent(appConfig, "", " "); err != nil {
|
if appcfg, err := json.MarshalIndent(appConfig, "", " "); err != nil {
|
||||||
log.Println("Unable to generate JSON config to inject in web application")
|
log.Println("Unable to generate JSON config to inject in web application")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
48
web/src/lib/config.ts
Normal file
48
web/src/lib/config.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
// This file is part of the happyDeliver (R) project.
|
||||||
|
// Copyright (c) 2025 happyDomain
|
||||||
|
// Authors: Pierre-Olivier Mercier, et al.
|
||||||
|
//
|
||||||
|
// This program is offered under a commercial and under the AGPL license.
|
||||||
|
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||||
|
//
|
||||||
|
// For AGPL licensing:
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
interface AppConfig {
|
||||||
|
report_retention?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultConfig: AppConfig = {
|
||||||
|
report_retention: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
function getConfigFromScriptTag(): AppConfig | null {
|
||||||
|
if (typeof document !== "undefined") {
|
||||||
|
const configScript = document.getElementById("app-config");
|
||||||
|
if (configScript) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(configScript.textContent || "");
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to parse app config:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialConfig = getConfigFromScriptTag() || defaultConfig;
|
||||||
|
|
||||||
|
export const appConfig = writable<AppConfig>(initialConfig);
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
import { createTest as apiCreateTest } from "$lib/api";
|
import { createTest as apiCreateTest } from "$lib/api";
|
||||||
|
import { appConfig } from "$lib/config";
|
||||||
import { FeatureCard, HowItWorksStep } from "$lib/components";
|
import { FeatureCard, HowItWorksStep } from "$lib/components";
|
||||||
|
|
||||||
let loading = $state(false);
|
let loading = $state(false);
|
||||||
|
|
@ -21,7 +22,27 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const features = [
|
function getRetentionTimeText(): string {
|
||||||
|
if (!$appConfig.report_retention) return "ever";
|
||||||
|
|
||||||
|
const seconds = $appConfig.report_retention / 1000000000;
|
||||||
|
const days = Math.floor(seconds / 86400);
|
||||||
|
const weeks = Math.floor(days / 7);
|
||||||
|
const months = Math.floor(days / 30);
|
||||||
|
|
||||||
|
if (months >= 1) {
|
||||||
|
return months === 1 ? "1 month" : `${months} months`;
|
||||||
|
} else if (weeks >= 1) {
|
||||||
|
return weeks === 1 ? "1 week" : `${weeks} weeks`;
|
||||||
|
} else if (days >= 1) {
|
||||||
|
return days === 1 ? "1 day" : `${days} days`;
|
||||||
|
} else {
|
||||||
|
const hours = Math.floor(seconds / 3600);
|
||||||
|
return hours === 1 ? "1 hour" : `${hours} hours`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const features = $derived([
|
||||||
{
|
{
|
||||||
icon: "bi-shield-check",
|
icon: "bi-shield-check",
|
||||||
title: "Authentication",
|
title: "Authentication",
|
||||||
|
|
@ -30,16 +51,31 @@
|
||||||
variant: "primary" as const,
|
variant: "primary" as const,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "bi-patch-check",
|
icon: "bi-building-check",
|
||||||
title: "BIMI Support",
|
title: "BIMI Support",
|
||||||
description:
|
description:
|
||||||
"Brand Indicators for Message Identification - verify your brand logo configuration.",
|
"Brand Indicators for Message Identification - verify your brand logo configuration.",
|
||||||
variant: "info" as const,
|
variant: "info" as const,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: "bi-link-45deg",
|
||||||
|
title: "ARC Verification",
|
||||||
|
description:
|
||||||
|
"Authenticated Received Chain validation for forwarded emails and mailing lists.",
|
||||||
|
variant: "primary" as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "bi-check2-circle",
|
||||||
|
title: "Domain Alignment",
|
||||||
|
description:
|
||||||
|
"Verify alignment between From, Return-Path, and DKIM domains for DMARC compliance.",
|
||||||
|
variant: "success" as const,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
icon: "bi-globe",
|
icon: "bi-globe",
|
||||||
title: "DNS Records",
|
title: "DNS Records",
|
||||||
description: "Verify MX, SPF, DKIM, DMARC, and BIMI records are properly configured.",
|
description:
|
||||||
|
"Verify PTR, MX, SPF, DKIM, DMARC, and BIMI records are properly configured.",
|
||||||
variant: "success" as const,
|
variant: "success" as const,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -54,32 +90,32 @@
|
||||||
description: "Check if your IP is listed in major DNS-based blacklists (RBLs).",
|
description: "Check if your IP is listed in major DNS-based blacklists (RBLs).",
|
||||||
variant: "danger" as const,
|
variant: "danger" as const,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: "bi-file-text",
|
|
||||||
title: "Content Analysis",
|
|
||||||
description: "HTML structure, link validation, image analysis, and more.",
|
|
||||||
variant: "info" as const,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
icon: "bi-card-heading",
|
icon: "bi-card-heading",
|
||||||
title: "Header Quality",
|
title: "Header Quality",
|
||||||
description: "Validate required headers, check for missing fields and alignment.",
|
description: "Validate required headers, check for missing fields and alignment.",
|
||||||
variant: "secondary" as const,
|
variant: "secondary" as const,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: "bi-file-text",
|
||||||
|
title: "Content Analysis",
|
||||||
|
description: "HTML structure, link validation, image analysis, and more.",
|
||||||
|
variant: "info" as const,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
icon: "bi-bar-chart",
|
icon: "bi-bar-chart",
|
||||||
title: "Detailed Scoring",
|
title: "Detailed Scoring",
|
||||||
description:
|
description:
|
||||||
"0-10 deliverability score with breakdown by category and recommendations.",
|
"A to F deliverability grade with breakdown by category and recommendations.",
|
||||||
variant: "primary" as const,
|
variant: "primary" as const,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "bi-lock",
|
icon: "bi-lock",
|
||||||
title: "Privacy First",
|
title: "Privacy First",
|
||||||
description: "Self-hosted solution, your data never leaves your infrastructure.",
|
description: `Self-hosted solution, your data never leaves your infrastructure. Reports retained for ${getRetentionTimeText()}.`,
|
||||||
variant: "success" as const,
|
variant: "success" as const,
|
||||||
},
|
},
|
||||||
];
|
]);
|
||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
{
|
{
|
||||||
|
|
@ -152,7 +188,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row g-4">
|
<div class="row g-4 justify-content-center">
|
||||||
{#each features as feature}
|
{#each features as feature}
|
||||||
<div class="col-md-6 col-lg-3">
|
<div class="col-md-6 col-lg-3">
|
||||||
<FeatureCard {...feature} />
|
<FeatureCard {...feature} />
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue