mirror of
https://github.com/prymitive/karma
synced 2026-05-19 04:26:41 +00:00
feat(project): add support for loading extra css/js files
This commit is contained in:
14
assets.go
14
assets.go
@@ -4,9 +4,11 @@ import (
|
||||
"errors"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
assetfs "github.com/elazarl/go-bindata-assetfs"
|
||||
"github.com/gin-gonic/gin"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -72,3 +74,15 @@ func loadTemplate(t *template.Template, path string) *template.Template {
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func serverFileOrEmpty(path string, contentType string, c *gin.Context) {
|
||||
if path == "" {
|
||||
c.Data(200, contentType, nil)
|
||||
return
|
||||
}
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
c.Data(200, contentType, nil)
|
||||
return
|
||||
}
|
||||
c.File(path)
|
||||
}
|
||||
|
||||
82
assets_test.go
Normal file
82
assets_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/prymitive/karma/internal/config"
|
||||
)
|
||||
|
||||
type customizationAssetsTest struct {
|
||||
customJS string
|
||||
customCSS string
|
||||
path string
|
||||
code int
|
||||
body string
|
||||
mime string
|
||||
}
|
||||
|
||||
func TestCustomizationAssets(t *testing.T) {
|
||||
customizationAssetsTests := []customizationAssetsTest{
|
||||
{
|
||||
path: "/custom.js",
|
||||
code: 200,
|
||||
body: "",
|
||||
mime: "application/javascript",
|
||||
},
|
||||
{
|
||||
path: "/custom.css",
|
||||
code: 200,
|
||||
body: "",
|
||||
mime: "text/css",
|
||||
},
|
||||
{
|
||||
customJS: "foo/bar/custom.js",
|
||||
path: "/custom.js",
|
||||
code: 200,
|
||||
body: "",
|
||||
mime: "application/javascript",
|
||||
},
|
||||
{
|
||||
customCSS: "foo/bar/custom.css",
|
||||
path: "/custom.css",
|
||||
code: 200,
|
||||
body: "",
|
||||
mime: "text/css",
|
||||
},
|
||||
{
|
||||
customJS: "ui/.env",
|
||||
path: "/custom.js",
|
||||
code: 200,
|
||||
body: "NODE_PATH=src\nPUBLIC_URL=.\n",
|
||||
mime: "text/plain; charset=utf-8",
|
||||
},
|
||||
{
|
||||
customCSS: "ui/.env",
|
||||
path: "/custom.css",
|
||||
code: 200,
|
||||
body: "NODE_PATH=src\nPUBLIC_URL=.\n",
|
||||
mime: "text/plain; charset=utf-8",
|
||||
},
|
||||
}
|
||||
|
||||
mockConfig()
|
||||
for _, staticFileTest := range customizationAssetsTests {
|
||||
config.Config.Custom.CSS = staticFileTest.customCSS
|
||||
config.Config.Custom.JS = staticFileTest.customJS
|
||||
r := ginTestEngine()
|
||||
|
||||
req := httptest.NewRequest("GET", staticFileTest.path, nil)
|
||||
resp := httptest.NewRecorder()
|
||||
r.ServeHTTP(resp, req)
|
||||
if resp.Code != staticFileTest.code {
|
||||
t.Errorf("Invalid status code for GET %s: %d", staticFileTest.path, resp.Code)
|
||||
}
|
||||
if resp.Body.String() != staticFileTest.body {
|
||||
t.Errorf("Invalid body for GET %s: %s, expected %s", staticFileTest.path, resp.Body.String(), staticFileTest.body)
|
||||
}
|
||||
if resp.Result().Header.Get("Content-Type") != staticFileTest.mime {
|
||||
t.Errorf("Invalid Content-Type for GET %s: %s, expected %s", staticFileTest.path, resp.Result().Header.Get("Content-Type"), staticFileTest.mime)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -439,6 +439,34 @@ sentry:
|
||||
public: https://<key>:<secret>@sentry.io/<project>
|
||||
```
|
||||
|
||||
## Customizing karma
|
||||
|
||||
In order to keep the core code simple karma doesn't support any way of extending
|
||||
provided functionality. There is however possibility to inject custom CSS &
|
||||
JavaScript code, which can be used to either override built in CSS styles
|
||||
or integrate with extra services, for example using error handlers other than
|
||||
Sentry.
|
||||
|
||||
```yaml
|
||||
custom:
|
||||
css: string
|
||||
js: string
|
||||
```
|
||||
|
||||
- `css` - path to a CSS file
|
||||
- `js` - path to JavaScript file
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
custom:
|
||||
css: /theme/custom.css
|
||||
js: /assets/custom.js
|
||||
```
|
||||
|
||||
Use at your own risk and be aware that used CSS class names might change without
|
||||
warning. This feature is provided as is without any guarantees.
|
||||
|
||||
## Command line flags
|
||||
|
||||
Config file options are mapped to command line flags, so `alertmanager:interval`
|
||||
|
||||
@@ -18,6 +18,9 @@ annotations:
|
||||
hidden:
|
||||
- help
|
||||
visible: []
|
||||
custom:
|
||||
css: /custom.css
|
||||
js: /custom.js
|
||||
debug: false
|
||||
filters:
|
||||
default:
|
||||
|
||||
@@ -41,6 +41,9 @@ func init() {
|
||||
|
||||
pflag.String("config.file", "", "Full path to the configuration file")
|
||||
|
||||
pflag.String("custom.css", "", "Path to a file with custom CSS to load")
|
||||
pflag.String("custom.js", "", "Path to a file with custom JavaScript to load")
|
||||
|
||||
pflag.Bool("debug", false, "Enable debug mode")
|
||||
|
||||
pflag.StringSlice("filters.default", []string{}, "List of default filters")
|
||||
@@ -118,6 +121,8 @@ func (config *configSchema) Read() {
|
||||
config.Annotations.Default.Hidden = v.GetBool("annotations.default.hidden")
|
||||
config.Annotations.Hidden = v.GetStringSlice("annotations.hidden")
|
||||
config.Annotations.Visible = v.GetStringSlice("annotations.visible")
|
||||
config.Custom.CSS = v.GetString("custom.css")
|
||||
config.Custom.JS = v.GetString("custom.js")
|
||||
config.Debug = v.GetBool("debug")
|
||||
config.Filters.Default = v.GetStringSlice("filters.default")
|
||||
config.Labels.Color.Static = v.GetStringSlice("labels.color.static")
|
||||
|
||||
@@ -25,6 +25,8 @@ func resetEnv() {
|
||||
"ANNOTATIONS_HIDDEN",
|
||||
"ANNOTATIONS_VISIBLE",
|
||||
"CONFIG_FILE",
|
||||
"CUSTOM_CSS",
|
||||
"CUSTOM_JS",
|
||||
"DEBUG",
|
||||
"FILTERS_DEFAULT",
|
||||
"LABELS_COLOR_STATIC",
|
||||
@@ -68,6 +70,9 @@ annotations:
|
||||
hidden: []
|
||||
visible:
|
||||
- summary
|
||||
custom:
|
||||
css: /custom.css
|
||||
js: /custom.js
|
||||
debug: true
|
||||
filters:
|
||||
default:
|
||||
@@ -132,6 +137,8 @@ func TestReadConfig(t *testing.T) {
|
||||
os.Setenv("ALERTMANAGER_URI", "http://localhost")
|
||||
os.Setenv("ANNOTATIONS_DEFAULT_HIDDEN", "true")
|
||||
os.Setenv("ANNOTATIONS_VISIBLE", "summary")
|
||||
os.Setenv("CUSTOM_CSS", "/custom.css")
|
||||
os.Setenv("CUSTOM_JS", "/custom.js")
|
||||
os.Setenv("DEBUG", "true")
|
||||
os.Setenv("FILTERS_DEFAULT", "@state=active foo=bar")
|
||||
os.Setenv("LABELS_COLOR_STATIC", "a bb ccc")
|
||||
|
||||
@@ -31,6 +31,10 @@ type configSchema struct {
|
||||
Hidden []string
|
||||
Visible []string
|
||||
}
|
||||
Custom struct {
|
||||
CSS string
|
||||
JS string
|
||||
}
|
||||
Debug bool
|
||||
Filters struct {
|
||||
Default []string
|
||||
|
||||
8
main.go
8
main.go
@@ -85,6 +85,14 @@ func setupRouter(router *gin.Engine) {
|
||||
router.GET(getViewURL("/autocomplete.json"), autocomplete)
|
||||
router.GET(getViewURL("/labelNames.json"), knownLabelNames)
|
||||
router.GET(getViewURL("/labelValues.json"), knownLabelValues)
|
||||
|
||||
router.GET(getViewURL("/custom.css"), func(c *gin.Context) {
|
||||
serverFileOrEmpty(config.Config.Custom.CSS, "text/css", c)
|
||||
})
|
||||
router.GET(getViewURL("/custom.js"), func(c *gin.Context) {
|
||||
serverFileOrEmpty(config.Config.Custom.JS, "application/javascript", c)
|
||||
})
|
||||
|
||||
router.NoRoute(notFound)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%/custom.css" media="screen" />
|
||||
<title>karma</title>
|
||||
</head>
|
||||
<body>
|
||||
@@ -36,5 +37,6 @@
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<script src="%PUBLIC_URL%/custom.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user