Compare commits
1 Commits
1e0f2b7f4a
...
sync
| Author | SHA1 | Date | |
|---|---|---|---|
| f27b647eb0 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,6 +6,3 @@ nto-cli/
|
|||||||
/**/node_modules/
|
/**/node_modules/
|
||||||
/**/dist/
|
/**/dist/
|
||||||
.xlsx
|
.xlsx
|
||||||
build/appimage
|
|
||||||
build/nfpm
|
|
||||||
build/nsis
|
|
||||||
@@ -50,13 +50,14 @@ wails3 generate bindings -ts
|
|||||||
Для финальной сборки запустите эту команду в директории проекта:
|
Для финальной сборки запустите эту команду в директории проекта:
|
||||||
|
|
||||||
```
|
```
|
||||||
PRODUCTION=true wails3 build
|
go env -w CGO_ENABLED=1
|
||||||
|
wails3 build -clean -upx -v 2 -webview2 embed
|
||||||
```
|
```
|
||||||
|
|
||||||
**Перед релизом не забыть**:
|
**Перед релизом не забыть**:
|
||||||
- убедиться, что дефолтные данные правильные
|
|
||||||
- убедиться, что приложение запускается
|
- поместить все нужные asset'ы в папку assets
|
||||||
- (опционально) поместить все нужные asset'ы в папку assets
|
- изменить версию схемы БД (пока не нужно)
|
||||||
- приложить сопроводительную записку.
|
- приложить сопроводительную записку.
|
||||||
|
|
||||||
## Работа без GitHub
|
## Работа без GitHub
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ tasks:
|
|||||||
cmds:
|
cmds:
|
||||||
- go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}
|
- go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}
|
||||||
vars:
|
vars:
|
||||||
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags "production" -trimpath -ldflags="-w -s"{{else}}-gcflags=all="-l" {{end}}'
|
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -ldflags="-w -s"{{else}}-gcflags=all="-l"{{end}}'
|
||||||
env:
|
env:
|
||||||
GOOS: darwin
|
GOOS: darwin
|
||||||
CGO_ENABLED: 1
|
CGO_ENABLED: 1
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ tasks:
|
|||||||
cmds:
|
cmds:
|
||||||
- go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}
|
- go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}
|
||||||
vars:
|
vars:
|
||||||
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags "production" -trimpath -ldflags="-w -s"{{else}}-gcflags=all="-l" {{end}}'
|
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -ldflags="-w -s"{{else}}-gcflags=all="-l"{{end}}'
|
||||||
env:
|
env:
|
||||||
GOOS: linux
|
GOOS: linux
|
||||||
CGO_ENABLED: 1
|
CGO_ENABLED: 1
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ tasks:
|
|||||||
- cmd: rm -f *.syso
|
- cmd: rm -f *.syso
|
||||||
platforms: [linux, darwin]
|
platforms: [linux, darwin]
|
||||||
vars:
|
vars:
|
||||||
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags "production" -trimpath -ldflags="-w -s -H windowsgui"{{else}}-gcflags=all="-l" {{end}}'
|
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -ldflags="-w -s -H windowsgui"{{else}}-gcflags=all="-l"{{end}}'
|
||||||
env:
|
env:
|
||||||
GOOS: windows
|
GOOS: windows
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 1
|
||||||
GOARCH: '{{.ARCH | default ARCH}}'
|
GOARCH: '{{.ARCH | default ARCH}}'
|
||||||
PRODUCTION: '{{.PRODUCTION | default "false"}}'
|
PRODUCTION: '{{.PRODUCTION | default "false"}}'
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ const load = async () => {
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await load();
|
await load();
|
||||||
|
console.log(await SortedByOrder({"Comments": "DESC"}))
|
||||||
});
|
});
|
||||||
|
|
||||||
const scheme: Scheme<Author> = reactive({
|
const scheme: Scheme<Author> = reactive({
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const pushOrRemove = (option: T) => {
|
|||||||
} else {
|
} else {
|
||||||
selected.value.push(option)
|
selected.value.push(option)
|
||||||
}
|
}
|
||||||
|
//setNullIds()
|
||||||
}
|
}
|
||||||
|
|
||||||
const setNullIds = () => {
|
const setNullIds = () => {
|
||||||
@@ -26,11 +27,12 @@ const setNullIds = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//onMounted(setNullIds)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="">
|
<div class="">
|
||||||
<ul class="max-h-48 h-auto overflow-y-auto background rounded-md p-3 w-full native-border">
|
<ul class="max-h-48 h-auto overflow-y-auto background rounded-md p-3 w-full border-gray-500 border">
|
||||||
<li v-for="option in options" :key="option.Id" class="flex items-center gap-2">
|
<li v-for="option in options" :key="option.Id" class="flex items-center gap-2">
|
||||||
<Checkbox :checked="selected.some(item => item.Id == option.Id)" @click="pushOrRemove(option)" />
|
<Checkbox :checked="selected.some(item => item.Id == option.Id)" @click="pushOrRemove(option)" />
|
||||||
<label :for="option.Id.toString()">{{ structView(option, path) }}</label>
|
<label :for="option.Id.toString()">{{ structView(option, path) }}</label>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Table from "../table/Table.vue";
|
import Table from "../table/Table.vue";
|
||||||
import {onMounted, reactive, watch} from "vue";
|
import { onMounted, reactive } from "vue";
|
||||||
import { getDefaultValues } from "../utils/structs/defaults.util";
|
import { getDefaultValues } from "../utils/structs/defaults.util";
|
||||||
import Service from "./post.service.ts";
|
import Service from "./post.service.ts";
|
||||||
import type { Scheme } from "../types/scheme.type";
|
import type { Scheme } from "../types/scheme.type";
|
||||||
@@ -16,7 +16,7 @@ const posttypeService = new PosttypeService();
|
|||||||
|
|
||||||
import CommentService from "../comment/comment.service.ts";
|
import CommentService from "../comment/comment.service.ts";
|
||||||
import { SortedByOrder } from "../../bindings/app/internal/services/postservice.ts";
|
import { SortedByOrder } from "../../bindings/app/internal/services/postservice.ts";
|
||||||
import {getDefaultSortOptions} from "../utils/structs/default-sort-options.util.ts";
|
import type { Search } from "../types/search.type.ts";
|
||||||
|
|
||||||
const commentService = new CommentService();
|
const commentService = new CommentService();
|
||||||
|
|
||||||
@@ -33,12 +33,13 @@ const load = async () => {
|
|||||||
(scheme as any).Comments.type!.nested!.values =
|
(scheme as any).Comments.type!.nested!.values =
|
||||||
await commentService.readAll();
|
await commentService.readAll();
|
||||||
|
|
||||||
items.value = await service.sort(sortOptions.value) ;
|
items.value = await service.readAll();
|
||||||
return items.value;
|
return items.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await load();
|
await load();
|
||||||
|
console.log(await SortedByOrder({ "Author": "DESC", "Text": "ASC" }));
|
||||||
});
|
});
|
||||||
|
|
||||||
const scheme: Scheme<Post> = reactive({
|
const scheme: Scheme<Post> = reactive({
|
||||||
@@ -116,6 +117,9 @@ const scheme: Scheme<Post> = reactive({
|
|||||||
values: [],
|
values: [],
|
||||||
field: ["Text"],
|
field: ["Text"],
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
customWindow: {
|
||||||
|
create: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -130,15 +134,15 @@ const validate: Validate<Post> = (entity) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const search = async (input: string) => {
|
const search: Search<Post> = (input) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortOptions = ref(getDefaultSortOptions(scheme))
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Table :scheme :service :get-defaults :load :items :validate @on-search="search" v-model:sort-options="sortOptions"></Table>
|
<Table :scheme :service :get-defaults :load :items :validate @on-search="search">
|
||||||
|
<template #CommentsCreate="{ data }">
|
||||||
|
<p>{{ data }}</p>
|
||||||
|
</template>
|
||||||
|
</Table>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ import {
|
|||||||
Delete,
|
Delete,
|
||||||
GetById,
|
GetById,
|
||||||
Update,
|
Update,
|
||||||
Count, SortedByOrder,
|
Count,
|
||||||
} from "../../bindings/app/internal/services/postservice.ts";
|
} from "../../bindings/app/internal/services/postservice.ts";
|
||||||
import type { Post } from "../../bindings/app/internal/services";
|
import type { Post } from "../../bindings/app/internal/services";
|
||||||
import type { IService } from "../types/service.type.ts";
|
import type { IService } from "../types/service.type.ts";
|
||||||
import type {SortOptions} from "../types/sort-options.type.ts";
|
|
||||||
|
|
||||||
export default class PostService implements IService<Post> {
|
export default class PostService implements IService<Post> {
|
||||||
async read(id: number) {
|
async read(id: number) {
|
||||||
@@ -34,8 +33,4 @@ export default class PostService implements IService<Post> {
|
|||||||
async count() {
|
async count() {
|
||||||
return await Count();
|
return await Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
async sort(options: SortOptions<Post>) {
|
|
||||||
return await SortedByOrder(options) as Post[]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,25 +5,10 @@
|
|||||||
|
|
||||||
html, body, .background {
|
html, body, .background {
|
||||||
background: white;
|
background: white;
|
||||||
color: rgb(51, 65, 85);
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondary-background {
|
|
||||||
background: var(--p-content-background)
|
|
||||||
}
|
|
||||||
|
|
||||||
.native-border {
|
|
||||||
border: 1px solid var(--p-select-border-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
html, body, .background {
|
html, body, .background {
|
||||||
background: #121212;
|
background: #121212;
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.native-border {
|
|
||||||
border: 1px solid rgb(100, 100, 109);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ async function handleSave() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Dialog v-model:visible="showCreate" class="w-[500px]">
|
<Dialog v-model:visible="showCreate">
|
||||||
<template #header>
|
<template #header>
|
||||||
<h1>{{ props.updateMode ? 'Изменить' : 'Создать' }} {{ props.name?.toLowerCase() }}</h1>
|
<h1>{{ props.updateMode ? 'Изменить' : 'Создать' }} {{ props.name?.toLowerCase() }}</h1>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
<script setup lang="ts" generic="T extends IEntity">
|
|
||||||
import type {IEntity} from "../types/entity.type.ts";
|
|
||||||
import type {SortOptions} from "../types/sort-options.type.ts";
|
|
||||||
import type {Scheme} from "../types/scheme.type.ts";
|
|
||||||
import {Select} from 'primevue'
|
|
||||||
import {watch} from "vue";
|
|
||||||
|
|
||||||
|
|
||||||
const options = defineModel<SortOptions<T>>()
|
|
||||||
const optionsKeys = Object.keys(options.value as T) as (keyof T)[]
|
|
||||||
|
|
||||||
defineProps<{
|
|
||||||
scheme: Scheme<T>
|
|
||||||
load: () => Promise<T[]>
|
|
||||||
}>()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<ul class="flex flex-col gap-2 native-border secondary-background p-3 rounded-md">
|
|
||||||
<li v-for="optionKey in optionsKeys" class="flex items-center justify-between w-full">
|
|
||||||
<h1>{{ scheme[optionKey].russian }}</h1>
|
|
||||||
<Select size="small" class="w-24" :options="['ASC', 'DESC']" v-model="options![optionKey]" @value-change="load"></Select>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
<script setup lang="ts" generic="T extends IEntity">
|
<script setup lang="ts" generic="T extends IEntity">
|
||||||
import {onMounted, ref, watch, type UnwrapRef} from "vue";
|
import { onMounted, ref, watch, type UnwrapRef } from "vue";
|
||||||
import type {TableProps} from "../types/table-props.type";
|
import type { TableProps } from "../types/table-props.type";
|
||||||
import {DataTable, Column, Button, InputText} from "primevue";
|
import { DataTable, Column, Button, InputText } from "primevue";
|
||||||
import {manyStructsView} from "../utils/structs/structs-view.util";
|
import { manyStructsView } from "../utils/structs/structs-view.util";
|
||||||
import type {TableEmits} from "../types/table-emits.type";
|
import type { TableEmits } from "../types/table-emits.type";
|
||||||
import FloatingButton from "../components/buttons/FloatingButton.vue";
|
import FloatingButton from "../components/buttons/FloatingButton.vue";
|
||||||
import type {IEntity} from "../types/entity.type";
|
import type { IEntity } from "../types/entity.type";
|
||||||
import DialogWindow from "./DialogWindow.vue";
|
import DialogWindow from "./DialogWindow.vue";
|
||||||
import {viewDate} from "../utils/date/view.util";
|
import { viewDate } from "../utils/date/view.util";
|
||||||
import SortingOptions from "./SortingOptions.vue";
|
|
||||||
import type {SortOptions} from "../types/sort-options.type.ts";
|
|
||||||
|
|
||||||
const props = defineProps<TableProps<T>>();
|
const props = defineProps<TableProps<T>>();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
props.load();
|
||||||
|
});
|
||||||
|
|
||||||
type Key = keyof T;
|
type Key = keyof T;
|
||||||
const keys = Object.keys(props.scheme) as Key[];
|
const keys = Object.keys(props.scheme) as Key[];
|
||||||
const emits = defineEmits<TableEmits>();
|
const emits = defineEmits<TableEmits>();
|
||||||
@@ -24,148 +26,176 @@ const showUpdate = ref(false);
|
|||||||
const updateItem = ref<null | T>(null);
|
const updateItem = ref<null | T>(null);
|
||||||
|
|
||||||
watch(showUpdate, (value) => {
|
watch(showUpdate, (value) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
updateItem.value = null;
|
updateItem.value = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(updateItem, (value) => {
|
watch(updateItem, (value) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
showUpdate.value = true;
|
showUpdate.value = true;
|
||||||
} else {
|
} else {
|
||||||
showUpdate.value = false;
|
showUpdate.value = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(showCreate, (value) => {
|
watch(showCreate, (value) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
createItem.value = props.getDefaults();
|
createItem.value = props.getDefaults();
|
||||||
} else {
|
} else {
|
||||||
createItem.value = null;
|
createItem.value = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(createItem, (value) => {
|
watch(createItem, (value) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
showCreate.value = true;
|
showCreate.value = true;
|
||||||
} else {
|
} else {
|
||||||
showCreate.value = false;
|
showCreate.value = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleFloatingButtonClick = () => {
|
const handleFloatingButtonClick = () => {
|
||||||
emits('onCreateOpen')
|
emits("onCreateOpen");
|
||||||
emits('onOpen')
|
emits("onOpen");
|
||||||
showCreate.value = true;
|
showCreate.value = true;
|
||||||
};
|
};
|
||||||
const slots = defineSlots();
|
const slots = defineSlots();
|
||||||
|
|
||||||
const createSlotName = (key: any) => key + "Create";
|
const createSlotName = (key: any) => key + "Create";
|
||||||
const updateSlotName = (key: any) => key + "Update";
|
const updateSlotName = (key: any) => key + "Update";
|
||||||
|
|
||||||
watch(() => props.items, () => {
|
watch(
|
||||||
if (props.colorize) {
|
() => props.items,
|
||||||
const trs = document.querySelectorAll("tr");
|
() => {
|
||||||
props.items.forEach(item => {
|
if (props.colorize) {
|
||||||
const tr = trs[item.Id];
|
const trs = document.querySelectorAll("tr");
|
||||||
if (tr) {
|
props.items.forEach((item) => {
|
||||||
tr.style.backgroundColor = props.colorize!(item);
|
const tr = trs[item.Id];
|
||||||
}
|
if (tr) {
|
||||||
})
|
tr.style.backgroundColor = props.colorize!(item);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
}
|
||||||
const input = ref('')
|
},
|
||||||
const sortOptions = defineModel<SortOptions<T>>('sort-options');
|
);
|
||||||
const showSortOptions = ref(false)
|
|
||||||
|
|
||||||
|
const input = defineModel<string>("search", { default: "" });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="m-2 flex flex-col items-center gap-2">
|
<div class="flex h-10 justify-center m-4 gap-2">
|
||||||
<div class="flex flex-col gap-2 relative">
|
<InputText v-model="input" placeholder="Поиск" class="h-full w-64" />
|
||||||
<div class="flex items-center justify-center gap-2 h-10">
|
<Button class="h-full aspect-square" severity="secondary">
|
||||||
<Button severity="secondary" class="h-full aspect-square" @click="showSortOptions = !showSortOptions">
|
<span class="pi pi-search"></span>
|
||||||
<span class="pi pi-sort"></span>
|
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<InputText class="h-full w-64" v-model="input"/>
|
|
||||||
<Button severity="secondary" class="h-full aspect-square" @click="emits('onSearch', input)">
|
|
||||||
<span class="pi pi-search"></span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<SortingOptions v-model="sortOptions as SortOptions<T>" :scheme v-if="showSortOptions"
|
|
||||||
class="absolute z-10 w-full top-full translate-y-2" :load="props.load"></SortingOptions>
|
|
||||||
</div>
|
</div>
|
||||||
|
<DialogWindow
|
||||||
</div>
|
:name
|
||||||
<DialogWindow :name :load :items :validate :scheme :service :get-defaults v-model:item="<T>createItem"
|
:load
|
||||||
v-model:show="showCreate" @on-save="data => emits('onSave', data)"
|
:items
|
||||||
@on-save-create="data => emits('onSaveCreate', data)">
|
:validate
|
||||||
<template v-for="key in keys" #[key]="{ data }">
|
:scheme
|
||||||
<slot :name="<string>key" :data="data"></slot>
|
:service
|
||||||
</template>
|
:get-defaults
|
||||||
<template v-for="key in keys" #[createSlotName(key)]="{ data }">
|
v-model:item="<T>createItem"
|
||||||
<slot :name="createSlotName(key)" :data="data"></slot>
|
v-model:show="showCreate"
|
||||||
</template>
|
@on-save="(data) => emits('onSave', data)"
|
||||||
</DialogWindow>
|
@on-save-create="(data) => emits('onSaveCreate', data)"
|
||||||
<DialogWindow :name :load :items :validate :scheme update-mode :service :get-defaults v-model:item="<T>updateItem"
|
>
|
||||||
v-model:show="showUpdate" @on-save="data => emits('onSave', data)"
|
<template v-for="key in keys" #[key]="{ data }">
|
||||||
@on-save-update="data => emits('onSaveUpdate', data)">
|
<slot :name="<string>key" :data></slot>
|
||||||
<template v-for="key in keys" #[key]="{ data }">
|
|
||||||
<slot :name="<string>key" :data="data"></slot>
|
|
||||||
</template>
|
|
||||||
<template v-for="key in keys" #[updateSlotName(key)]="{ data }">
|
|
||||||
<slot :name="updateSlotName(key)" :data="data"></slot>
|
|
||||||
</template>
|
|
||||||
</DialogWindow>
|
|
||||||
<div>
|
|
||||||
<DataTable :value="<[]>items" paginator :rows="10">
|
|
||||||
<template #header v-if="props.name">
|
|
||||||
<p>{{ props.name }}</p>
|
|
||||||
</template>
|
|
||||||
<template v-for="key in keys">
|
|
||||||
<Column :header="props.scheme[key]?.russian" v-if="!props.scheme[key].hidden">
|
|
||||||
<template #body="{ data }">
|
|
||||||
<p class="truncate max-w-56" v-tooltip="viewDate(manyStructsView(
|
|
||||||
data[key],
|
|
||||||
props.scheme[key]?.type?.nested?.field,
|
|
||||||
), scheme[key]?.type?.primitive)">
|
|
||||||
{{
|
|
||||||
viewDate(manyStructsView(
|
|
||||||
data[key],
|
|
||||||
props.scheme[key]?.type?.nested?.field,
|
|
||||||
), scheme[key]?.type?.primitive)
|
|
||||||
}}
|
|
||||||
</p>
|
|
||||||
</template>
|
|
||||||
</Column>
|
|
||||||
</template>
|
|
||||||
<Column header="Действия">
|
|
||||||
<template #body="{ data }">
|
|
||||||
<div class="flex gap-2">
|
|
||||||
<Button severity="secondary" icon="pi pi-pencil" @click="async () => {
|
|
||||||
await emits('onUpdateOpen')
|
|
||||||
await emits('onOpen')
|
|
||||||
updateItem = data
|
|
||||||
}"></Button>
|
|
||||||
<Button severity="danger" icon="pi pi-trash" @click="async () => {
|
|
||||||
await emits('onDelete', data)
|
|
||||||
await props.service.delete(data.Id)
|
|
||||||
await load()
|
|
||||||
}"></Button>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</Column>
|
<template v-for="key in keys" #[createSlotName(key)]="{ data }">
|
||||||
<template #paginatorstart>
|
<slot :name="createSlotName(key)" :data></slot>
|
||||||
<Button severity="secondary" @click="props.load">
|
</template>
|
||||||
<span class="pi pi-refresh"></span>
|
</DialogWindow>
|
||||||
</Button>
|
<DialogWindow
|
||||||
</template>
|
:name
|
||||||
<template #paginatorend>
|
:load
|
||||||
<span></span>
|
:items
|
||||||
</template>
|
:validate
|
||||||
</DataTable>
|
:scheme
|
||||||
<FloatingButton @click="handleFloatingButtonClick"/>
|
update-mode
|
||||||
</div>
|
:service
|
||||||
|
:get-defaults
|
||||||
|
v-model:item="<T>updateItem"
|
||||||
|
v-model:show="showUpdate"
|
||||||
|
@on-save="(data) => emits('onSave', data)"
|
||||||
|
@on-save-update="(data) => emits('onSaveUpdate', data)"
|
||||||
|
>
|
||||||
|
<template v-for="key in keys" #[key]="{ data }">
|
||||||
|
<slot :name="<string>key" :data></slot>
|
||||||
|
</template>
|
||||||
|
<template v-for="key in keys" #[updateSlotName(key)]="{ data }">
|
||||||
|
<slot :name="updateSlotName(key)" :data></slot>
|
||||||
|
</template>
|
||||||
|
</DialogWindow>
|
||||||
|
<div>
|
||||||
|
<DataTable :value="<[]>items" paginator :rows="10">
|
||||||
|
<template #header v-if="props.name">
|
||||||
|
<p>{{ props.name }}</p>
|
||||||
|
</template>
|
||||||
|
<template v-for="key in keys">
|
||||||
|
<Column
|
||||||
|
:header="props.scheme[key]?.russian"
|
||||||
|
v-if="!props.scheme[key].hidden"
|
||||||
|
>
|
||||||
|
<template #body="{ data }">
|
||||||
|
<p
|
||||||
|
class="truncate max-w-56"
|
||||||
|
v-tooltip="
|
||||||
|
viewDate(
|
||||||
|
manyStructsView(
|
||||||
|
data[key],
|
||||||
|
props.scheme[key]?.type?.nested?.field,
|
||||||
|
),
|
||||||
|
scheme[key]?.type?.primitive,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
viewDate(
|
||||||
|
manyStructsView(
|
||||||
|
data[key],
|
||||||
|
props.scheme[key]?.type?.nested?.field,
|
||||||
|
),
|
||||||
|
scheme[key]?.type?.primitive,
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
</template>
|
||||||
|
<Column header="Действия">
|
||||||
|
<template #body="{ data }">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<Button
|
||||||
|
severity="secondary"
|
||||||
|
icon="pi pi-pencil"
|
||||||
|
@click="
|
||||||
|
async () => {
|
||||||
|
await emits('onUpdateOpen');
|
||||||
|
await emits('onOpen');
|
||||||
|
updateItem = data;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></Button>
|
||||||
|
<Button
|
||||||
|
severity="danger"
|
||||||
|
icon="pi pi-trash"
|
||||||
|
@click="
|
||||||
|
async () => {
|
||||||
|
await emits('onDelete', data);
|
||||||
|
await props.service.delete(data.Id);
|
||||||
|
await load();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
</DataTable>
|
||||||
|
<FloatingButton @click="handleFloatingButtonClick" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
3
frontend/src/types/search.type.ts
Normal file
3
frontend/src/types/search.type.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import type { IEntity } from "./entity.type";
|
||||||
|
|
||||||
|
export type Search<T extends IEntity> = (input: string) => T[]
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import type { IEntity } from "./entity.type";
|
|
||||||
import type { Sorting } from "./sorting.type";
|
|
||||||
|
|
||||||
export type SortOptions<T extends IEntity> = {
|
|
||||||
[key in keyof Partial<T>]: Sorting
|
|
||||||
}
|
|
||||||
7
frontend/src/types/sort.type.ts
Normal file
7
frontend/src/types/sort.type.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import type { IEntity } from "./entity.type";
|
||||||
|
|
||||||
|
export type SortOptions<T extends IEntity> = {
|
||||||
|
[key in keyof T]: "ASC" | "DESC"
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Sort<T extends IEntity> = (options: SortOptions<T>) => T[]
|
||||||
@@ -1 +0,0 @@
|
|||||||
export type Sorting = "DESC" | "ASC"
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import type { IEntity } from "./entity.type";
|
import type { IEntity } from "./entity.type";
|
||||||
import type { Scheme } from "./scheme.type";
|
import type { Scheme } from "./scheme.type";
|
||||||
|
import type { Search } from "./search.type";
|
||||||
import type { IService } from "./service.type";
|
import type { IService } from "./service.type";
|
||||||
|
import type { Sort } from "./sort.type";
|
||||||
import type { Validate } from "./validate.type";
|
import type { Validate } from "./validate.type";
|
||||||
|
|
||||||
export interface TableProps<T extends IEntity> {
|
export interface TableProps<T extends IEntity> {
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
import type { IEntity } from "../../types/entity.type";
|
|
||||||
import type { Scheme } from "../../types/scheme.type";
|
|
||||||
import type { SortOptions } from "../../types/sort-options.type";
|
|
||||||
|
|
||||||
export const getDefaultSortOptions = <T extends IEntity>(scheme: Scheme<T>): SortOptions<T> => {
|
|
||||||
const keys = Object.keys(scheme) as (keyof T)[]
|
|
||||||
const result: Partial<SortOptions<T>> = {}
|
|
||||||
|
|
||||||
keys.forEach(key => {
|
|
||||||
if (!scheme[key].hidden && key !== 'entityId' && !scheme[key].many) {
|
|
||||||
result[key] = 'ASC'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return result as SortOptions<T>
|
|
||||||
}
|
|
||||||
6
frontend/src/utils/structs/default-sort.util.ts
Normal file
6
frontend/src/utils/structs/default-sort.util.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import type { IEntity } from "../../types/entity.type";
|
||||||
|
import type { Scheme } from "../../types/scheme.type";
|
||||||
|
|
||||||
|
export const defaultSort = <T extends IEntity>(scheme: Scheme<T>) => {
|
||||||
|
|
||||||
|
}
|
||||||
10
go.mod
10
go.mod
@@ -6,12 +6,10 @@ toolchain go1.24.1
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/kuzgoga/fogg v0.1.2
|
github.com/kuzgoga/fogg v0.1.2
|
||||||
github.com/ncruces/go-sqlite3 v0.24.1
|
|
||||||
github.com/ncruces/go-sqlite3/gormlite v0.24.0
|
|
||||||
github.com/wailsapp/wails/v3 v3.0.0-alpha.9
|
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
|
||||||
golang.org/x/text v0.23.0
|
golang.org/x/text v0.23.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
|
||||||
@@ -48,7 +46,6 @@ require (
|
|||||||
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.22 // 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/ncruces/julianday v1.0.0 // 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
|
||||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||||
@@ -57,18 +54,17 @@ 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/tetratelabs/wazero v1.9.0 // indirect
|
|
||||||
github.com/wailsapp/go-webview2 v1.0.19 // 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
|
||||||
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
|
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
golang.org/x/crypto v0.30.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||||
golang.org/x/mod v0.22.0 // indirect
|
golang.org/x/mod v0.22.0 // indirect
|
||||||
golang.org/x/net v0.32.0 // indirect
|
golang.org/x/net v0.32.0 // indirect
|
||||||
golang.org/x/sync v0.12.0 // indirect
|
golang.org/x/sync v0.12.0 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
golang.org/x/sys v0.28.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/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
|||||||
23
go.sum
23
go.sum
@@ -105,12 +105,6 @@ github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP
|
|||||||
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=
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||||
github.com/ncruces/go-sqlite3 v0.24.1 h1:qHlIz+dlH3Y0wCUErFZXon5hCvw1Kc9eEkZVYYi8p14=
|
|
||||||
github.com/ncruces/go-sqlite3 v0.24.1/go.mod h1:n6Z7036yFilJx04yV0mi5JWaF66rUmXn1It9Ux8dx68=
|
|
||||||
github.com/ncruces/go-sqlite3/gormlite v0.24.0 h1:81sHeq3CCdhjoqAB650n5wEdRlLO9VBvosArskcN3+c=
|
|
||||||
github.com/ncruces/go-sqlite3/gormlite v0.24.0/go.mod h1:vXfVWdBfg7qOgqQqHpzUWl9LLswD0h+8mK4oouaV2oc=
|
|
||||||
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
|
|
||||||
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
|
||||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||||
@@ -143,8 +137,6 @@ 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/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
|
|
||||||
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
|
|
||||||
github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU=
|
github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU=
|
||||||
github.com/wailsapp/go-webview2 v1.0.19/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=
|
||||||
@@ -165,8 +157,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
||||||
@@ -207,15 +199,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
@@ -251,8 +243,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=
|
||||||
|
|||||||
@@ -2,17 +2,12 @@ package database
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"app/internal/dal"
|
"app/internal/dal"
|
||||||
"context"
|
|
||||||
"github.com/ncruces/go-sqlite3/driver"
|
|
||||||
"log"
|
"log"
|
||||||
"log/slog"
|
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/ncruces/go-sqlite3/embed"
|
"gorm.io/driver/sqlite"
|
||||||
"github.com/ncruces/go-sqlite3/ext/unicode"
|
|
||||||
"github.com/ncruces/go-sqlite3/gormlite"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
)
|
)
|
||||||
@@ -36,14 +31,13 @@ func initialize() error {
|
|||||||
Colorful: true, // Disable color
|
Colorful: true, // Disable color
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
db, err = gorm.Open(gormlite.Open("file:"+Path+"?_fk=1"), &gorm.Config{
|
db, err = gorm.Open(sqlite.Open("file:"+Path+"?_fk=1"), &gorm.Config{
|
||||||
Logger: newLogger,
|
Logger: newLogger,
|
||||||
FullSaveAssociations: false,
|
FullSaveAssociations: false,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
RegisterUnicodeExtension(db)
|
|
||||||
if res := db.Exec(`PRAGMA foreign_keys = ON`); res.Error != nil {
|
if res := db.Exec(`PRAGMA foreign_keys = ON`); res.Error != nil {
|
||||||
return res.Error
|
return res.Error
|
||||||
}
|
}
|
||||||
@@ -91,49 +85,3 @@ func GetInstance() *gorm.DB {
|
|||||||
})
|
})
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterUnicodeExtension(db *gorm.DB) {
|
|
||||||
sqlDB, err := db.DB()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
conn, err := sqlDB.Conn(ctx)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
err = conn.Raw(func(driverConn any) error {
|
|
||||||
c := driverConn.(driver.Conn)
|
|
||||||
sqliteConn := c.Raw()
|
|
||||||
|
|
||||||
if err := unicode.Register(sqliteConn); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sqliteConn.Exec(`SELECT icu_load_collation('ru-RU', 'russian')`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sqliteConn.Exec(`SELECT icu_load_collation('en-US', 'english')`); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
stmt, _, err := sqliteConn.Prepare(`SELECT 'ы' LIKE 'Ы'`)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer stmt.Close()
|
|
||||||
|
|
||||||
if stmt.Step() {
|
|
||||||
slog.Info("ICU test result", "value", stmt.ColumnBool(0))
|
|
||||||
}
|
|
||||||
return stmt.Err()
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
18
package-lock.json
generated
Normal file
18
package-lock.json
generated
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "boilerplate",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"@wailsio/runtime": "3.0.0-alpha.66"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@wailsio/runtime": {
|
||||||
|
"version": "3.0.0-alpha.66",
|
||||||
|
"resolved": "https://registry.npmjs.org/@wailsio/runtime/-/runtime-3.0.0-alpha.66.tgz",
|
||||||
|
"integrity": "sha512-ENLu8rn1griL1gFHJqkq1i+BVxrrA0JPJHYneUJYuf/s54kjuQViW0RKDEe/WTDo56ABpfykrd/T8OYpPUyXUw==",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
package.json
Normal file
5
package.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@wailsio/runtime": "3.0.0-alpha.66"
|
||||||
|
}
|
||||||
|
}
|
||||||
22
pnpm-lock.yaml
generated
Normal file
22
pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
lockfileVersion: '9.0'
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
importers:
|
||||||
|
|
||||||
|
.:
|
||||||
|
dependencies:
|
||||||
|
'@wailsio/runtime':
|
||||||
|
specifier: 3.0.0-alpha.66
|
||||||
|
version: 3.0.0-alpha.66
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
'@wailsio/runtime@3.0.0-alpha.66':
|
||||||
|
resolution: {integrity: sha512-ENLu8rn1griL1gFHJqkq1i+BVxrrA0JPJHYneUJYuf/s54kjuQViW0RKDEe/WTDo56ABpfykrd/T8OYpPUyXUw==}
|
||||||
|
|
||||||
|
snapshots:
|
||||||
|
|
||||||
|
'@wailsio/runtime@3.0.0-alpha.66': {}
|
||||||
Reference in New Issue
Block a user