diff --git a/app.go b/app.go index af53038..16fea9c 100644 --- a/app.go +++ b/app.go @@ -3,11 +3,16 @@ package main import ( "context" "fmt" + "os" + + "git.cems.dev/cdricms/bdooc/proto" + "github.com/wailsapp/wails/v2/pkg/runtime" ) // App struct type App struct { - ctx context.Context + ctx context.Context + employees *proto.EmployeeList // Caching purposes } // NewApp creates a new App application struct @@ -21,7 +26,60 @@ func (a *App) startup(ctx context.Context) { a.ctx = ctx } -// Greet returns a greeting for the given name -func (a *App) Greet(name string) string { - return fmt.Sprintf("Hello %s, It's show time!", name) +func (a *App) GetEmployees(path string, limit, page uint, column, query *string) ([]*proto.Employee, error) { + if a.employees == nil { + e, err := proto.LoadFromFile(path) + if err != nil { + return nil, err + } + a.employees = e + } + + if column != nil && query != nil { + e, err := a.employees.QueryEmployeesByColumn(proto.EmployeeField(proto.SnakeCaseToPascalCase(*column)), *query) + if err != nil { + return nil, err + } + if uint(len(e)) < page*limit+limit { + return e[page*limit:], nil + } + return e[page*limit : page*limit+limit], nil + } + + if uint(len(a.employees.Employees)) < page*limit+limit { + return a.employees.Employees[page*limit:], nil + } + return a.employees.Employees[page*limit : page*limit+limit], nil +} + +func (a *App) SaveData(data []uint8, filename string) { + err := proto.SaveToFile(data, filename) + if err != nil { + panic(err) + } +} + +func (a *App) GetProtoPath() string { + return a.OpenPath([]runtime.FileFilter{{ + DisplayName: "Proto binary file", + Pattern: "*.bin", + }}) +} + +func (a *App) OpenPath(filters []runtime.FileFilter) string { + path, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{ + Filters: filters, + }) + + if err != nil { + panic(err) + } + + return path +} + +func (a *App) IsPathValid(path string) bool { + _, err := os.Stat(path) + fmt.Println(path) + return !os.IsNotExist(err) } diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index 1987eb0..de522fc 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -1,79 +1,35 @@
- -
{resultText}
-
- - -
+ {#if path} + + + {page+1} + + {/if} diff --git a/frontend/src/Table.svelte b/frontend/src/Table.svelte new file mode 100644 index 0000000..4bf5352 --- /dev/null +++ b/frontend/src/Table.svelte @@ -0,0 +1,92 @@ + + +
+ {#await listEmployees(path, limit, page, column, query)} +

Loading...

+ {:then employees} +
+ + + +
+
+ + {#each Object.keys(employees[0]) as key} + + {/each} + + {#each employees as employee} + + {#each Object.values(employee) as value} + + {/each} + + {/each} +
{key}
{value}
+ {:catch error} +

{error}

+ {/await} + + + diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 02a3bb9..fc6a020 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -1,4 +1,14 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +import {proto} from '../models'; +import {frontend} from '../models'; -export function Greet(arg1:string):Promise; +export function GetEmployees(arg1:string,arg2:number,arg3:number,arg4:any,arg5:any):Promise>; + +export function GetProtoPath():Promise; + +export function IsPathValid(arg1:string):Promise; + +export function OpenPath(arg1:Array):Promise; + +export function SaveData(arg1:Array,arg2:string):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index c71ae77..e52b28d 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,6 +2,22 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -export function Greet(arg1) { - return window['go']['main']['App']['Greet'](arg1); +export function GetEmployees(arg1, arg2, arg3, arg4, arg5) { + return window['go']['main']['App']['GetEmployees'](arg1, arg2, arg3, arg4, arg5); +} + +export function GetProtoPath() { + return window['go']['main']['App']['GetProtoPath'](); +} + +export function IsPathValid(arg1) { + return window['go']['main']['App']['IsPathValid'](arg1); +} + +export function OpenPath(arg1) { + return window['go']['main']['App']['OpenPath'](arg1); +} + +export function SaveData(arg1, arg2) { + return window['go']['main']['App']['SaveData'](arg1, arg2); } diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts new file mode 100755 index 0000000..d272b97 --- /dev/null +++ b/frontend/wailsjs/go/models.ts @@ -0,0 +1,87 @@ +export namespace proto { + + export class Employee { + emp_id?: number; + name_prefix?: string; + first_name?: string; + middle_initial?: string; + last_name?: string; + gender?: number; + email?: string; + fathers_name?: string; + mothers_name?: string; + mothers_maiden_name?: string; + birthdate?: string; + birth_time?: string; + weight_kg?: number; + joining_date?: string; + joining_quarter?: number; + joining_half?: number; + joining_year?: number; + joining_month?: number; + joining_month_name?: number; + joining_month_name_short?: number; + joining_month_day?: number; + joining_week_day?: number; + joining_week_day_short?: number; + years_of_service?: number; + salary?: number; + latest_hike_percentage?: string; + ssn?: string; + phone_number?: string; + place_name?: string; + county?: string; + city?: string; + state?: string; + zip?: number; + region?: string; + username?: string; + password?: string; + + static createFrom(source: any = {}) { + return new Employee(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.emp_id = source["emp_id"]; + this.name_prefix = source["name_prefix"]; + this.first_name = source["first_name"]; + this.middle_initial = source["middle_initial"]; + this.last_name = source["last_name"]; + this.gender = source["gender"]; + this.email = source["email"]; + this.fathers_name = source["fathers_name"]; + this.mothers_name = source["mothers_name"]; + this.mothers_maiden_name = source["mothers_maiden_name"]; + this.birthdate = source["birthdate"]; + this.birth_time = source["birth_time"]; + this.weight_kg = source["weight_kg"]; + this.joining_date = source["joining_date"]; + this.joining_quarter = source["joining_quarter"]; + this.joining_half = source["joining_half"]; + this.joining_year = source["joining_year"]; + this.joining_month = source["joining_month"]; + this.joining_month_name = source["joining_month_name"]; + this.joining_month_name_short = source["joining_month_name_short"]; + this.joining_month_day = source["joining_month_day"]; + this.joining_week_day = source["joining_week_day"]; + this.joining_week_day_short = source["joining_week_day_short"]; + this.years_of_service = source["years_of_service"]; + this.salary = source["salary"]; + this.latest_hike_percentage = source["latest_hike_percentage"]; + this.ssn = source["ssn"]; + this.phone_number = source["phone_number"]; + this.place_name = source["place_name"]; + this.county = source["county"]; + this.city = source["city"]; + this.state = source["state"]; + this.zip = source["zip"]; + this.region = source["region"]; + this.username = source["username"]; + this.password = source["password"]; + } + } + +} + diff --git a/go.mod b/go.mod index ea0eb65..4f9a1c4 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/leaanthony/go-ansi-parser v1.6.0 // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.6.0 // indirect - github.com/leaanthony/u v1.1.0 // indirect + github.com/leaanthony/u v1.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect diff --git a/go.sum b/go.sum index ab634dd..9580cc0 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRC github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js= github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8= -github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= -github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= +github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= +github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= diff --git a/main.go b/main.go index a00e771..c89cb1c 100644 --- a/main.go +++ b/main.go @@ -2,10 +2,17 @@ package main import ( "embed" + "encoding/csv" + "os" + "git.cems.dev/cdricms/bdooc/parsing" + p "git.cems.dev/cdricms/bdooc/proto" "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/menu" + "github.com/wailsapp/wails/v2/pkg/menu/keys" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/runtime" ) //go:embed all:frontend/dist @@ -14,6 +21,55 @@ var assets embed.FS func main() { // Create an instance of the app structure app := NewApp() + appMenu := menu.NewMenu() + fileMenu := appMenu.AddSubmenu("File") + fileMenu.AddText("Open proto file", keys.CmdOrCtrl("o"), func(_ *menu.CallbackData) { + path := app.GetProtoPath() + runtime.EventsEmit(app.ctx, "proto-opened", path) + }) + + fileMenu.AddText("Convert CSV to Proto", keys.CmdOrCtrl("k"), func(_ *menu.CallbackData) { + path := app.OpenPath([]runtime.FileFilter{{ + DisplayName: "CSV file", + Pattern: "*.csv", + }}) + + employeesProtoChan := make(chan *p.EmployeeList) + + go func() { + // Parse CSV to Go Struct + file, err := os.Open(path) + if err != nil { + panic(err) + } + defer file.Close() + reader := csv.NewReader(file) + employees, err := parsing.UnmarshalEmployees(reader) + if err != nil { + panic(err) + } + // Convert CSV's Go struct to Proto + employeesProto := parsing.MapToProto(employees) + employeesProtoChan <- employeesProto + }() + + // Get the filepath from the user. + filePath, err := runtime.SaveFileDialog(app.ctx, runtime.SaveDialogOptions{ + Title: "Destination for Proto file.", + Filters: []runtime.FileFilter{{ + DisplayName: "Proto binary file", + Pattern: "*.bin", + }}, + }) + if err != nil { + panic(err) + } + // Await the conversion + employeesProto := <-employeesProtoChan + // Save + employeesProto.SaveToFile(filePath) + runtime.EventsEmit(app.ctx, "csv-converted", filePath) + }) // Create application with options err := wails.Run(&options.App{ @@ -23,6 +79,7 @@ func main() { AssetServer: &assetserver.Options{ Assets: assets, }, + Menu: appMenu, BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, OnStartup: app.startup, Bind: []interface{}{ diff --git a/proto/io.go b/proto/io.go index 3219739..24aa5f7 100644 --- a/proto/io.go +++ b/proto/io.go @@ -6,6 +6,15 @@ import ( // "git.cems.dev/cdricms/bdooc/parsing" ) +func SaveToFile(data []uint8, filename string) error { + EmployeeList := &EmployeeList{} + err := proto.Unmarshal(data, EmployeeList) + if err != nil { + return err + } + return EmployeeList.SaveToFile(filename) +} + func (el *EmployeeList) SaveToFile(filename string) error { data, err := proto.Marshal(el) if err != nil { diff --git a/proto/queries.go b/proto/queries.go index 6590772..eee7243 100644 --- a/proto/queries.go +++ b/proto/queries.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "reflect" + "strings" ) func GetMax[T float64 | float32 | int | uint | int8 | uint8 | int16 | uint16 | int32 | uint32 | int64 | uint64](a, b T) T { @@ -62,6 +63,15 @@ const ( FieldPassword = "Password" ) +func SnakeCaseToPascalCase(s string) string { + words := strings.Split(s, "_") + for i, word := range words { + words[i] = strings.ToUpper(word[0:1]) + strings.ToLower(word[1:]) + } + return strings.Join(words, "") +} + + func (e *Employee) Copy() Employee { return Employee{ EmpId: e.GetEmpId(),