mirror of
https://github.com/wahyd4/badger.git
synced 2026-08-08 21:05:55 +10:00
Add feature toggle api, tried to reduce frontend size
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/wahyd4/badger/models"
|
||||
)
|
||||
|
||||
type FeatureTogglesHandler struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
func (handler *FeatureTogglesHandler) Toggles(c *gin.Context) {
|
||||
toggles := make([]*models.FeatureToggle, 0)
|
||||
|
||||
if err := handler.DB.Find(&toggles).Error; err != nil {
|
||||
sentry.CaptureException(err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"msg": ErrorMessageInternalError})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, toggles)
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
NoAuthPaths = []string{"/api/badges", "/api/auth"}
|
||||
NoAuthPaths = []string{"/api/badges", "/api/auth", "/api/toggles"}
|
||||
)
|
||||
|
||||
type UsersHandler struct {
|
||||
|
||||
@@ -60,6 +60,7 @@ func main() {
|
||||
&models.Token{},
|
||||
&models.User{},
|
||||
&models.ViewRecord{},
|
||||
&models.FeatureToggle{},
|
||||
&models.BadgeViewCount{})
|
||||
|
||||
client, err := api.NewClient(api.Config{
|
||||
@@ -74,8 +75,8 @@ func main() {
|
||||
handler := &handlers.BadgesHandler{DB: db, PrometheusAPIClient: client}
|
||||
|
||||
userHandler := &handlers.UsersHandler{DB: db}
|
||||
|
||||
statsHandler := &handlers.StatsHandler{DB: db}
|
||||
toggleHandler := &handlers.FeatureTogglesHandler{DB: db}
|
||||
|
||||
r := gin.Default()
|
||||
|
||||
@@ -97,6 +98,7 @@ func main() {
|
||||
api.POST("/auth", userHandler.Authenticate)
|
||||
api.POST("/badges", handler.CreateBadge)
|
||||
api.GET("/badges", handler.MyBadges)
|
||||
api.GET("/toggles", toggleHandler.Toggles)
|
||||
|
||||
statsAPI := r.Group("/api/stats")
|
||||
statsAPI.Use(handler.ValidateBadge)
|
||||
|
||||
@@ -158,6 +158,11 @@ spec:
|
||||
backend:
|
||||
serviceName: badger-ui
|
||||
servicePort: 80
|
||||
- path: /badges
|
||||
pathType: Exact
|
||||
backend:
|
||||
serviceName: badger-ui
|
||||
servicePort: 80
|
||||
- path: /stats
|
||||
pathType: Prefix
|
||||
backend:
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package models
|
||||
|
||||
import "github.com/jinzhu/gorm"
|
||||
|
||||
type FeatureToggle struct {
|
||||
gorm.Model
|
||||
Name string `json:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
+21
-22
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<b-overlay :show="isLoading" rounded="sm" variant="dark" class="overlay">
|
||||
<b-navbar toggleable="md" type="dark" variant="dark">
|
||||
<b-navbar-brand href="/" >Badges</b-navbar-brand>
|
||||
<b-navbar-brand href="/">Badges</b-navbar-brand>
|
||||
<b-navbar-toggle target="nav-collapse"> </b-navbar-toggle>
|
||||
|
||||
<b-collapse id="nav-collapse" is-nav v-if="!isProduction">
|
||||
<b-collapse id="nav-collapse" is-nav v-if="true">
|
||||
<b-navbar-nav>
|
||||
<b-nav-item to="/badges" exact>
|
||||
My badges
|
||||
@@ -43,25 +43,23 @@
|
||||
<b-col md="3" class="contact-me">
|
||||
<a href="mailto:me@toozhao.com" class="contact">Contact me</a>
|
||||
</b-col>
|
||||
<b-col md="3">
|
||||
</b-col>
|
||||
|
||||
<b-col md="3"> </b-col>
|
||||
</b-row>
|
||||
<template #overlay>
|
||||
<div class="text-center" v-if="hasError">
|
||||
<b-icon icon="stopwatch" font-scale="3" animation="cylon"></b-icon>
|
||||
<p id="error-detail">{{error}}</p>
|
||||
<b-button
|
||||
ref="cancel"
|
||||
variant="outline-light"
|
||||
size="sm"
|
||||
aria-describedby="cancel-label"
|
||||
href="/"
|
||||
>
|
||||
Back to homepage
|
||||
</b-button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="text-center" v-if="hasError">
|
||||
<!-- <b-icon icon="stopwatch" font-scale="3" animation="cylon"></b-icon> -->
|
||||
<p id="error-detail">{{ error }}</p>
|
||||
<b-button
|
||||
ref="cancel"
|
||||
variant="outline-light"
|
||||
size="sm"
|
||||
aria-describedby="cancel-label"
|
||||
href="/"
|
||||
>
|
||||
Back to homepage
|
||||
</b-button>
|
||||
</div>
|
||||
</template>
|
||||
</b-overlay>
|
||||
</template>
|
||||
|
||||
@@ -76,7 +74,7 @@ export default Vue.extend({
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch("users/loginFromLocal")
|
||||
this.$store.dispatch("users/loginFromLocal");
|
||||
|
||||
if (this.$store.state.users.token === "") {
|
||||
this.$store.dispatch("users/authenticate", {
|
||||
@@ -98,7 +96,7 @@ export default Vue.extend({
|
||||
hasError() {
|
||||
return this.$store.state.error.error !== "";
|
||||
},
|
||||
error(){
|
||||
error() {
|
||||
return this.$store.state.error.error;
|
||||
},
|
||||
isProduction() {
|
||||
@@ -142,7 +140,8 @@ html {
|
||||
font-size: 13px;
|
||||
background: #eee;
|
||||
padding: 5vh 0;
|
||||
.copyright, .contact-me {
|
||||
.copyright,
|
||||
.contact-me {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
+10
-3
@@ -105,9 +105,9 @@ export default {
|
||||
** See https://nuxtjs.org/api/configuration-build/
|
||||
*/
|
||||
build: {
|
||||
babel: {
|
||||
compact: true
|
||||
}
|
||||
// babel: {
|
||||
// compact: true
|
||||
// }
|
||||
},
|
||||
auth: {
|
||||
redirect: {
|
||||
@@ -145,6 +145,13 @@ export default {
|
||||
port: 3000,
|
||||
host: '0.0.0.0'
|
||||
},
|
||||
bootstrapVue: {
|
||||
// Install the `IconsPlugin` plugin (in addition to `BootstrapVue` plugin)
|
||||
icons: false,
|
||||
components: ['BContainer', 'BRow', 'BCol', 'BFormInput', 'BButton', 'BTable', 'BModal', 'BCard',
|
||||
'BLink', 'BCardText', 'BFormTextarea', 'BImg', 'BDropdownItem', 'BOverlay', 'BNavbar', 'BNavbarBrand',
|
||||
'BNavbarToggle', 'BCollapse', 'BNavbarNav', 'BNavItem', 'BNavItemDropdown', 'BButtonGroup', 'BAlert']
|
||||
}
|
||||
// router: {
|
||||
// middleware: ['auth']
|
||||
// }
|
||||
|
||||
Generated
+59
-14
@@ -3491,13 +3491,58 @@
|
||||
}
|
||||
},
|
||||
"@nuxt/opencollective": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.0.tgz",
|
||||
"integrity": "sha512-Vf09BxCdj1iT2IRqVwX5snaY2WCTkvM0O4cWWSO1ThCFuc4if0Q/nNwAgCxRU0FeYHJ7DdyMUNSdswCLKlVqeg==",
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.2.tgz",
|
||||
"integrity": "sha512-XG7rUdXG9fcafu9KTDIYjJSkRO38EwjlKYIb5TQ/0WDbiTUTtUtgncMscKOYzfsY86kGs05pAuMOR+3Fi0aN3A==",
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"consola": "^2.10.1",
|
||||
"node-fetch": "^2.6.0"
|
||||
"chalk": "^4.1.0",
|
||||
"consola": "^2.15.0",
|
||||
"node-fetch": "^2.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nuxt/server": {
|
||||
@@ -6032,17 +6077,17 @@
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "4.5.2",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.2.tgz",
|
||||
"integrity": "sha512-vlGn0bcySYl/iV+BGA544JkkZP5LB3jsmkeKLFQakCOwCM3AOk7VkldBz4jrzSe+Z0Ezn99NVXa1o45cQY4R6A=="
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz",
|
||||
"integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw=="
|
||||
},
|
||||
"bootstrap-vue": {
|
||||
"version": "2.16.0",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.16.0.tgz",
|
||||
"integrity": "sha512-gLETwPmeRHCe5WHmhGxzb5PtTEuKqQPGl0TFvZ2Odbkg/7UuIHdqIexrJRerpnomP4ZzDQ+qYGL91Ls9lcQsJQ==",
|
||||
"version": "2.21.2",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.21.2.tgz",
|
||||
"integrity": "sha512-0Exe+4MZysqhZNXIKf4TzkvXaupxh9EHsoCRez0o5Dc0J7rlafayOEwql63qXv74CgZO8E4U8ugRNJko1vMvNw==",
|
||||
"requires": {
|
||||
"@nuxt/opencollective": "^0.3.0",
|
||||
"bootstrap": ">=4.5.0 <5.0.0",
|
||||
"@nuxt/opencollective": "^0.3.2",
|
||||
"bootstrap": ">=4.5.3 <5.0.0",
|
||||
"popper.js": "^1.16.1",
|
||||
"portal-vue": "^2.1.7",
|
||||
"vue-functional-data-merge": "^3.1.0"
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@
|
||||
"@nuxtjs/auth-next": "5.0.0-1611574754.9020f2a",
|
||||
"@nuxtjs/axios": "^5.12.5",
|
||||
"@nuxtjs/pwa": "^3.0.0-beta.20",
|
||||
"bootstrap": "^4.5.0",
|
||||
"bootstrap-vue": "^2.15.0",
|
||||
"bootstrap": "^4.6.0",
|
||||
"bootstrap-vue": "^2.21.2",
|
||||
"chart.js": "^2.9.4",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"express-jwt": "^6.0.0",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<b-card-text> </b-card-text>
|
||||
|
||||
<b-card-text>
|
||||
<img :src="badgeUrl(badge)" class="my-badge" />
|
||||
<b-link :href="statsUrl(badge)"><img :src="badgeUrl(badge)" class="my-badge" /></b-link>
|
||||
</b-card-text>
|
||||
|
||||
<a href="#" class="card-link" style="display:none"><svg></svg></a>
|
||||
@@ -62,6 +62,9 @@ export default {
|
||||
},
|
||||
badgeUrl(badge) {
|
||||
return `${this.$config.backendURL}/badges/${badge.ulid}/green.svg?i=1`;
|
||||
},
|
||||
statsUrl(badge) {
|
||||
return `/stats/${badge.ulid}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+2
-2
@@ -8,14 +8,14 @@
|
||||
<b-col md="4" class="text-center">
|
||||
<b-card title="" bg-variant="light">
|
||||
<div v-for="s in strategies" :key="s.key" class="mb-2">
|
||||
<b-btn
|
||||
<b-button
|
||||
block
|
||||
:style="{ background: s.color }"
|
||||
class="login-button"
|
||||
@click="$auth.loginWith(s.key)"
|
||||
>
|
||||
Login with {{ s.name }}
|
||||
</b-btn>
|
||||
</b-button>
|
||||
</div>
|
||||
</b-card>
|
||||
</b-col>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
export const state = () => ({
|
||||
toggles: []
|
||||
});
|
||||
|
||||
export const mutations = {
|
||||
setToggles(state, toggles) {
|
||||
state.toggles = toggles;
|
||||
}
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
async getToggles(context, callback) {
|
||||
const result = await this.$axios.$get("/api/toggles");
|
||||
context.commit("setToggles", result);
|
||||
callback();
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user