diff --git a/internal/config/cli.go b/internal/config/cli.go index 93c18ce..d19b90b 100644 --- a/internal/config/cli.go +++ b/internal/config/cli.go @@ -38,6 +38,7 @@ func declareFlags(o *Config) { flag.DurationVar(&o.Analysis.HTTPTimeout, "http-timeout", o.Analysis.HTTPTimeout, "Timeout when performing HTTP query") flag.Var(&StringArray{&o.Analysis.RBLs}, "rbl", "Append a RBL (use this option multiple time to append multiple RBLs)") flag.DurationVar(&o.ReportRetention, "report-retention", o.ReportRetention, "How long to keep reports (e.g., 720h, 30d). 0 = keep forever") + flag.Var(&URL{&o.SurveyURL}, "survey-url", "URL for user feedback survey") // Others flags are declared in some other files likes sources, storages, ... when they need specials configurations } diff --git a/internal/config/config.go b/internal/config/config.go index 510aaa9..668573a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -25,6 +25,7 @@ import ( "flag" "fmt" "log" + "net/url" "os" "path" "strings" @@ -41,6 +42,7 @@ type Config struct { Email EmailConfig Analysis AnalysisConfig ReportRetention time.Duration // How long to keep reports. 0 = keep forever + SurveyURL url.URL // URL for user feedback survey } // DatabaseConfig contains database connection settings diff --git a/internal/config/custom.go b/internal/config/custom.go index 9461632..97c8d71 100644 --- a/internal/config/custom.go +++ b/internal/config/custom.go @@ -23,6 +23,7 @@ package config import ( "fmt" + "net/url" "strings" ) @@ -43,3 +44,25 @@ func (i *StringArray) Set(value string) error { return nil } + +type URL struct { + URL *url.URL +} + +func (i *URL) String() string { + if i.URL != nil { + return i.URL.String() + } else { + return "" + } +} + +func (i *URL) Set(value string) error { + u, err := url.Parse(value) + if err != nil { + return err + } + + *i.URL = *u + return nil +} diff --git a/web/routes.go b/web/routes.go index 184da64..8a0ceb2 100644 --- a/web/routes.go +++ b/web/routes.go @@ -58,6 +58,10 @@ func DeclareRoutes(cfg *config.Config, router *gin.Engine) { appConfig["report_retention"] = cfg.ReportRetention } + if cfg.SurveyURL.Host != "" { + appConfig["survey_url"] = cfg.SurveyURL.String() + } + if appcfg, err := json.MarshalIndent(appConfig, "", " "); err != nil { log.Println("Unable to generate JSON config to inject in web application") } else { diff --git a/web/src/lib/components/SummaryCard.svelte b/web/src/lib/components/SummaryCard.svelte index 9eb6272..7c2f2fb 100644 --- a/web/src/lib/components/SummaryCard.svelte +++ b/web/src/lib/components/SummaryCard.svelte @@ -14,10 +14,11 @@ } interface Props { + children?: import("svelte").Snippet; report: Report; } - let { report }: Props = $props(); + let { children, report }: Props = $props(); function buildSummary(): TextSegment[] { const segments: TextSegment[] = []; @@ -455,7 +456,7 @@ Summary -

+

{#each summarySegments as segment} {#if segment.link} {#if report.grade == "A" || report.grade == "A+"}, well done 🎉{:else if report.grade == "C" || report.grade == "D"}: you should try to increase your score to ensure inbox delivery.{:else if report.grade == "E"}: you could have delivery issues with common providers.{:else if report.grade == "F"}: it will most likely be rejected by most providers.{:else}!{/if} Check the details below 🔽

+ {@render children?.()} diff --git a/web/src/lib/components/TinySurvey.svelte b/web/src/lib/components/TinySurvey.svelte new file mode 100644 index 0000000..e971b80 --- /dev/null +++ b/web/src/lib/components/TinySurvey.svelte @@ -0,0 +1,96 @@ + + +{#if $appConfig.surveyUrl} +
+ {#if step === 0} + {#if question}{@render question()}{:else} +

Help us to design a better tool, rate this report!

+ {/if} +
+ {#each [...Array(5).keys()] as i} + + {/each} +
+ {:else if step === 1} +

+ {#if responses.stars == 5}Thank you! Would you like to tell us more? + {:else if responses.stars == 4}What are we missing to earn 5 stars? + {:else}How could we improve? + {/if} +

+ + + + {:else if step === 2} +

+ Thank you so much for taking the time to share your feedback! +

+ {/if} +
+{/if} diff --git a/web/src/lib/components/index.ts b/web/src/lib/components/index.ts index 8b83ae5..e600c11 100644 --- a/web/src/lib/components/index.ts +++ b/web/src/lib/components/index.ts @@ -13,3 +13,4 @@ export { default as ContentAnalysisCard } from "./ContentAnalysisCard.svelte"; export { default as HeaderAnalysisCard } from "./HeaderAnalysisCard.svelte"; export { default as PtrRecordsDisplay } from "./PtrRecordsDisplay.svelte"; export { default as PtrForwardRecordsDisplay } from "./PtrForwardRecordsDisplay.svelte"; +export { default as TinySurvey } from "./TinySurvey.svelte"; diff --git a/web/src/lib/config.ts b/web/src/lib/config.ts index 65eb1bb..c4c0bd4 100644 --- a/web/src/lib/config.ts +++ b/web/src/lib/config.ts @@ -23,10 +23,12 @@ import { writable } from "svelte/store"; interface AppConfig { report_retention?: number; + surveyUrl?: string; } const defaultConfig: AppConfig = { report_retention: 0, + surveyUrl: "", }; function getConfigFromScriptTag(): AppConfig | null { diff --git a/web/src/routes/test/[test]/+page.svelte b/web/src/routes/test/[test]/+page.svelte index 7ef2b63..7f50923 100644 --- a/web/src/routes/test/[test]/+page.svelte +++ b/web/src/routes/test/[test]/+page.svelte @@ -12,7 +12,8 @@ DnsRecordsCard, BlacklistCard, ContentAnalysisCard, - HeaderAnalysisCard + HeaderAnalysisCard, + TinySurvey, } from "$lib/components"; let testId = $derived(page.params.test); @@ -236,7 +237,11 @@
- + +
+ +
+