feat: sorting for primitive fields
# Conflicts: # frontend/src/App.vue
This commit is contained in:
@@ -50,6 +50,15 @@ export function GetById(id: number): Promise<$models.Author | null> & { cancel()
|
|||||||
return $typingPromise;
|
return $typingPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SortedByOrder(fieldsSortOrder: { [_: string]: string }): Promise<($models.Author | null)[]> & { cancel(): void } {
|
||||||
|
let $resultPromise = $Call.ByID(3046628691, fieldsSortOrder) as any;
|
||||||
|
let $typingPromise = $resultPromise.then(($result: any) => {
|
||||||
|
return $$createType2($result);
|
||||||
|
}) as any;
|
||||||
|
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
|
||||||
|
return $typingPromise;
|
||||||
|
}
|
||||||
|
|
||||||
export function Update(item: $models.Author): Promise<$models.Author> & { cancel(): void } {
|
export function Update(item: $models.Author): Promise<$models.Author> & { cancel(): void } {
|
||||||
let $resultPromise = $Call.ByID(2240704960, item) as any;
|
let $resultPromise = $Call.ByID(2240704960, item) as any;
|
||||||
let $typingPromise = $resultPromise.then(($result: any) => {
|
let $typingPromise = $resultPromise.then(($result: any) => {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { getDefaultValues } from "../utils/structs/defaults.util";
|
|||||||
import Service from "./author.service.ts";
|
import Service from "./author.service.ts";
|
||||||
import type { Scheme } from "../types/scheme.type";
|
import type { Scheme } from "../types/scheme.type";
|
||||||
import { Author } from "../../bindings/app/internal/services";
|
import { Author } from "../../bindings/app/internal/services";
|
||||||
|
import { SortedByOrder } from "../../bindings/app/internal/services/authorservice.ts";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import type { Validate } from "../types/validate.type";
|
import type { Validate } from "../types/validate.type";
|
||||||
|
|
||||||
@@ -29,7 +30,8 @@ const load = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
load();
|
await load();
|
||||||
|
console.log(await SortedByOrder({"Name": "ASC"}))
|
||||||
});
|
});
|
||||||
|
|
||||||
const scheme: Scheme<Author> = reactive({
|
const scheme: Scheme<Author> = reactive({
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func ErrorDialog(title string, message string) {
|
|||||||
application.ErrorDialog().SetTitle(title).SetMessage(message).Show()
|
application.ErrorDialog().SetTitle(title).SetMessage(message).Show()
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveFileDialog(title string, filename string) (string, error) {
|
func SaveFileDialog(filename string) (string, error) {
|
||||||
selection, err := application.SaveFileDialog().SetFilename(filename).PromptForSingleSelection()
|
selection, err := application.SaveFileDialog().SetFilename(filename).PromptForSingleSelection()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ func ApplyStyleHeaders(file *excelize.File, sheetName string, headers TableHeade
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WriteData(file *excelize.File, filename string) error {
|
func WriteData(file *excelize.File, filename string) error {
|
||||||
filepath, err := dialogs.SaveFileDialog("Экспорт данных", filename)
|
filepath, err := dialogs.SaveFileDialog(filename)
|
||||||
|
|
||||||
if !strings.HasSuffix(filepath, ".xlsx") {
|
if !strings.HasSuffix(filepath, ".xlsx") {
|
||||||
filepath += ".xlsx"
|
filepath += ".xlsx"
|
||||||
|
|||||||
@@ -4,31 +4,30 @@ import (
|
|||||||
"app/internal/dal"
|
"app/internal/dal"
|
||||||
"app/internal/database"
|
"app/internal/database"
|
||||||
"app/internal/models"
|
"app/internal/models"
|
||||||
|
"app/internal/utils"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"gorm.io/gen/field"
|
"gorm.io/gen/field"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthorService struct{}
|
type AuthorService struct {
|
||||||
|
}
|
||||||
type Author = models.Author
|
type Author = models.Author
|
||||||
|
|
||||||
func (service *AuthorService) Create(item Author) (Author, error) {
|
func (service *AuthorService) Create(item Author) (Author, error) {
|
||||||
ReplaceEmptySlicesWithNil(&item)
|
utils.ReplaceEmptySlicesWithNil(&item)
|
||||||
err := dal.Author.Create(&item)
|
err := dal.Author.Create(&item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
err = AppendAssociations(database.GetInstance(), &item)
|
err = utils.AppendAssociations(database.GetInstance(), &item)
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (service *AuthorService) GetAll() ([]*Author, error) {
|
func (service *AuthorService) GetAll() ([]*Author, error) {
|
||||||
var authors []*Author
|
var authors []*Author
|
||||||
authors, err := dal.Author.Preload(field.Associations).Find()
|
authors, err := dal.Author.Preload(field.Associations).Find()
|
||||||
return authors, err
|
return authors, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (service *AuthorService) GetById(id uint) (*Author, error) {
|
func (service *AuthorService) GetById(id uint) (*Author, error) {
|
||||||
item, err := dal.Author.Preload(field.Associations).Where(dal.Author.Id.Eq(id)).First()
|
item, err := dal.Author.Preload(field.Associations).Where(dal.Author.Id.Eq(id)).First()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -40,16 +39,13 @@ func (service *AuthorService) GetById(id uint) (*Author, error) {
|
|||||||
}
|
}
|
||||||
return item, nil
|
return item, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (service *AuthorService) Update(item Author) (Author, error) {
|
func (service *AuthorService) Update(item Author) (Author, error) {
|
||||||
ReplaceEmptySlicesWithNil(&item)
|
utils.ReplaceEmptySlicesWithNil(&item)
|
||||||
|
|
||||||
_, err := dal.Author.Updates(&item)
|
_, err := dal.Author.Updates(&item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
err = utils.UpdateAssociations(database.GetInstance(), &item)
|
||||||
err = UpdateAssociations(database.GetInstance(), &item)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
@@ -57,13 +53,15 @@ func (service *AuthorService) Update(item Author) (Author, error) {
|
|||||||
|
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (service *AuthorService) Delete(id uint) error {
|
func (service *AuthorService) Delete(id uint) error {
|
||||||
_, err := dal.Author.Unscoped().Where(dal.Author.Id.Eq(id)).Delete()
|
_, err := dal.Author.Unscoped().Where(dal.Author.Id.Eq(id)).Delete()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (service *AuthorService) Count() (int64, error) {
|
func (service *AuthorService) Count() (int64, error) {
|
||||||
amount, err := dal.Author.Count()
|
amount, err := dal.Author.Count()
|
||||||
return amount, err
|
return amount, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (service *AuthorService) SortedByOrder(fieldsSortOrder map[string]string) ([]*Author, error) {
|
||||||
|
return utils.SortByOrder(fieldsSortOrder, Author{})
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"app/internal/dal"
|
"app/internal/dal"
|
||||||
"app/internal/database"
|
"app/internal/database"
|
||||||
"app/internal/models"
|
"app/internal/models"
|
||||||
|
"app/internal/utils"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"gorm.io/gen/field"
|
"gorm.io/gen/field"
|
||||||
@@ -15,12 +16,12 @@ type CommentService struct {
|
|||||||
type Comment = models.Comment
|
type Comment = models.Comment
|
||||||
|
|
||||||
func (service *CommentService) Create(item Comment) (Comment, error) {
|
func (service *CommentService) Create(item Comment) (Comment, error) {
|
||||||
ReplaceEmptySlicesWithNil(&item)
|
utils.ReplaceEmptySlicesWithNil(&item)
|
||||||
err := dal.Comment.Preload(field.Associations).Create(&item)
|
err := dal.Comment.Preload(field.Associations).Create(&item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
err = AppendAssociations(database.GetInstance(), &item)
|
err = utils.AppendAssociations(database.GetInstance(), &item)
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,13 +44,13 @@ func (service *CommentService) GetById(id uint) (*Comment, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (service *CommentService) Update(item Comment) (Comment, error) {
|
func (service *CommentService) Update(item Comment) (Comment, error) {
|
||||||
ReplaceEmptySlicesWithNil(&item)
|
utils.ReplaceEmptySlicesWithNil(&item)
|
||||||
err := dal.Comment.Preload(field.Associations).Save(&item)
|
err := dal.Comment.Preload(field.Associations).Save(&item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UpdateAssociations(database.GetInstance(), &item)
|
err = utils.UpdateAssociations(database.GetInstance(), &item)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"app/internal/dialogs"
|
"app/internal/dialogs"
|
||||||
"app/internal/extras/excel"
|
"app/internal/extras/excel"
|
||||||
"app/internal/models"
|
"app/internal/models"
|
||||||
|
"app/internal/utils"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
@@ -17,12 +18,12 @@ type PostService struct{}
|
|||||||
type Post = models.Post
|
type Post = models.Post
|
||||||
|
|
||||||
func (service *PostService) Create(item Post) (Post, error) {
|
func (service *PostService) Create(item Post) (Post, error) {
|
||||||
ReplaceEmptySlicesWithNil(&item)
|
utils.ReplaceEmptySlicesWithNil(&item)
|
||||||
err := dal.Post.Preload(field.Associations).Create(&item)
|
err := dal.Post.Preload(field.Associations).Create(&item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
err = AppendAssociations(database.GetInstance(), &item)
|
err = utils.AppendAssociations(database.GetInstance(), &item)
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
func (service *PostService) GetAll() ([]*Post, error) {
|
func (service *PostService) GetAll() ([]*Post, error) {
|
||||||
@@ -43,12 +44,12 @@ func (service *PostService) GetById(id uint) (*Post, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (service *PostService) Update(item Post) (Post, error) {
|
func (service *PostService) Update(item Post) (Post, error) {
|
||||||
ReplaceEmptySlicesWithNil(&item)
|
utils.ReplaceEmptySlicesWithNil(&item)
|
||||||
err := dal.Post.Preload(field.Associations).Save(&item)
|
err := dal.Post.Preload(field.Associations).Save(&item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
err = UpdateAssociations(database.GetInstance(), &item)
|
err = utils.UpdateAssociations(database.GetInstance(), &item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"app/internal/dialogs"
|
"app/internal/dialogs"
|
||||||
"app/internal/extras/excel"
|
"app/internal/extras/excel"
|
||||||
"app/internal/models"
|
"app/internal/models"
|
||||||
|
"app/internal/utils"
|
||||||
"errors"
|
"errors"
|
||||||
"gorm.io/gen/field"
|
"gorm.io/gen/field"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -17,12 +18,12 @@ type PostTypeService struct {
|
|||||||
type PostType = models.PostType
|
type PostType = models.PostType
|
||||||
|
|
||||||
func (service *PostTypeService) Create(item PostType) (PostType, error) {
|
func (service *PostTypeService) Create(item PostType) (PostType, error) {
|
||||||
ReplaceEmptySlicesWithNil(&item)
|
utils.ReplaceEmptySlicesWithNil(&item)
|
||||||
err := dal.PostType.Preload(field.Associations).Create(&item)
|
err := dal.PostType.Preload(field.Associations).Create(&item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
err = AppendAssociations(database.GetInstance(), &item)
|
err = utils.AppendAssociations(database.GetInstance(), &item)
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
func (service *PostTypeService) GetAll() ([]*PostType, error) {
|
func (service *PostTypeService) GetAll() ([]*PostType, error) {
|
||||||
@@ -42,12 +43,12 @@ func (service *PostTypeService) GetById(id uint) (*PostType, error) {
|
|||||||
return item, nil
|
return item, nil
|
||||||
}
|
}
|
||||||
func (service *PostTypeService) Update(item PostType) (PostType, error) {
|
func (service *PostTypeService) Update(item PostType) (PostType, error) {
|
||||||
ReplaceEmptySlicesWithNil(&item)
|
utils.ReplaceEmptySlicesWithNil(&item)
|
||||||
err := dal.PostType.Preload(field.Associations).Save(&item)
|
err := dal.PostType.Preload(field.Associations).Save(&item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
err = UpdateAssociations(database.GetInstance(), &item)
|
err = utils.UpdateAssociations(database.GetInstance(), &item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
package services
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func UpdateAssociations(db *gorm.DB, item interface{}) error {
|
|
||||||
// We expect a pointer to a struct so we can do db.Model(item).
|
|
||||||
val := reflect.ValueOf(item)
|
|
||||||
if val.Kind() != reflect.Ptr {
|
|
||||||
return errors.New("item must be a pointer to a struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
elem := val.Elem()
|
|
||||||
if elem.Kind() != reflect.Struct {
|
|
||||||
return errors.New("item must be a pointer to a struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
t := elem.Type()
|
|
||||||
for i := 0; i < elem.NumField(); i++ {
|
|
||||||
fieldVal := elem.Field(i)
|
|
||||||
fieldType := t.Field(i)
|
|
||||||
|
|
||||||
// Only process exported fields (capitalized) and slices.
|
|
||||||
if fieldType.PkgPath == "" && fieldVal.Kind() == reflect.Slice {
|
|
||||||
// For clarity, the association name is the struct field name by default.
|
|
||||||
assocName := fieldType.Name
|
|
||||||
|
|
||||||
// Replace the association with the current slice value.
|
|
||||||
// If you only want to replace on non-nil or non-empty slices, you can add extra checks here.
|
|
||||||
if err := db.Model(item).Association(assocName).Replace(fieldVal.Interface()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package services
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package services
|
package utils
|
||||||
|
|
||||||
import "reflect"
|
import "reflect"
|
||||||
|
|
||||||
40
internal/utils/sorting.go
Normal file
40
internal/utils/sorting.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"app/internal/database"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SortByOrder Order items by specified field and a sort type
|
||||||
|
// Example: SortByOrder(map[string]string{"name": "ASC"}, &models.Post{})
|
||||||
|
// ASC - по возрастанию (от А до Я)
|
||||||
|
// DESC - по убыванию (от Я до А)
|
||||||
|
func SortByOrder[T any](fieldsSortOrder map[string]string, entity T) ([]*T, error) {
|
||||||
|
var (
|
||||||
|
orderQuery string
|
||||||
|
items []*T
|
||||||
|
)
|
||||||
|
|
||||||
|
for name, order := range fieldsSortOrder {
|
||||||
|
structInfo := reflect.ValueOf(entity).Type()
|
||||||
|
_, fieldExist := structInfo.FieldByName(name)
|
||||||
|
|
||||||
|
if !fieldExist {
|
||||||
|
return nil, errors.New(fmt.Sprintf("Field `%s` not found", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
if order != "ASC" && order != "DESC" {
|
||||||
|
return nil, errors.New(fmt.Sprintf("Field `%s` can only be sorted by ASC or DESC", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
orderQuery += fmt.Sprintf("%s %s", name, order)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := database.GetInstance().Order(orderQuery).Find(&items)
|
||||||
|
if result.Error != nil {
|
||||||
|
return items, result.Error
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
41
internal/utils/update_associations.go
Normal file
41
internal/utils/update_associations.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UpdateAssociations(db *gorm.DB, item interface{}) error {
|
||||||
|
// We expect a pointer to a struct so we can do db.Model(item).
|
||||||
|
val := reflect.ValueOf(item)
|
||||||
|
if val.Kind() != reflect.Ptr {
|
||||||
|
return errors.New("item must be a pointer to a struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
elem := val.Elem()
|
||||||
|
if elem.Kind() != reflect.Struct {
|
||||||
|
return errors.New("item must be a pointer to a struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
t := elem.Type()
|
||||||
|
for i := 0; i < elem.NumField(); i++ {
|
||||||
|
fieldVal := elem.Field(i)
|
||||||
|
fieldType := t.Field(i)
|
||||||
|
|
||||||
|
// Only process exported fields (capitalized) and slices.
|
||||||
|
if fieldType.PkgPath == "" && fieldVal.Kind() == reflect.Slice {
|
||||||
|
// For clarity, the association name is the struct field name by default.
|
||||||
|
assocName := fieldType.Name
|
||||||
|
|
||||||
|
// Replace the association with the current slice value.
|
||||||
|
// If you only want to replace on non-nil or non-empty slices, you can add extra checks here.
|
||||||
|
if err := db.Model(item).Association(assocName).Replace(fieldVal.Interface()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user