initial commit
10
.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/build
|
||||||
|
/.svelte-kit
|
||||||
|
/package
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
vite.config.js.timestamp-*
|
||||||
|
vite.config.ts.timestamp-*
|
||||||
19
LICENSE
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2025 gogacoder <me@gogacoder.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
|
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
3384
package-lock.json
generated
Normal file
38
package.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "nikita",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite dev",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
|
"tauri": "tauri"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@electric-sql/pglite": "^0.2.13",
|
||||||
|
"@nikonell/splash": "latest",
|
||||||
|
"@tauri-apps/api": "^2",
|
||||||
|
"@tauri-apps/plugin-dialog": "^2.2.0",
|
||||||
|
"@tauri-apps/plugin-fs": "^2.2.0",
|
||||||
|
"@tauri-apps/plugin-shell": "^2",
|
||||||
|
"drizzle-orm": "^0.36.3",
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@sveltejs/adapter-static": "^3.0.5",
|
||||||
|
"@sveltejs/kit": "^2.7.0",
|
||||||
|
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
||||||
|
"@tauri-apps/cli": "^2",
|
||||||
|
"drizzle-kit": "^0.28.1",
|
||||||
|
"sass": "^1.81.0",
|
||||||
|
"svelte": "^5.0.0",
|
||||||
|
"svelte-check": "^4.0.0",
|
||||||
|
"tslib": "^2.8.0",
|
||||||
|
"typescript": "^5.5.0",
|
||||||
|
"vite": "^5.4.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src-tauri/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
/target/
|
||||||
|
|
||||||
|
# Generated by Tauri
|
||||||
|
# will have schema files for capabilities auto-completion
|
||||||
|
/gen/schemas
|
||||||
26
src-tauri/Cargo.toml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
[package]
|
||||||
|
name = "nikita"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "App for CJSC Lesozavod No. 10 Belka business process management."
|
||||||
|
authors = ["ber⁴"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
# The `_lib` suffix may seem redundant but it is necessary
|
||||||
|
# to make the lib name unique and wouldn't conflict with the bin name.
|
||||||
|
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
|
||||||
|
name = "nikita_lib"
|
||||||
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tauri-build = { version = "2", features = [] }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tauri = { version = "2", features = [] }
|
||||||
|
tauri-plugin-shell = "2"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
tauri-plugin-fs = "2"
|
||||||
|
tauri-plugin-dialog = "2"
|
||||||
3
src-tauri/build.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
tauri_build::build()
|
||||||
|
}
|
||||||
17
src-tauri/capabilities/default.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
|
"identifier": "default",
|
||||||
|
"description": "Capability for the main window",
|
||||||
|
"windows": [
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
"core:default",
|
||||||
|
"shell:allow-open",
|
||||||
|
"fs:default",
|
||||||
|
"fs:read-all",
|
||||||
|
"fs:read-files",
|
||||||
|
"fs:default",
|
||||||
|
"dialog:default"
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
src-tauri/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src-tauri/icons/128x128@2x.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
src-tauri/icons/32x32.png
Normal file
|
After Width: | Height: | Size: 974 B |
BIN
src-tauri/icons/Square107x107Logo.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src-tauri/icons/Square142x142Logo.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src-tauri/icons/Square150x150Logo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src-tauri/icons/Square284x284Logo.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
src-tauri/icons/Square30x30Logo.png
Normal file
|
After Width: | Height: | Size: 903 B |
BIN
src-tauri/icons/Square310x310Logo.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
src-tauri/icons/Square44x44Logo.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src-tauri/icons/Square71x71Logo.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src-tauri/icons/Square89x89Logo.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src-tauri/icons/StoreLogo.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src-tauri/icons/icon.icns
Normal file
BIN
src-tauri/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
src-tauri/icons/icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
16
src-tauri/src/lib.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||||
|
#[tauri::command]
|
||||||
|
fn greet(name: &str) -> String {
|
||||||
|
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
|
pub fn run() {
|
||||||
|
tauri::Builder::default()
|
||||||
|
.plugin(tauri_plugin_dialog::init())
|
||||||
|
.plugin(tauri_plugin_fs::init())
|
||||||
|
.plugin(tauri_plugin_shell::init())
|
||||||
|
.invoke_handler(tauri::generate_handler![greet])
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("error while running tauri application");
|
||||||
|
}
|
||||||
6
src-tauri/src/main.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||||
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
nikita_lib::run()
|
||||||
|
}
|
||||||
35
src-tauri/tauri.conf.json
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
|
"productName": "nikita",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"identifier": "com.nikita.app",
|
||||||
|
"build": {
|
||||||
|
"beforeDevCommand": "bun run dev",
|
||||||
|
"devUrl": "http://localhost:1420",
|
||||||
|
"beforeBuildCommand": "bun run build",
|
||||||
|
"frontendDist": "../build"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"windows": [
|
||||||
|
{
|
||||||
|
"title": "nikita",
|
||||||
|
"width": 800,
|
||||||
|
"height": 600
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"security": {
|
||||||
|
"csp": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bundle": {
|
||||||
|
"active": true,
|
||||||
|
"targets": "all",
|
||||||
|
"icon": [
|
||||||
|
"icons/32x32.png",
|
||||||
|
"icons/128x128.png",
|
||||||
|
"icons/128x128@2x.png",
|
||||||
|
"icons/icon.icns",
|
||||||
|
"icons/icon.ico"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/app.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Tauri + SvelteKit + Typescript App</title>
|
||||||
|
%sveltekit.head%
|
||||||
|
</head>
|
||||||
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
38
src/lib/entities/brigadeType.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { makeEntity } from "@nikonell/splash/entities/factory.js";
|
||||||
|
import { FieldTypes } from "@nikonell/splash/types/entity.js";
|
||||||
|
import { makeField } from "@nikonell/splash/entities/factory.js";
|
||||||
|
|
||||||
|
export interface BrigadeType {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const brigadeTypeFields = {
|
||||||
|
name: makeField({
|
||||||
|
name: "name",
|
||||||
|
title: "Наименование",
|
||||||
|
type: FieldTypes.String,
|
||||||
|
required: true,
|
||||||
|
placeholder: "Введите наименование",
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const brigadeTypeRelations = {};
|
||||||
|
|
||||||
|
export const brigadeType = makeEntity<
|
||||||
|
BrigadeType,
|
||||||
|
typeof brigadeTypeFields,
|
||||||
|
typeof brigadeTypeRelations
|
||||||
|
>({
|
||||||
|
name: "brigade_type",
|
||||||
|
title: "Вид бригады",
|
||||||
|
extras: [],
|
||||||
|
fields: brigadeTypeFields,
|
||||||
|
relations: brigadeTypeRelations,
|
||||||
|
defaultValues: [
|
||||||
|
{ name: "Бригада по распиловке" },
|
||||||
|
{ name: "Бригада по сушке" },
|
||||||
|
{ name: "Бригада по обработке" },
|
||||||
|
{ name: "Бригада пеллетного цеха" },
|
||||||
|
],
|
||||||
|
});
|
||||||
13
src/lib/index.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import type { Section } from "@nikonell/splash/types/section.js";
|
||||||
|
import { brigadeType } from "./entities/brigadeType";
|
||||||
|
|
||||||
|
export const entities = [brigadeType];
|
||||||
|
|
||||||
|
export const sections: Section[] = [
|
||||||
|
{
|
||||||
|
name: "commercial_service",
|
||||||
|
title: "Коммерческая служба",
|
||||||
|
entities: [brigadeType],
|
||||||
|
extras: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
16
src/lib/utils/excel.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { readFile } from "./files"
|
||||||
|
import * as XLSX from 'xlsx';
|
||||||
|
|
||||||
|
export const parseExcelFile = async (path: string): Promise<string[][] | null> => {
|
||||||
|
try {
|
||||||
|
const contents = await readFile(path);
|
||||||
|
const workbook = XLSX.read(contents, { type: "array" });
|
||||||
|
const wsNames = workbook.SheetNames;
|
||||||
|
const sheet = workbook.Sheets[wsNames[0]];
|
||||||
|
const rows = XLSX.utils.sheet_to_json<string[]>(sheet, { header: 1, raw: false, defval: "" });
|
||||||
|
return rows
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/lib/utils/files.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { open } from '@tauri-apps/plugin-dialog';
|
||||||
|
import { readFile as read, readTextFile as readText } from '@tauri-apps/plugin-fs';
|
||||||
|
|
||||||
|
export const requestSingleFile = async () => {
|
||||||
|
return open({
|
||||||
|
multiple: false,
|
||||||
|
directory: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const readFile = async (path: string): Promise<Uint8Array<ArrayBufferLike>> => {
|
||||||
|
return read(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const readTextFile = async (path: string): Promise<string> => {
|
||||||
|
return readText(path);
|
||||||
|
}
|
||||||
37
src/routes/+layout.svelte
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { page } from "$app/stores";
|
||||||
|
import { initDatabase } from "@nikonell/splash/database/client.js";
|
||||||
|
import {
|
||||||
|
SkeletonPageLayout,
|
||||||
|
SkeletonRowPage,
|
||||||
|
} from "@nikonell/splash/components/pages";
|
||||||
|
import { SkeletonTable } from "@nikonell/splash/components/ui";
|
||||||
|
import { entities } from "../lib";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { children }: Props = $props();
|
||||||
|
|
||||||
|
let loaded = $state(false);
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
await initDatabase(entities);
|
||||||
|
loaded = true;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if loaded}
|
||||||
|
{@render children()}
|
||||||
|
{:else}
|
||||||
|
<SkeletonPageLayout>
|
||||||
|
{#if $page.url.pathname === "/"}
|
||||||
|
<SkeletonTable />
|
||||||
|
{:else if ["/edit", "/create"].includes($page.url.pathname)}
|
||||||
|
<SkeletonRowPage />
|
||||||
|
{/if}
|
||||||
|
</SkeletonPageLayout>
|
||||||
|
{/if}
|
||||||
5
src/routes/+layout.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// Tauri doesn't have a Node.js server to do proper SSR
|
||||||
|
// so we will use adapter-static to prerender the app (SSG)
|
||||||
|
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
||||||
|
export const prerender = true;
|
||||||
|
export const ssr = false;
|
||||||
6
src/routes/+page.svelte
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { entities, sections } from "$lib";
|
||||||
|
import { DisplayTablePage } from "@nikonell/splash/components/pages";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DisplayTablePage {entities} {sections} />
|
||||||
6
src/routes/create/+page.svelte
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { entities, sections } from "$lib";
|
||||||
|
import { CreateRowPage } from "@nikonell/splash/components/pages";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CreateRowPage {entities} {sections} />
|
||||||
6
src/routes/edit/+page.svelte
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { entities, sections } from "$lib";
|
||||||
|
import { EditRowPage } from "@nikonell/splash/components/pages";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<EditRowPage {entities} {sections} />
|
||||||
BIN
static/favicon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
static/fonts/gilroy/Gilroy-Black.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-Bold.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-Extrabold.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-Heavy.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-Light.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-Medium.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-Regular.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-Semibold.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-Thin.woff2
Normal file
BIN
static/fonts/gilroy/Gilroy-UltraLight.woff2
Normal file
15
svelte.config.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// Tauri doesn't have a Node.js server to do proper SSR
|
||||||
|
// so we will use adapter-static to prerender the app (SSG)
|
||||||
|
// See: https://v2.tauri.app/start/frontend/sveltekit/ for more info
|
||||||
|
import adapter from "@sveltejs/adapter-static";
|
||||||
|
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
|
||||||
|
|
||||||
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
|
const config = {
|
||||||
|
preprocess: vitePreprocess(),
|
||||||
|
kit: {
|
||||||
|
adapter: adapter(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
19
tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"extends": "./.svelte-kit/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strict": true,
|
||||||
|
"moduleResolution": "bundler"
|
||||||
|
}
|
||||||
|
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
||||||
|
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
|
||||||
|
//
|
||||||
|
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||||
|
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||||
|
}
|
||||||
38
vite.config.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { defineConfig } from "vite";
|
||||||
|
import { sveltekit } from "@sveltejs/kit/vite";
|
||||||
|
|
||||||
|
// @ts-expect-error process is a nodejs global
|
||||||
|
const host = process.env.TAURI_DEV_HOST;
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig(async () => ({
|
||||||
|
plugins: [sveltekit()],
|
||||||
|
optimizeDeps: {
|
||||||
|
exclude: ['@electric-sql/pglite'],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||||
|
//
|
||||||
|
// 1. prevent vite from obscuring rust errors
|
||||||
|
clearScreen: false,
|
||||||
|
// 2. tauri expects a fixed port, fail if that port is not available
|
||||||
|
server: {
|
||||||
|
port: 1420,
|
||||||
|
strictPort: true,
|
||||||
|
host: host || false,
|
||||||
|
hmr: host
|
||||||
|
? {
|
||||||
|
protocol: "ws",
|
||||||
|
host,
|
||||||
|
port: 1421,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
watch: {
|
||||||
|
// 3. tell vite to ignore watching `src-tauri`
|
||||||
|
ignored: ["**/src-tauri/**"],
|
||||||
|
},
|
||||||
|
fs: {
|
||||||
|
allow: ['..']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||