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

@@ -50,6 +50,11 @@ export function GetById(id: number): Promise<$models.PostType | null> & { cancel
return $typingPromise; return $typingPromise;
} }
export function ImportFromExcel(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1671814244) as any;
return $resultPromise;
}
export function Update(item: $models.PostType): Promise<$models.PostType> & { cancel(): void } { export function Update(item: $models.PostType): Promise<$models.PostType> & { cancel(): void } {
let $resultPromise = $Call.ByID(2773888269, item) as any; let $resultPromise = $Call.ByID(2773888269, item) as any;
let $typingPromise = $resultPromise.then(($result: any) => { let $typingPromise = $resultPromise.then(($result: any) => {

View File

@@ -1,18 +1,27 @@
<script setup lang="ts"> <script setup lang="ts">
import { Dialog } from 'primevue'; import { Dialog } from "primevue";
import { useErrorStore } from './stores/error.store'; import { useErrorStore } from "./stores/error.store";
import CommentScheme from "./comment/CommentScheme.vue";
import PostScheme from "./post/PostScheme.vue";
import PosttypeScheme from "./posttype/PosttypeScheme.vue";
import AuthorScheme from "./author/AuthorScheme.vue";
const errorStore = useErrorStore() const errorStore = useErrorStore();
</script> </script>
<template> <template>
<Dialog v-model:visible="errorStore.show" maximizable class="w-[400px] h-[400px]"> <Dialog
<template #header> v-model:visible="errorStore.show"
Ошибка maximizable
</template> class="w-[400px] h-[400px]"
<h1 class="text-red-500 text-2xl">{{ errorStore.message }}</h1> >
<template #header> Ошибка </template>
<h1 class="text-red-500 text-2xl">{{ errorStore.message }}</h1>
</Dialog> </Dialog>
<main class="w-screen h-screen"> <main class="w-screen h-screen">
<CommentScheme></CommentScheme>
<PostScheme></PostScheme>
<PosttypeScheme></PosttypeScheme>
<AuthorScheme></AuthorScheme>
</main> </main>
</template> </template>

View File

@@ -22,112 +22,111 @@ const service = new Service();
const items = ref<Post[]>([]); const items = ref<Post[]>([]);
const load = async () => { const load = async () => {
(scheme as any).Author.type!.nested!.values = await authorService.readAll(); (scheme as any).Author.type!.nested!.values = await authorService.readAll();
(scheme as any).PostType.type!.nested!.values = (scheme as any).PostType.type!.nested!.values =
await posttypeService.readAll(); await posttypeService.readAll();
(scheme as any).Comments.type!.nested!.values = (scheme as any).Comments.type!.nested!.values =
await commentService.readAll(); await commentService.readAll();
items.value = await service.readAll(); items.value = await service.readAll();
return items.value; return items.value;
}; };
onMounted(async () => { onMounted(async () => {
load(); await load();
}); });
const scheme: Scheme<Post> = reactive({ const scheme: Scheme<Post> = reactive({
entityId: "PostId", entityId: "PostId",
Id: { Id: {
hidden: true, hidden: true,
type: { type: {
primitive: "number", primitive: "number",
},
}, },
},
Text: { Text: {
russian: "Текст", russian: "Текст",
type: { type: {
primitive: "string", primitive: "string",
},
}, },
},
Deadline: { Deadline: {
russian: "Дедлайн", russian: "Дедлайн",
date: true, date: true,
type: { type: {
primitive: "date", primitive: "date",
},
}, },
},
CreatedAt: { CreatedAt: {
readonly: true, russian: "Дата создания",
date: true, type: {
type: { primitive: "date",
primitive: "date", },
}, },
},
AuthorId: { AuthorId: {
hidden: true, hidden: true,
type: { type: {
primitive: "number", primitive: "number",
},
}, },
},
Author: { Author: {
russian: "Автор", russian: "Автор",
type: { type: {
nested: { nested: {
values: [], values: [],
field: ["Name"], field: ["Name"],
}, },
},
}, },
},
PostTypeId: { PostTypeId: {
hidden: true, hidden: true,
type: { type: {
primitive: "number", primitive: "number",
},
}, },
},
PostType: { PostType: {
russian: "Тип", russian: "Тип",
type: { type: {
nested: { nested: {
values: [], values: [],
field: ["Name"], field: ["Name"],
}, },
},
}, },
},
Comments: { Comments: {
russian: "Комментарии", russian: "Комментарии",
many: true, many: true,
type: { type: {
nested: { nested: {
values: [], values: [],
field: ["Text"], field: ["Text"],
}, },
},
}, },
},
}); });
const getDefaults = () => getDefaultValues(scheme); const getDefaults = () => getDefaultValues(scheme);
const validate: Validate<Post> = (entity) => { const validate: Validate<Post> = (entity) => {
return { return {
status: "success", status: "success",
}; };
}; };
</script> </script>
<template> <template>
<main class="w-screen h-screen"> <main class="w-screen h-screen">
<Table :scheme :service :get-defaults :load :items :validate></Table> <Table :scheme :service :get-defaults :load :items :validate></Table>
</main> </main>
</template> </template>

View File

@@ -7,49 +7,51 @@ import type { Scheme } from "../types/scheme.type";
import { PostType } from "../../bindings/app/internal/services"; import { PostType } from "../../bindings/app/internal/services";
import { ref } from "vue"; import { ref } from "vue";
import type { Validate } from "../types/validate.type"; import type { Validate } from "../types/validate.type";
import { ImportFromExcel } from "../../bindings/app/internal/services/posttypeservice.ts";
const service = new Service(); const service = new Service();
const items = ref<PostType[]>([]); const items = ref<PostType[]>([]);
const load = async () => { const load = async () => {
items.value = await service.readAll(); items.value = await service.readAll();
return items.value; return items.value;
}; };
onMounted(async () => { onMounted(async () => {
load(); await load();
await ImportFromExcel();
}); });
const scheme: Scheme<PostType> = reactive({ const scheme: Scheme<PostType> = reactive({
entityId: "PostTypeId", entityId: "PostTypeId",
Id: { Id: {
hidden: true, hidden: true,
type: { type: {
primitive: "number", primitive: "number",
},
}, },
},
Name: { Name: {
russian: "Название", russian: "Название",
type: { type: {
primitive: "string", primitive: "string",
},
}, },
},
}); });
const getDefaults = () => getDefaultValues(scheme); const getDefaults = () => getDefaultValues(scheme);
const validate: Validate<PostType> = (entity) => { const validate: Validate<PostType> = (entity) => {
return { return {
status: "success", status: "success",
}; };
}; };
</script> </script>
<template> <template>
<main class="w-screen h-screen"> <main class="w-screen h-screen">
<Table :scheme :service :get-defaults :load :items :validate></Table> <Table :scheme :service :get-defaults :load :items :validate></Table>
</main> </main>
</template> </template>

9
go.mod
View File

@@ -5,9 +5,9 @@ go 1.22.4
toolchain go1.23.4 toolchain go1.23.4
require ( require (
github.com/wailsapp/wails/v3 v3.0.0-alpha.8.3 github.com/wailsapp/wails/v3 v3.0.0-alpha.9
github.com/xuri/excelize/v2 v2.9.0 github.com/xuri/excelize/v2 v2.9.0
gorm.io/driver/sqlite v1.5.0 gorm.io/driver/sqlite v1.5.7
gorm.io/gen v0.3.26 gorm.io/gen v0.3.26
gorm.io/gorm v1.25.12 gorm.io/gorm v1.25.12
gorm.io/plugin/dbresolver v1.5.3 gorm.io/plugin/dbresolver v1.5.3
@@ -42,7 +42,7 @@ require (
github.com/lmittmann/tint v1.0.4 // indirect github.com/lmittmann/tint v1.0.4 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
@@ -52,7 +52,7 @@ require (
github.com/samber/lo v1.38.1 // indirect github.com/samber/lo v1.38.1 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect github.com/skeema/knownhosts v1.2.2 // indirect
github.com/wailsapp/go-webview2 v1.0.18 // indirect github.com/wailsapp/go-webview2 v1.0.19 // indirect
github.com/wailsapp/mimetype v1.4.1 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d // indirect
@@ -65,6 +65,7 @@ require (
golang.org/x/sys v0.28.0 // indirect golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.21.0 // indirect
golang.org/x/tools v0.28.0 // indirect golang.org/x/tools v0.28.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gorm.io/datatypes v1.2.5 // indirect gorm.io/datatypes v1.2.5 // indirect
gorm.io/driver/mysql v1.5.7 // indirect gorm.io/driver/mysql v1.5.7 // indirect

16
go.sum
View File

@@ -96,8 +96,9 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA= github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA= github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
@@ -134,12 +135,12 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/wailsapp/go-webview2 v1.0.18 h1:SSSCoLA+MYikSp1U0WmvELF/4c3x5kH8Vi31TKyZ4yk= github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU=
github.com/wailsapp/go-webview2 v1.0.18/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
github.com/wailsapp/wails/v3 v3.0.0-alpha.8.3 h1:9aCL0IXD60A5iscQ/ps6f3ti3IlaoG6LQe0RZ9JkueU= github.com/wailsapp/wails/v3 v3.0.0-alpha.9 h1:b8CfRrhPno8Fra0xFp4Ifyj+ogmXBc35rsQWvcrHtsI=
github.com/wailsapp/wails/v3 v3.0.0-alpha.8.3/go.mod h1:9Ca1goy5oqxmy8Oetb8Tchkezcx4tK03DK+SqYByu5Y= github.com/wailsapp/wails/v3 v3.0.0-alpha.9/go.mod h1:dSv6s722nSWaUyUiapAM1DHc5HKggNGY1a79shO85/g=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY= github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
@@ -226,6 +227,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -238,8 +241,9 @@ gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g= gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g= gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY= gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY=

View File

@@ -1,44 +1,45 @@
package dialogs package dialogs
import ( import (
"fmt"
"github.com/wailsapp/wails/v3/pkg/application" "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) { func InfoDialog(title string, message string) {
checkInit() application.InfoDialog().SetTitle(title).SetMessage(message).Show()
application.InfoDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
} }
func WarningDialog(title string, message string) { func WarningDialog(title string, message string) {
checkInit() application.WarningDialog().SetTitle(title).SetMessage(message).Show()
application.WarningDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
} }
func ErrorDialog(title string, message string) { func ErrorDialog(title string, message string) {
checkInit() application.ErrorDialog().SetTitle(title).SetMessage(message).Show()
application.ErrorDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
} }
func SaveFileDialog(title string, filename string) (string, error) { func SaveFileDialog(title string, filename string) (string, error) {
checkInit() selection, err := application.SaveFileDialog().SetFilename(filename).PromptForSingleSelection()
selection, err := application.SaveFileDialog().AttachToWindow(currentWindow).SetFilename(filename).PromptForSingleSelection()
if err != nil { if err != nil {
return "", err return "", err
} }
return selection, nil 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"` Id uint `gorm:"primaryKey" ui:"hidden"`
Text string `ui:"label:Текст"` Text string `ui:"label:Текст"`
Deadline int64 `ui:"label:Дедлайн;datatype:datetime;"` 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;"` AuthorId uint `ui:"hidden" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Author Author `ui:"label:Автор; field:Name;"` Author Author `ui:"label:Автор; field:Name;"`
PostTypeId uint `ui:"hidden"` PostTypeId uint `ui:"hidden"`

View File

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

View File

@@ -3,8 +3,13 @@ package services
import ( import (
"app/internal/dal" "app/internal/dal"
"app/internal/database" "app/internal/database"
"app/internal/dialogs"
"app/internal/extras/excel"
"app/internal/models" "app/internal/models"
"errors" "errors"
"os/signal"
"strconv"
"syscall"
"gorm.io/gen/field" "gorm.io/gen/field"
"gorm.io/gorm" "gorm.io/gorm"
@@ -59,3 +64,30 @@ func (service *PostTypeService) Count() (int64, error) {
amount, err := dal.PostType.Count() amount, err := dal.PostType.Count()
return amount, err 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
}

View File

@@ -1,7 +1,6 @@
package main package main
import ( import (
"app/internal/dialogs"
"app/internal/services" "app/internal/services"
"embed" "embed"
"github.com/wailsapp/wails/v3/pkg/application" "github.com/wailsapp/wails/v3/pkg/application"
@@ -14,7 +13,7 @@ var assets embed.FS
func main() { func main() {
app := application.New(application.Options{ app := application.New(application.Options{
Name: "nto_starterkit", Name: "nto_starterkit",
Description: "A demo of using raw HTML & CSS", Description: "NTO toolkit template",
Services: append([]application.Service{services.MigratorService}, services.ExportedServices...), Services: append([]application.Service{services.MigratorService}, services.ExportedServices...),
Assets: application.AssetOptions{ Assets: application.AssetOptions{
Handler: application.AssetFileServerFS(assets), Handler: application.AssetFileServerFS(assets),
@@ -29,16 +28,15 @@ func main() {
// 'Mac' options tailor the window when running on macOS. // 'Mac' options tailor the window when running on macOS.
// 'BackgroundColour' is the background colour of the window. // 'BackgroundColour' is the background colour of the window.
// 'URL' is the URL that will be loaded into the webview. // 'URL' is the URL that will be loaded into the webview.
window := app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
Title: "Завод \"Белочка\"", Title: "Завод \"Белочка\"",
Mac: application.MacWindow{ Mac: application.MacWindow{
InvisibleTitleBarHeight: 50, InvisibleTitleBarHeight: 50,
Backdrop: application.MacBackdropTranslucent, Backdrop: application.MacBackdropTranslucent,
TitleBar: application.MacTitleBarHiddenInset, TitleBar: application.MacTitleBarHiddenInset,
}, },
URL: "/", URL: "/",
}) })
dialogs.Init(window)
err := app.Run() err := app.Run()