gddo-server: add UI to turn on/off redirect to pkg.go.dev
This change adds UI for the option to set a cookie and have
candidate godoc.org links redirect to their equivalent pkg.go.dev
counterparts. If a user returns to godoc.org with the utm_source
form value equal to 'backtogodoc', it will display an option to
turn off the automatic redirect.
The intention is to have a link on pkg.go.dev that allows the
user to return to godoc.org and also turn off the automatic redirect
without having to know the special URL param values.
Updates golang/go#37099
Change-Id: I27bd03cbc484a1e504795ff669224c2a2a7d72b6
Reviewed-on: https://go-review.googlesource.com/c/gddo/+/222315
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Alexander Rakoczy <alex@golang.org>
diff --git a/gddo-server/assets/site.css b/gddo-server/assets/site.css
index 71da77f..f05feb4 100644
--- a/gddo-server/assets/site.css
+++ b/gddo-server/assets/site.css
@@ -123,12 +123,17 @@
.banner-action-container {
text-align: right;
+ white-space: nowrap;
}
.banner-action {
white-space: nowrap;
}
+.banner-action + .banner-action {
+ margin-left: 24px;
+}
+
@media (max-width: 768px) {
.banner {
flex-direction: column;
@@ -180,3 +185,42 @@
text-transform: uppercase;
font-size: 0.75em;
}
+
+.redirect-toast {
+ align-items: center;
+ background-color: #202124;
+ border-radius: 4px;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+ bottom: 20px;
+ color: #fff;
+ display: flex;
+ justify-content: space-between;
+ left: 20px;
+ padding: 10px 18px;
+ position: fixed;
+}
+
+@media (max-width: 768px) {
+ .redirect-toast {
+ width: calc(100% - 40px);
+ }
+}
+
+.redirect-toast-actions {
+ margin-left: 48px;
+ white-space: nowrap;
+}
+
+.redirect-toast-action,
+.redirect-toast-action:link,
+.redirect-toast-action:visited {
+ background: none;
+ border: 0;
+ color: #8ab4f9;
+ padding: 10px;
+}
+
+.redirect-toast-action:active,
+.redirect-toast-action:hover {
+ text-decoration: none;
+}
diff --git a/gddo-server/assets/site.js b/gddo-server/assets/site.js
index 4f52d58..04e26c3 100644
--- a/gddo-server/assets/site.js
+++ b/gddo-server/assets/site.js
@@ -103,11 +103,11 @@
switch(e.which) {
case 38: // up
incrActive(-1);
- e.preventDefault();
+ e.preventDefault();
break;
case 40: // down
incrActive(1);
- e.preventDefault();
+ e.preventDefault();
break;
case 13: // enter
if (active >= 0) {
@@ -228,4 +228,14 @@
target: '.gddo-sidebar',
offset: 10
});
+
+ const redirectToastEl = document.querySelector('.js-redirectToast');
+ if (!redirectToastEl) {
+ return; // element may not even be on the page
+ }
+ const redirectToastDismissEl = redirectToastEl.querySelector('.js-redirectToastDismiss');
+ redirectToastDismissEl.addEventListener('click', e => {
+ e.preventDefault();
+ redirectToastEl.style.display = 'none';
+ });
});
diff --git a/gddo-server/assets/templates/layout.html b/gddo-server/assets/templates/layout.html
index 577203a..4bd077a 100644
--- a/gddo-server/assets/templates/layout.html
+++ b/gddo-server/assets/templates/layout.html
@@ -32,6 +32,7 @@
Pkg.go.dev is a new destination for Go discovery & docs. Check it out at {{template "PkgGoDevLink" $}} and share your feedback.
</div>
<div class="banner-action-container">
+ <a class="banner-action" href="?redirect=on">Always use pkg.go.dev</a>
<a class="banner-action" href="https://blog.golang.org/pkg.go.dev-2020">Learn more</a>
</div>
</div>
@@ -71,6 +72,16 @@
</div>
</div>
</div>
+
+{{if .showPkgGoDevRedirectToast}}
+ <div class="redirect-toast js-redirectToast">
+ <div>Always use godoc.org as default</div>
+ <div class="redirect-toast-actions">
+ <a class="redirect-toast-action" href="?redirect=off">Yes</a>
+ <button class="redirect-toast-action js-redirectToastDismiss">Dismiss</button>
+ </div>
+ </div>
+{{end}}
<script src="{{staticPath "/-/jquery-2.0.3.min.js"}}"></script>
<script src="{{staticPath "/-/bootstrap.min.js"}}"></script>
<script src="{{staticPath "/-/site.js"}}"></script>
diff --git a/gddo-server/main.go b/gddo-server/main.go
index f3df330..795df07 100644
--- a/gddo-server/main.go
+++ b/gddo-server/main.go
@@ -274,6 +274,8 @@
}
}
+ showPkgGoDevRedirectToast := userReturningFromPkgGoDev(req)
+
switch {
case isView(req, "imports"):
if pdoc.Name == "" {
@@ -284,9 +286,10 @@
return err
}
return s.templates.execute(resp, "imports.html", http.StatusOK, nil, map[string]interface{}{
- "flashMessages": flashMessages,
- "pkgs": pkgs,
- "pdoc": newTDoc(s.v, pdoc),
+ "flashMessages": flashMessages,
+ "pkgs": pkgs,
+ "pdoc": newTDoc(s.v, pdoc),
+ "showPkgGoDevRedirectToast": showPkgGoDevRedirectToast,
})
case isView(req, "tools"):
proto := "http"
@@ -294,9 +297,10 @@
proto = "https"
}
return s.templates.execute(resp, "tools.html", http.StatusOK, nil, map[string]interface{}{
- "flashMessages": flashMessages,
- "uri": fmt.Sprintf("%s://%s/%s", proto, req.Host, importPath),
- "pdoc": newTDoc(s.v, pdoc),
+ "flashMessages": flashMessages,
+ "uri": fmt.Sprintf("%s://%s/%s", proto, req.Host, importPath),
+ "pdoc": newTDoc(s.v, pdoc),
+ "showPkgGoDevRedirectToast": showPkgGoDevRedirectToast,
})
case isView(req, "importers"):
if pdoc.Name == "" {
@@ -312,9 +316,10 @@
template = "importers_robot.html"
}
return s.templates.execute(resp, template, http.StatusOK, nil, map[string]interface{}{
- "flashMessages": flashMessages,
- "pkgs": pkgs,
- "pdoc": newTDoc(s.v, pdoc),
+ "flashMessages": flashMessages,
+ "pkgs": pkgs,
+ "pdoc": newTDoc(s.v, pdoc),
+ "showPkgGoDevRedirectToast": showPkgGoDevRedirectToast,
})
case isView(req, "import-graph"):
if requestType == robotRequest {
@@ -339,10 +344,11 @@
return err
}
return s.templates.execute(resp, "graph.html", http.StatusOK, nil, map[string]interface{}{
- "flashMessages": flashMessages,
- "svg": template.HTML(b),
- "pdoc": newTDoc(s.v, pdoc),
- "hide": hide,
+ "flashMessages": flashMessages,
+ "svg": template.HTML(b),
+ "pdoc": newTDoc(s.v, pdoc),
+ "hide": hide,
+ "showPkgGoDevRedirectToast": showPkgGoDevRedirectToast,
})
case isView(req, "play"):
u, err := s.playURL(pdoc, req.Form.Get("play"), req.Header.Get("X-AppEngine-Country"))
@@ -410,10 +416,11 @@
template += templateExt(req)
return s.templates.execute(resp, template, status, http.Header{"Etag": {etag}}, map[string]interface{}{
- "flashMessages": flashMessages,
- "pkgs": pkgs,
- "pdoc": newTDoc(s.v, pdoc),
- "importerCount": importerCount,
+ "flashMessages": flashMessages,
+ "pkgs": pkgs,
+ "pdoc": newTDoc(s.v, pdoc),
+ "importerCount": importerCount,
+ "showPkgGoDevRedirectToast": showPkgGoDevRedirectToast,
})
}
}
@@ -544,7 +551,11 @@
}
return s.templates.execute(resp, "home"+templateExt(req), http.StatusOK, nil,
- map[string]interface{}{"Popular": pkgs})
+ map[string]interface{}{
+ "Popular": pkgs,
+
+ "showPkgGoDevRedirectToast": userReturningFromPkgGoDev(req),
+ })
}
if path, ok := isBrowseURL(q); ok {
@@ -577,12 +588,21 @@
}
return s.templates.execute(resp, "results"+templateExt(req), http.StatusOK, nil,
- map[string]interface{}{"q": q, "pkgs": pkgs})
+ map[string]interface{}{
+ "q": q,
+ "pkgs": pkgs,
+
+ "showPkgGoDevRedirectToast": userReturningFromPkgGoDev(req),
+ })
}
func (s *server) serveAbout(resp http.ResponseWriter, req *http.Request) error {
return s.templates.execute(resp, "about.html", http.StatusOK, nil,
- map[string]interface{}{"Host": req.Host})
+ map[string]interface{}{
+ "Host": req.Host,
+
+ "showPkgGoDevRedirectToast": userReturningFromPkgGoDev(req),
+ })
}
func (s *server) serveBot(resp http.ResponseWriter, req *http.Request) error {
@@ -1071,6 +1091,10 @@
})
}
+func userReturningFromPkgGoDev(req *http.Request) bool {
+ return req.FormValue("utm_source") == "backtogodoc"
+}
+
var gddoToPkgGoDevRequest = map[string]string{
"/-/about": "/about",
"/-/go": "/std",
@@ -1083,6 +1107,10 @@
// if not redirecting to the same path that was used for the godoc.org request.
func pkgGoDevRedirectHandler(f func(http.ResponseWriter, *http.Request) error) func(http.ResponseWriter, *http.Request) error {
return func(w http.ResponseWriter, r *http.Request) error {
+ if userReturningFromPkgGoDev(r) {
+ return f(w, r)
+ }
+
redirectParam := r.FormValue(pkgGoDevRedirectParam)
if redirectParam == pkgGoDevRedirectOn {
diff --git a/gddo-server/main_test.go b/gddo-server/main_test.go
index ba76b64..269030a 100644
--- a/gddo-server/main_test.go
+++ b/gddo-server/main_test.go
@@ -85,6 +85,12 @@
wantSetCookieHeader: "",
wantStatusCode: http.StatusFound,
},
+ {
+ name: "do not redirect if user is returning from pkg.go.dev",
+ url: "http://godoc.org/net/http?utm_source=backtogodoc",
+ cookie: &http.Cookie{Name: "pkggodev-redirect", Value: "on"},
+ wantStatusCode: http.StatusOK,
+ },
} {
t.Run(test.name, func(t *testing.T) {
req := httptest.NewRequest("GET", test.url, nil)
@@ -108,7 +114,7 @@
}
if got, want := resp.StatusCode, test.wantStatusCode; got != want {
- t.Errorf("Status code mismatch: got %q; want %q", got, want)
+ t.Errorf("Status code mismatch: got %d; want %d", got, want)
}
})
}