feat: excel importer

This commit is contained in:
2025-03-10 16:31:08 +07:00
parent 8fbbd7b142
commit 6bf4f1e289
12 changed files with 250 additions and 145 deletions

View File

@@ -1,44 +1,45 @@
package dialogs
import (
"fmt"
"github.com/wailsapp/wails/v3/pkg/application"
)
var currentWindow *application.WebviewWindow
func Init(window *application.WebviewWindow) {
if window == nil {
panic("currentWindow is nil")
}
currentWindow = window
}
func checkInit() {
if currentWindow == nil {
panic("Initialize dialogs package before use")
}
}
func InfoDialog(title string, message string) {
checkInit()
application.InfoDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
application.InfoDialog().SetTitle(title).SetMessage(message).Show()
}
func WarningDialog(title string, message string) {
checkInit()
application.WarningDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
application.WarningDialog().SetTitle(title).SetMessage(message).Show()
}
func ErrorDialog(title string, message string) {
checkInit()
application.ErrorDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
application.ErrorDialog().SetTitle(title).SetMessage(message).Show()
}
func SaveFileDialog(title string, filename string) (string, error) {
checkInit()
selection, err := application.SaveFileDialog().AttachToWindow(currentWindow).SetFilename(filename).PromptForSingleSelection()
selection, err := application.SaveFileDialog().SetFilename(filename).PromptForSingleSelection()
if err != nil {
return "", err
}
return selection, nil
}
func OpenFileDialog(title string) (string, error) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
dialog := application.OpenFileDialog()
dialog.SetTitle(title)
dialog.CanChooseDirectories(false)
dialog.AddFilter("Электронные таблицы (.xlsx)", "*.xlsx")
dialog.AddFilter("Электронные таблицы (.xls)", "*.xls")
path, err := dialog.PromptForSingleSelection()
if err != nil {
return "", err
}
return path, nil
}

View File

@@ -0,0 +1,53 @@
package excel
import (
"fmt"
"log/slog"
"github.com/xuri/excelize/v2"
)
type Importer struct {
SheetName string
Loader func(rowIndex int, row []string) error
StartFromRowIdx int
}
func ImportEntitiesFromSpreadsheet(path string, importers ...Importer) error {
for _, importer := range importers {
err := ImportEntitiesFromSpreadsheet(path, importer)
if err != nil {
return err
}
}
return nil
}
func ImportFromSpreadsheet(filepath string, importer Importer) error {
f, err := excelize.OpenFile(filepath)
defer func() {
err := f.Close()
if err != nil {
slog.Error(fmt.Sprintf("Failed to close file: %s", err))
}
}()
if err != nil {
return err
}
rows, err := f.GetRows(importer.SheetName)
if err != nil {
return err
}
for i, row := range rows {
err := importer.Loader(i, row)
if err != nil {
return err
}
}
return nil
}

View File

@@ -13,7 +13,7 @@ type Post struct {
Id uint `gorm:"primaryKey" ui:"hidden"`
Text string `ui:"label:Текст"`
Deadline int64 `ui:"label:Дедлайн;datatype:datetime;"`
CreatedAt int64 `gorm:"autoCreateTime" ui:"readonly;datatype:datetime;"`
CreatedAt int64 `gorm:"autoCreateTime" ui:"label:Время создания; readonly; datatype:datetime;"`
AuthorId uint `ui:"hidden" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Author Author `ui:"label:Автор; field:Name;"`
PostTypeId uint `ui:"hidden"`

View File

@@ -6,10 +6,11 @@ import (
"context"
"crypto/sha256"
"fmt"
"github.com/wailsapp/wails/v3/pkg/application"
"io"
"log/slog"
"os"
"github.com/wailsapp/wails/v3/pkg/application"
)
type Migrator struct{}
@@ -77,9 +78,9 @@ func Migrate(entities ...any) error {
err = db.AutoMigrate(entities...)
if err != nil {
slog.Info("Error occurred while migrations: %s. Recreate database...", err)
slog.Info(fmt.Sprintf("Error occurred while migrations: %s, Recreate database...", err))
if err = createDatabase(entities...); err != nil {
slog.Error("Error occurred again: %s. Panic!", err)
slog.Error(fmt.Sprintf("Error occurred again: %s. Panic!", err))
return err
}
} else {
@@ -87,7 +88,7 @@ func Migrate(entities ...any) error {
var hashAfterMigration string
hashAfterMigration, err = CalculateFileSha256Checksum(database.Path)
if err != nil {
slog.Error("Failed to calc hash: %s", err)
slog.Error(fmt.Sprintf("Failed to calc hash: %s", err))
return err
}
@@ -95,7 +96,7 @@ func Migrate(entities ...any) error {
slog.Info("Hashes before and after migrations are different. Recreate database...")
err = createDatabase(entities...)
if err != nil {
slog.Error("Failed to create new database: %s", err)
slog.Error(fmt.Sprintf("Failed to create new database: %s", err))
return err
}
}

View File

@@ -3,8 +3,13 @@ package services
import (
"app/internal/dal"
"app/internal/database"
"app/internal/dialogs"
"app/internal/extras/excel"
"app/internal/models"
"errors"
"os/signal"
"strconv"
"syscall"
"gorm.io/gen/field"
"gorm.io/gorm"
@@ -59,3 +64,30 @@ func (service *PostTypeService) Count() (int64, error) {
amount, err := dal.PostType.Count()
return amount, err
}
func (service *PostTypeService) ImportFromExcel() error {
signal.Ignore(syscall.SIGSEGV)
filepath, err := dialogs.OpenFileDialog("Импорт данных")
if err != nil {
return err
}
err = excel.ImportFromSpreadsheet(filepath, excel.Importer{
SheetName: "Тип поста",
Loader: func(rowIndex int, row []string) error {
id, err := strconv.Atoi(row[0])
if err != nil {
return err
}
service.Create(PostType{
Id: uint(id),
Name: row[1],
})
return nil
},
})
if err != nil {
return err
}
return nil
}