From 8d9038d0bbacf3c7f7333015d4de80dc27c4c90c Mon Sep 17 00:00:00 2001 From: Denis Gukov Date: Tue, 20 Jan 2026 15:06:33 +0500 Subject: [PATCH 1/2] feat: add intro dialog --- api/router.go | 1 + api/system_info.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/api/router.go b/api/router.go index f484d351c..6725a5adc 100644 --- a/api/router.go +++ b/api/router.go @@ -183,6 +183,7 @@ func Route( authenticatedAPI.Use(StoreMiddleware, JSONMiddleware, authentication) authenticatedAPI.Path("/info").HandlerFunc(systemInfoController.GetSystemInfo).Methods("GET", "HEAD") + authenticatedAPI.Path("/info/seen_intro").HandlerFunc(systemInfoController.SetSeenIntro).Methods("POST") authenticatedAPI.Path("/subscription").HandlerFunc(subscriptionController.Activate).Methods("POST") authenticatedAPI.Path("/subscription").HandlerFunc(subscriptionController.GetSubscription).Methods("GET") diff --git a/api/system_info.go b/api/system_info.go index f5ca48ca7..3e558ab5b 100644 --- a/api/system_info.go +++ b/api/system_info.go @@ -2,6 +2,7 @@ package api import ( "errors" + "fmt" "net/http" "github.com/semaphoreui/semaphore/api/helpers" @@ -76,6 +77,16 @@ func (c *SystemInfoController) GetSystemInfo(w http.ResponseWriter, r *http.Requ plan = token.Plan } + // Check if user has seen the intro + seenIntroKey := fmt.Sprintf("seen_intro_%d", user.ID) + seenIntroVersion, err := helpers.Store(r).GetOption(seenIntroKey) + + if err != nil { + log.WithError(err).Error("Failed to get seen_intro option") + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + body := map[string]any{ "version": util.Version(), "ansible": util.AnsibleVersion(), @@ -87,7 +98,33 @@ func (c *SystemInfoController) GetSystemInfo(w http.ResponseWriter, r *http.Requ "schedule_timezone": timezone, "teams": util.Config.Teams, "roles": roles, + "seen_intro": seenIntroVersion, } helpers.WriteJSON(w, http.StatusOK, body) } + +func (c *SystemInfoController) SetSeenIntro(w http.ResponseWriter, r *http.Request) { + user := helpers.GetFromContext(r, "user").(*db.User) + + var reqBody struct { + Version string `json:"version"` + } + + if !helpers.Bind(w, r, &reqBody) { + return + } + + seenIntroKey := fmt.Sprintf("seen_intro_%d", user.ID) + + err := helpers.Store(r).SetOption(seenIntroKey, reqBody.Version) + if err != nil { + log.WithError(err).Error("Failed to set seen_intro option") + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + helpers.WriteJSON(w, http.StatusOK, map[string]string{ + "status": "ok", + }) +} From d21c75f9b7a879f28adb7645d37f97e1cd202ce3 Mon Sep 17 00:00:00 2001 From: Denis Gukov Date: Tue, 20 Jan 2026 22:02:14 +0500 Subject: [PATCH 2/2] feat(be): seen intro flag --- api/system_info.go | 5 +- web/src/App.vue | 7 +++ web/src/assets/intro/poster.webp | Bin 0 -> 126270 bytes web/src/components/IntroDialog.vue | 73 +++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 web/src/assets/intro/poster.webp create mode 100644 web/src/components/IntroDialog.vue diff --git a/api/system_info.go b/api/system_info.go index 3e558ab5b..f0298219f 100644 --- a/api/system_info.go +++ b/api/system_info.go @@ -77,9 +77,10 @@ func (c *SystemInfoController) GetSystemInfo(w http.ResponseWriter, r *http.Requ plan = token.Plan } - // Check if user has seen the intro + // Check if the user has seen the intro seenIntroKey := fmt.Sprintf("seen_intro_%d", user.ID) seenIntroVersion, err := helpers.Store(r).GetOption(seenIntroKey) + seenIntro := seenIntroVersion == util.Ver if err != nil { log.WithError(err).Error("Failed to get seen_intro option") @@ -98,7 +99,7 @@ func (c *SystemInfoController) GetSystemInfo(w http.ResponseWriter, r *http.Requ "schedule_timezone": timezone, "teams": util.Config.Teams, "roles": roles, - "seen_intro": seenIntroVersion, + "seen_intro": seenIntro, } helpers.WriteJSON(w, http.StatusOK, body) diff --git a/web/src/App.vue b/web/src/App.vue index 2f045c1dc..3cbfe84e6 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -1,5 +1,7 @@ +