refactor(cosy): cosy directory structure

This commit is contained in:
0xJacky 2023-12-11 23:09:47 +08:00
parent 40ca44d183
commit 9d62b3ef03
No known key found for this signature in database
GPG key ID: B6E4A6E4A561BAF0
10 changed files with 333 additions and 92 deletions

View file

@ -29,6 +29,7 @@ type Ctx[T any] struct {
transformer func(*T) any
permanentlyDelete bool
SelectedFields []string
itemKey string
}
func Core[T any](c *gin.Context) *Ctx[T] {
@ -37,51 +38,26 @@ func Core[T any](c *gin.Context) *Ctx[T] {
gormScopes: make([]func(tx *gorm.DB) *gorm.DB, 0),
beforeExecuteHookFunc: make([]func(ctx *Ctx[T]), 0),
beforeDecodeHookFunc: make([]func(ctx *Ctx[T]), 0),
itemKey: "`id`",
}
}
func (c *Ctx[T]) SetItemKey(key string) *Ctx[T] {
c.itemKey = key
return c
}
func (c *Ctx[T]) SetValidRules(rules gin.H) *Ctx[T] {
c.rules = rules
return c
}
func (c *Ctx[T]) BeforeDecodeHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
c.beforeDecodeHookFunc = append(c.beforeDecodeHookFunc, hook...)
return c
}
func (c *Ctx[T]) BeforeExecuteHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
c.beforeExecuteHookFunc = append(c.beforeExecuteHookFunc, hook...)
return c
}
func (c *Ctx[T]) ExecutedHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
c.executedHookFunc = append(c.executedHookFunc, hook...)
return c
}
func (c *Ctx[T]) SetPreloads(args ...string) *Ctx[T] {
c.preloads = append(c.preloads, args...)
return c
}
func (c *Ctx[T]) beforeExecuteHook() {
if len(c.beforeExecuteHookFunc) > 0 {
for _, v := range c.beforeExecuteHookFunc {
v(c)
}
}
}
func (c *Ctx[T]) beforeDecodeHook() {
if len(c.beforeDecodeHookFunc) > 0 {
for _, v := range c.beforeDecodeHookFunc {
v(c)
}
}
}
func (c *Ctx[T]) validate() (errs gin.H) {
c.Payload = make(gin.H)
@ -128,13 +104,3 @@ func (c *Ctx[T]) AbortWithError(err error) {
func (c *Ctx[T]) Abort() {
c.abort = true
}
func (c *Ctx[T]) PermanentlyDelete() *Ctx[T] {
c.permanentlyDelete = true
return c
}
func (c *Ctx[T]) GormScope(hook func(tx *gorm.DB) *gorm.DB) *Ctx[T] {
c.gormScopes = append(c.gormScopes, hook)
return c
}

View file

@ -6,6 +6,11 @@ import (
"net/http"
)
func (c *Ctx[T]) PermanentlyDelete() *Ctx[T] {
c.permanentlyDelete = true
return c
}
func (c *Ctx[T]) Destroy() {
if c.abort {
return

207
api/cosy/filter.go Normal file
View file

@ -0,0 +1,207 @@
package cosy
import (
"fmt"
"github.com/0xJacky/Nginx-UI/internal/logger"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"strings"
)
func (c *Ctx[T]) SetFussy(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return QueryToFussySearch(c.ctx, tx, keys...)
})
return c
}
func (c *Ctx[T]) SetFussyKeys(value string, keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return QueryToFussyKeysSearch(c.ctx, tx, value, keys...)
})
return c
}
func (c *Ctx[T]) SetEqual(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return QueryToEqualSearch(c.ctx, tx, keys...)
})
return c
}
func (c *Ctx[T]) SetIn(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return QueryToInSearch(c.ctx, tx, keys...)
})
return c
}
func (c *Ctx[T]) SetOrFussy(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return QueryToOrFussySearch(c.ctx, tx, keys...)
})
return c
}
func (c *Ctx[T]) SetOrEqual(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return QueryToOrEqualSearch(c.ctx, tx, keys...)
})
return c
}
func (c *Ctx[T]) SetOrIn(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return QueryToOrInSearch(c.ctx, tx, keys...)
})
return c
}
func QueryToInSearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
for _, v := range keys {
queryArray := c.QueryArray(v + "[]")
if len(queryArray) == 0 {
queryArray = c.QueryArray(v)
}
if len(queryArray) > 0 {
var sb strings.Builder
_, err := fmt.Fprintf(&sb, "`%s` IN ?", v)
if err != nil {
logger.Error(err)
continue
}
db = db.Where(sb.String(), queryArray)
}
}
return db
}
func QueryToEqualSearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
for _, v := range keys {
if c.Query(v) != "" {
var sb strings.Builder
_, err := fmt.Fprintf(&sb, "`%s` = ?", v)
if err != nil {
logger.Error(err)
continue
}
db = db.Where(sb.String(), c.Query(v))
}
}
return db
}
func QueryToFussySearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
for _, v := range keys {
if c.Query(v) != "" {
var sb strings.Builder
_, err := fmt.Fprintf(&sb, "`%s` LIKE ?", v)
if err != nil {
logger.Error(err)
continue
}
var sbValue strings.Builder
_, err = fmt.Fprintf(&sbValue, "%%%s%%", c.Query(v))
if err != nil {
logger.Error(err)
continue
}
db = db.Where(sb.String(), sbValue.String())
}
}
return db
}
func QueryToFussyKeysSearch(c *gin.Context, db *gorm.DB, value string, keys ...string) *gorm.DB {
if c.Query(value) == "" {
return db
}
var condition *gorm.DB
for i, v := range keys {
sb := v + " LIKE ?"
sv := "%" + c.Query(value) + "%"
switch i {
case 0:
condition = db.Where(db.Where(sb, sv))
default:
condition = condition.Or(sb, sv)
}
}
return db.Where(condition)
}
func QueryToOrInSearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
for _, v := range keys {
queryArray := c.QueryArray(v + "[]")
if len(queryArray) == 0 {
queryArray = c.QueryArray(v)
}
if len(queryArray) > 0 {
var sb strings.Builder
_, err := fmt.Fprintf(&sb, "`%s` IN ?", v)
if err != nil {
logger.Error(err)
continue
}
db = db.Or(sb.String(), queryArray)
}
}
return db
}
func QueryToOrEqualSearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
for _, v := range keys {
if c.Query(v) != "" {
var sb strings.Builder
_, err := fmt.Fprintf(&sb, "`%s` = ?", v)
if err != nil {
logger.Error(err)
continue
}
db = db.Or(sb.String(), c.Query(v))
}
}
return db
}
func QueryToOrFussySearch(c *gin.Context, db *gorm.DB, keys ...string) *gorm.DB {
for _, v := range keys {
if c.Query(v) != "" {
var sb strings.Builder
_, err := fmt.Fprintf(&sb, "`%s` LIKE ?", v)
if err != nil {
logger.Error(err)
continue
}
var sbValue strings.Builder
_, err = fmt.Fprintf(&sbValue, "%%%s%%", c.Query(v))
if err != nil {
logger.Error(err)
continue
}
db = db.Or(sb.String(), sbValue.String())
}
}
return db
}

39
api/cosy/hook.go Normal file
View file

@ -0,0 +1,39 @@
package cosy
import "gorm.io/gorm"
func (c *Ctx[T]) GormScope(hook func(tx *gorm.DB) *gorm.DB) *Ctx[T] {
c.gormScopes = append(c.gormScopes, hook)
return c
}
func (c *Ctx[T]) beforeExecuteHook() {
if len(c.beforeExecuteHookFunc) > 0 {
for _, v := range c.beforeExecuteHookFunc {
v(c)
}
}
}
func (c *Ctx[T]) beforeDecodeHook() {
if len(c.beforeDecodeHookFunc) > 0 {
for _, v := range c.beforeDecodeHookFunc {
v(c)
}
}
}
func (c *Ctx[T]) BeforeDecodeHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
c.beforeDecodeHookFunc = append(c.beforeDecodeHookFunc, hook...)
return c
}
func (c *Ctx[T]) BeforeExecuteHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
c.beforeExecuteHookFunc = append(c.beforeExecuteHookFunc, hook...)
return c
}
func (c *Ctx[T]) ExecutedHook(hook ...func(ctx *Ctx[T])) *Ctx[T] {
c.executedHookFunc = append(c.executedHookFunc, hook...)
return c
}

View file

@ -4,58 +4,39 @@ import (
"github.com/0xJacky/Nginx-UI/internal/logger"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
"gorm.io/gorm"
"net/http"
)
func (c *Ctx[T]) SetFussy(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return model.QueryToFussySearch(c.ctx, tx, keys...)
})
return c
func GetPagingParams(c *gin.Context) (page, offset, pageSize int) {
page = cast.ToInt(c.Query("page"))
if page == 0 {
page = 1
}
pageSize = settings.ServerSettings.PageSize
reqPageSize := c.Query("page_size")
if reqPageSize != "" {
pageSize = cast.ToInt(reqPageSize)
}
offset = (page - 1) * pageSize
return
}
func (c *Ctx[T]) SetFussyKeys(value string, keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return model.QueryToFussyKeysSearch(c.ctx, tx, value, keys...)
})
return c
}
func (c *Ctx[T]) combineStdSelectorRequest() {
var StdSelectorInitParams struct {
ID []int `json:"id"`
}
func (c *Ctx[T]) SetEqual(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return model.QueryToEqualSearch(c.ctx, tx, keys...)
})
return c
}
if err := c.ctx.ShouldBindJSON(&StdSelectorInitParams); err != nil {
logger.Error(err)
return
}
func (c *Ctx[T]) SetIn(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return model.QueryToInSearch(c.ctx, tx, keys...)
c.GormScope(func(tx *gorm.DB) *gorm.DB {
return tx.Where(c.itemKey+" IN ?", StdSelectorInitParams.ID)
})
return c
}
func (c *Ctx[T]) SetOrFussy(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return model.QueryToOrFussySearch(c.ctx, tx, keys...)
})
return c
}
func (c *Ctx[T]) SetOrEqual(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return model.QueryToOrEqualSearch(c.ctx, tx, keys...)
})
return c
}
func (c *Ctx[T]) SetOrIn(keys ...string) *Ctx[T] {
c.gormScopes = append(c.gormScopes, func(tx *gorm.DB) *gorm.DB {
return model.QueryToOrInSearch(c.ctx, tx, keys...)
})
return c
}
func (c *Ctx[T]) result() (*gorm.DB, bool) {
@ -72,7 +53,7 @@ func (c *Ctx[T]) result() (*gorm.DB, bool) {
var dbModel T
result := model.UseDB()
if c.ctx.Query("trash") == "true" {
if cast.ToBool(c.ctx.Query("trash")) {
stmt := &gorm.Statement{DB: model.UseDB()}
err := stmt.Parse(&dbModel)
if err != nil {
@ -84,6 +65,8 @@ func (c *Ctx[T]) result() (*gorm.DB, bool) {
result = result.Model(&dbModel)
c.combineStdSelectorRequest()
if len(c.gormScopes) > 0 {
result = result.Scopes(c.gormScopes...)
}
@ -97,7 +80,7 @@ func (c *Ctx[T]) ListAllData() ([]*T, bool) {
return nil, false
}
result = result.Scopes(model.SortOrder(c.ctx))
result = result.Scopes(c.SortOrder())
models := make([]*T, 0)
result.Find(&models)
return models, true
@ -109,7 +92,7 @@ func (c *Ctx[T]) PagingListData() (*model.DataList, bool) {
return nil, false
}
result = result.Scopes(model.OrderAndPaginate(c.ctx))
result = result.Scopes(c.OrderAndPaginate())
data := &model.DataList{}
if c.scan == nil {
models := make([]*T, 0)

39
api/cosy/sort.go Normal file
View file

@ -0,0 +1,39 @@
package cosy
import (
"fmt"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
func (c *Ctx[T]) SortOrder() func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
sort := c.ctx.DefaultQuery("order", "desc")
order := fmt.Sprintf("%s %s", DefaultQuery(c.ctx, "sort_by", c.itemKey), sort)
return db.Order(order)
}
}
func (c *Ctx[T]) OrderAndPaginate() func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
sort := c.ctx.DefaultQuery("order", "desc")
order := fmt.Sprintf("%s %s", DefaultQuery(c.ctx, "sort_by", c.itemKey), sort)
db = db.Order(order)
_, offset, pageSize := GetPagingParams(c.ctx)
return db.Offset(offset).Limit(pageSize)
}
}
func DefaultValue(c *gin.Context, key string, defaultValue any) any {
if value, ok := c.Get(key); ok {
return value
}
return defaultValue
}
func DefaultQuery(c *gin.Context, key string, defaultValue any) string {
return c.DefaultQuery(key, DefaultValue(c, key, defaultValue).(string))
}

View file

@ -28,6 +28,8 @@ func (c *Ctx[T]) Modify() {
return
}
var dbModel T
db := model.UseDB()
result := db
@ -35,7 +37,7 @@ func (c *Ctx[T]) Modify() {
result = result.Scopes(c.gormScopes...)
}
err := result.Session(&gorm.Session{}).First(&c.Model, id).Error
err := result.Session(&gorm.Session{}).First(&dbModel, id).Error
if err != nil {
c.AbortWithError(err)
@ -65,7 +67,7 @@ func (c *Ctx[T]) Modify() {
return
}
err = db.Model(&c.Model).Select(selectedFields).Updates(&c.Model).Error
err = db.Model(&dbModel).Select(selectedFields).Updates(&c.Model).Error
if err != nil {
c.AbortWithError(err)
@ -85,6 +87,6 @@ func (c *Ctx[T]) Modify() {
if c.nextHandler != nil {
(*c.nextHandler)(c.ctx)
} else {
c.ctx.JSON(http.StatusOK, c.Model)
c.ctx.JSON(http.StatusOK, dbModel)
}
}

View file

@ -51,7 +51,7 @@
"@vitejs/plugin-vue": "^4.5.0",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-sfc": "^3.3.10",
"ace-builds": "^1.31.2",
"ace-builds": "^1.32.0",
"autoprefixer": "^10.4.16",
"eslint": "^8.54.0",
"eslint-import-resolver-alias": "^1.1.2",

2
app/pnpm-lock.yaml generated
View file

@ -122,7 +122,7 @@ devDependencies:
specifier: ^0.4.0
version: 0.4.0
ace-builds:
specifier: ^1.31.2
specifier: ^1.32.0
version: 1.32.0
autoprefixer:
specifier: ^10.4.16

View file

@ -18,7 +18,7 @@ RUN set -x \
&& curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null \
&& echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
https://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
| tee /etc/apt/sources.list.d/nginx.list
RUN echo "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" | tee /etc/apt/preferences.d/99nginx \