- SyncG15Office files each submission as a G15Office task with its screenshot through a fetchguard client limited to the configured host; a River job with 3 attempts, PHP's messages on failure, nothing sent when unconfigured - the replay of PHP's recorded G15Office exchange (classes/testdata) asserts the task JSON, headers and the screenshot part - settings screen (cabana field types only), read-only submissions list, manage_settings permission and navigation - embed.js served byte for byte at /plugins/golem15/feedback/assets/js/embed.js - feedback:import-settings copies the WinterCMS settings row once
36 lines
1.0 KiB
Go
36 lines
1.0 KiB
Go
package feedback
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
_ "embed"
|
|
"encoding/hex"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// EmbedJSPath is where the widget script is served: the path the WinterCMS
|
|
// plugin's file had under the web root, which embedding pages and the
|
|
// application's frontend proxy request.
|
|
const EmbedJSPath = "/plugins/golem15/feedback/assets/js/embed.js"
|
|
|
|
// embedJS is the WinterCMS plugin's assets/js/embed.js, byte for byte.
|
|
//
|
|
//go:embed assets/js/embed.js
|
|
var embedJS []byte
|
|
|
|
var embedJSETag = func() string {
|
|
sum := sha256.Sum256(embedJS)
|
|
return `"` + hex.EncodeToString(sum[:16]) + `"`
|
|
}()
|
|
|
|
// EmbedJS serves the widget script with a JavaScript content type and an
|
|
// ETag, answering conditional and range requests like a static file.
|
|
func EmbedJS() http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
|
|
w.Header().Set("ETag", embedJSETag)
|
|
http.ServeContent(w, r, "embed.js", time.Time{}, bytes.NewReader(embedJS))
|
|
}
|
|
}
|