diff --git a/.xlsx b/.xlsx new file mode 100755 index 0000000..01b4c50 Binary files /dev/null and b/.xlsx differ diff --git a/frontend/bindings/app/internal/services/authorservice.ts b/frontend/bindings/app/internal/services/authorservice.ts index b6380f1..8d42285 100644 --- a/frontend/bindings/app/internal/services/authorservice.ts +++ b/frontend/bindings/app/internal/services/authorservice.ts @@ -50,6 +50,15 @@ export function GetById(id: number): Promise<$models.Author | null> & { cancel() 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 } { let $resultPromise = $Call.ByID(2240704960, item) as any; let $typingPromise = $resultPromise.then(($result: any) => { diff --git a/frontend/src/author/AuthorScheme.vue b/frontend/src/author/AuthorScheme.vue index dab27ea..97f3a1c 100644 --- a/frontend/src/author/AuthorScheme.vue +++ b/frontend/src/author/AuthorScheme.vue @@ -5,6 +5,7 @@ import { getDefaultValues } from "../utils/structs/defaults.util"; import Service from "./author.service.ts"; import type { Scheme } from "../types/scheme.type"; import { Author } from "../../bindings/app/internal/services"; +import { SortedByOrder } from "../../bindings/app/internal/services/authorservice.ts"; import { ref } from "vue"; import type { Validate } from "../types/validate.type"; @@ -29,7 +30,8 @@ const load = async () => { }; onMounted(async () => { - load(); + await load(); + console.log(await SortedByOrder({"Name": "ASC"})) }); const scheme: Scheme = reactive({ diff --git a/internal/dialogs/dialogs.go b/internal/dialogs/dialogs.go index aafbc30..b0a8de3 100644 --- a/internal/dialogs/dialogs.go +++ b/internal/dialogs/dialogs.go @@ -18,7 +18,7 @@ func ErrorDialog(title string, message string) { 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() if err != nil { return "", err diff --git a/internal/extras/excel/export.go b/internal/extras/excel/export.go index bc17675..d8f843d 100644 --- a/internal/extras/excel/export.go +++ b/internal/extras/excel/export.go @@ -329,7 +329,7 @@ func ApplyStyleHeaders(file *excelize.File, sheetName string, headers TableHeade } func WriteData(file *excelize.File, filename string) error { - filepath, err := dialogs.SaveFileDialog("Экспорт данных", filename) + filepath, err := dialogs.SaveFileDialog(filename) if !strings.HasSuffix(filepath, ".xlsx") { filepath += ".xlsx" diff --git a/internal/services/author.go b/internal/services/author.go index b3049a9..a749c66 100644 --- a/internal/services/author.go +++ b/internal/services/author.go @@ -4,31 +4,30 @@ import ( "app/internal/dal" "app/internal/database" "app/internal/models" + "app/internal/utils" "errors" - "gorm.io/gen/field" "gorm.io/gorm" ) -type AuthorService struct{} +type AuthorService struct { +} type Author = models.Author func (service *AuthorService) Create(item Author) (Author, error) { - ReplaceEmptySlicesWithNil(&item) + utils.ReplaceEmptySlicesWithNil(&item) err := dal.Author.Create(&item) if err != nil { return item, err } - err = AppendAssociations(database.GetInstance(), &item) + err = utils.AppendAssociations(database.GetInstance(), &item) return item, err } - func (service *AuthorService) GetAll() ([]*Author, error) { var authors []*Author authors, err := dal.Author.Preload(field.Associations).Find() return authors, err } - func (service *AuthorService) GetById(id uint) (*Author, error) { item, err := dal.Author.Preload(field.Associations).Where(dal.Author.Id.Eq(id)).First() if err != nil { @@ -40,16 +39,13 @@ func (service *AuthorService) GetById(id uint) (*Author, error) { } return item, nil } - func (service *AuthorService) Update(item Author) (Author, error) { - ReplaceEmptySlicesWithNil(&item) - + utils.ReplaceEmptySlicesWithNil(&item) _, err := dal.Author.Updates(&item) if err != nil { return item, err } - - err = UpdateAssociations(database.GetInstance(), &item) + err = utils.UpdateAssociations(database.GetInstance(), &item) if err != nil { return item, err @@ -57,13 +53,15 @@ func (service *AuthorService) Update(item Author) (Author, error) { return item, err } - func (service *AuthorService) Delete(id uint) error { _, err := dal.Author.Unscoped().Where(dal.Author.Id.Eq(id)).Delete() return err } - func (service *AuthorService) Count() (int64, error) { amount, err := dal.Author.Count() return amount, err } + +func (service *AuthorService) SortedByOrder(fieldsSortOrder map[string]string) ([]*Author, error) { + return utils.SortByOrder(fieldsSortOrder, Author{}) +} diff --git a/internal/services/comment.go b/internal/services/comment.go index 5039867..34b9bf8 100644 --- a/internal/services/comment.go +++ b/internal/services/comment.go @@ -4,6 +4,7 @@ import ( "app/internal/dal" "app/internal/database" "app/internal/models" + "app/internal/utils" "errors" "gorm.io/gen/field" @@ -15,12 +16,12 @@ type CommentService struct { type Comment = models.Comment func (service *CommentService) Create(item Comment) (Comment, error) { - ReplaceEmptySlicesWithNil(&item) + utils.ReplaceEmptySlicesWithNil(&item) err := dal.Comment.Preload(field.Associations).Create(&item) if err != nil { return item, err } - err = AppendAssociations(database.GetInstance(), &item) + err = utils.AppendAssociations(database.GetInstance(), &item) return item, err } @@ -43,13 +44,13 @@ func (service *CommentService) GetById(id uint) (*Comment, error) { } func (service *CommentService) Update(item Comment) (Comment, error) { - ReplaceEmptySlicesWithNil(&item) + utils.ReplaceEmptySlicesWithNil(&item) err := dal.Comment.Preload(field.Associations).Save(&item) if err != nil { return item, err } - err = UpdateAssociations(database.GetInstance(), &item) + err = utils.UpdateAssociations(database.GetInstance(), &item) if err != nil { return item, err diff --git a/internal/services/post.go b/internal/services/post.go index a90936d..38da3f8 100644 --- a/internal/services/post.go +++ b/internal/services/post.go @@ -6,6 +6,7 @@ import ( "app/internal/dialogs" "app/internal/extras/excel" "app/internal/models" + "app/internal/utils" "errors" "fmt" @@ -17,12 +18,12 @@ type PostService struct{} type Post = models.Post func (service *PostService) Create(item Post) (Post, error) { - ReplaceEmptySlicesWithNil(&item) + utils.ReplaceEmptySlicesWithNil(&item) err := dal.Post.Preload(field.Associations).Create(&item) if err != nil { return item, err } - err = AppendAssociations(database.GetInstance(), &item) + err = utils.AppendAssociations(database.GetInstance(), &item) return item, err } 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) { - ReplaceEmptySlicesWithNil(&item) + utils.ReplaceEmptySlicesWithNil(&item) err := dal.Post.Preload(field.Associations).Save(&item) if err != nil { return item, err } - err = UpdateAssociations(database.GetInstance(), &item) + err = utils.UpdateAssociations(database.GetInstance(), &item) if err != nil { return item, err } diff --git a/internal/services/posttype.go b/internal/services/posttype.go index 6054de6..bf28af8 100644 --- a/internal/services/posttype.go +++ b/internal/services/posttype.go @@ -6,6 +6,7 @@ import ( "app/internal/dialogs" "app/internal/extras/excel" "app/internal/models" + "app/internal/utils" "errors" "gorm.io/gen/field" "gorm.io/gorm" @@ -17,12 +18,12 @@ type PostTypeService struct { type PostType = models.PostType func (service *PostTypeService) Create(item PostType) (PostType, error) { - ReplaceEmptySlicesWithNil(&item) + utils.ReplaceEmptySlicesWithNil(&item) err := dal.PostType.Preload(field.Associations).Create(&item) if err != nil { return item, err } - err = AppendAssociations(database.GetInstance(), &item) + err = utils.AppendAssociations(database.GetInstance(), &item) return item, err } func (service *PostTypeService) GetAll() ([]*PostType, error) { @@ -42,12 +43,12 @@ func (service *PostTypeService) GetById(id uint) (*PostType, error) { return item, nil } func (service *PostTypeService) Update(item PostType) (PostType, error) { - ReplaceEmptySlicesWithNil(&item) + utils.ReplaceEmptySlicesWithNil(&item) err := dal.PostType.Preload(field.Associations).Save(&item) if err != nil { return item, err } - err = UpdateAssociations(database.GetInstance(), &item) + err = utils.UpdateAssociations(database.GetInstance(), &item) if err != nil { return item, err } diff --git a/internal/services/update_associations.go b/internal/services/update_associations.go deleted file mode 100644 index 6b186e3..0000000 --- a/internal/services/update_associations.go +++ /dev/null @@ -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 -} diff --git a/internal/services/append_associations.go b/internal/utils/append_associations.go similarity index 98% rename from internal/services/append_associations.go rename to internal/utils/append_associations.go index 0ba068f..ad667fc 100644 --- a/internal/services/append_associations.go +++ b/internal/utils/append_associations.go @@ -1,4 +1,4 @@ -package services +package utils import ( "errors" diff --git a/internal/services/handle_nil.go b/internal/utils/replace_empty_to_nil.go similarity index 98% rename from internal/services/handle_nil.go rename to internal/utils/replace_empty_to_nil.go index 985c376..d941009 100644 --- a/internal/services/handle_nil.go +++ b/internal/utils/replace_empty_to_nil.go @@ -1,4 +1,4 @@ -package services +package utils import "reflect" diff --git a/internal/utils/sorting.go b/internal/utils/sorting.go new file mode 100644 index 0000000..ebaa331 --- /dev/null +++ b/internal/utils/sorting.go @@ -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 +} diff --git a/internal/utils/update_associations.go b/internal/utils/update_associations.go new file mode 100644 index 0000000..1c9a8eb --- /dev/null +++ b/internal/utils/update_associations.go @@ -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 +}