diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..dc0bb0f --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v22.12.0 diff --git a/package-lock.json b/package-lock.json index 2eab453..c5655b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ }, "devDependencies": { "@tauri-apps/cli": "2.3.1", + "@types/node": "22.12.0", "@vitejs/plugin-vue": "5.2.1", "pug": "3.0.3", "sass": "1.85.1", @@ -1394,6 +1395,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.12.0.tgz", + "integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.20.0" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz", @@ -2727,6 +2738,13 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true, + "license": "MIT" + }, "node_modules/uuid": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", diff --git a/package.json b/package.json index befec82..6334a40 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ }, "devDependencies": { "@tauri-apps/cli": "2.3.1", + "@types/node": "22.12.0", "@vitejs/plugin-vue": "5.2.1", "pug": "3.0.3", "sass": "1.85.1", diff --git a/src/router.ts b/src/router.ts index a2359a5..fd0434b 100644 --- a/src/router.ts +++ b/src/router.ts @@ -3,8 +3,8 @@ import { createRouter, } from 'vue-router' -import Editor from './views/Editor.vue' -import Home from './views/Home.vue' +import Editor from 'src/views/Editor/Editor.vue' +import Home from 'src/views/Home/Home.vue' export const routes = [ { path: '/', component: Home }, diff --git a/src/store.ts b/src/store.ts index 19056a9..f7f90f1 100644 --- a/src/store.ts +++ b/src/store.ts @@ -1,14 +1,32 @@ import { defineStore } from 'pinia' -import { type Inventory } from './types/data' +import { type Inventory } from 'src/types/data' + +interface InventoryState { + filePath: string, + data: Inventory | null, +} + +const fileTree = (state: InventoryState) => state.filePath.split(/(\\)|(\/)/gm) export const useAppStore = defineStore('appStore', { state: () => ({ currentInventory: { filePath: '', data: null as Inventory | null, - }, + } as InventoryState, }), + getters: { + fileTree: (state) => fileTree(state.currentInventory), + fileDirectory: (state) => { + const split = fileTree(state.currentInventory) + return state.currentInventory.filePath.replace(split[split.length - 1], '') + }, + fileName: (state) => { + const split = fileTree(state.currentInventory) + return split[split.length - 1] + }, + }, }) export type AppStoreDefinition = Omit< diff --git a/src/views/Editor/DataEditor.vue b/src/views/Editor/DataEditor.vue new file mode 100644 index 0000000..c9681fb --- /dev/null +++ b/src/views/Editor/DataEditor.vue @@ -0,0 +1,85 @@ +<script setup lang="ts"> +import { ref } from 'vue' +import DataTable from 'primevue/datatable' +import Column from 'primevue/column' +import Image from 'primevue/image' +import InputText from 'primevue/inputtext' + +import { + type Row as DataRow, + type Column as DataColumn, +} from 'src/types/data' + +const props = defineProps<{ + columns: DataColumn[], +}>() +const model = defineModel<DataRow[]>() +const editingRows = ref([]) + +const onRowEditSave = (event: { newData: any, index: number }) => { + let { newData, index } = event + model.value![index] = newData + console.log(model.value) +} +</script> + +<template lang="pug"> +DataTable( + @row-edit-save='onRowEditSave' + v-model:editingRows='editingRows' + :value='model' + editMode='row' + tableStyle='min-width: 50rem' +) + Column( + v-for='col of columns' + :key='col.name' + :field='col.name' + :header='col.name' + style='width:5rem;' + ) + template( + #body='slotProps' + ) + div( + v-if='col.type === "image"' + ) + Image( + v-if='slotProps.data.image' + :src='slotProps.data.image.src' + :alt='slotProps.data.image.alt' + preview + ) + span( + v-else + ) No image + div( + v-else + ) + span {{ slotProps.data[col.name] }} + template( + #editor='{ data, field }' + ) + div( + v-if='col.type === "image"' + ) + span Not Implemented + div( + v-else + ) + InputText( + v-model='data[field]' + fluid + ) + Column( + :rowEditor='true' + style='width:10%;min-width:8rem;' + bodyStyle='text-align:center;' + ) +</template> + +<style scoped lang="sass"> +:deep(.p-image) + img + max-width: 16rem +</style> diff --git a/src/views/Editor/Editor.vue b/src/views/Editor/Editor.vue new file mode 100644 index 0000000..17659f2 --- /dev/null +++ b/src/views/Editor/Editor.vue @@ -0,0 +1,41 @@ +<script setup lang="ts"> +import { ref } from 'vue' +import Tabs from 'primevue/tabs' +import TabList from 'primevue/tablist' +import Tab from 'primevue/tab' +import TabPanels from 'primevue/tabpanels' +import TabPanel from 'primevue/tabpanel' + +import { + FieldTypes, +} from 'src/types/data' +import { useAppStore } from 'src/store' +import DataEditor from './DataEditor.vue' +import FieldEditor from './FieldEditor.vue' + +const appStore = useAppStore() + +const data = ref([...appStore.currentInventory.data?.rows || []]) +const fields = ref([...appStore.currentInventory.data?.columns || []]) +</script> + +<template lang="pug"> +Tabs(value='data-editor') + TabList + Tab(value='data-editor') Data Editor + Tab(value='field-editor') Field Editor + TabPanels + TabPanel(value='field-editor') + FieldEditor( + v-model='fields' + ) + TabPanel(value='data-editor') + DataEditor( + v-model='data' + :columns='fields' + ) +</template> + +<style scoped lang="sass"> + +</style> diff --git a/src/views/Editor.vue b/src/views/Editor/FieldEditor.vue similarity index 55% rename from src/views/Editor.vue rename to src/views/Editor/FieldEditor.vue index 54e01b3..6160d29 100644 --- a/src/views/Editor.vue +++ b/src/views/Editor/FieldEditor.vue @@ -3,35 +3,21 @@ import { ref } from 'vue' import Button from 'primevue/button' import DataTable from 'primevue/datatable' import Column from 'primevue/column' -import ColumnGroup from 'primevue/columngroup' -import Image from 'primevue/image' import InputText from 'primevue/inputtext' -import Row from 'primevue/row' import Select from 'primevue/select' import { FieldTypes, -} from '../types/data' -import { useAppStore } from '../store' + type Column as DataColumn, +} from 'src/types/data' -const appStore = useAppStore() - -const sampleData = ref([...appStore.currentInventory.data?.rows || []]) -const editingRows = ref([]) - -const sampleFields = ref([...appStore.currentInventory.data?.columns || []]) +const model = defineModel<DataColumn[]>() const editingFields = ref([]) -const onRowEditSave = (event: { newData: any, index: number }) => { - let { newData, index } = event - sampleData.value[index] = newData - console.log(sampleData.value) -} - const onFieldEditSave = (event: { newData: any, index: number }) => { let { newData, index } = event - sampleFields.value[index] = newData - console.log(sampleFields.value) + model.value![index] = newData + console.log(model.value) } </script> @@ -39,7 +25,7 @@ const onFieldEditSave = (event: { newData: any, index: number }) => { DataTable( @row-edit-save='onFieldEditSave' v-model:editingRows='editingFields' - :value='sampleFields' + :value='model' editMode='row' tableStyle='min-width: 50rem' ) @@ -121,62 +107,7 @@ DataTable( slotProps.editorCancelCallback(e) }` ) -DataTable( - @row-edit-save='onRowEditSave' - v-model:editingRows='editingRows' - :value='sampleData' - editMode='row' - tableStyle='min-width: 50rem' -) - Column( - v-for='col of sampleFields' - :key='col.name' - :field='col.name' - :header='col.name' - style='width:5rem;' - ) - template( - #body='slotProps' - ) - div( - v-if='col.type === "image"' - ) - Image( - v-if='slotProps.data.image' - :src='slotProps.data.image.src' - :alt='slotProps.data.image.alt' - preview - ) - span( - v-else - ) No image - div( - v-else - ) - span {{ slotProps.data[col.name] }} - template( - #editor='{ data, field }' - ) - div( - v-if='col.type === "image"' - ) - span Not Implemented - div( - v-else - ) - InputText( - v-model='data[field]' - fluid - ) - Column( - :rowEditor='true' - style='width:10%;min-width:8rem;' - bodyStyle='text-align:center;' - ) </template> -<style lang="sass"> -.p-image - img - max-width: 16rem +<style scoped lang="sass"> </style> diff --git a/src/views/Home.vue b/src/views/Home/Home.vue similarity index 98% rename from src/views/Home.vue rename to src/views/Home/Home.vue index f13fcee..3c40b25 100644 --- a/src/views/Home.vue +++ b/src/views/Home/Home.vue @@ -13,7 +13,7 @@ import InputGroup from 'primevue/inputgroup' import InputGroupAddon from 'primevue/inputgroupaddon' import Panel from 'primevue/panel' -import { useAppStore } from '../store' +import { useAppStore } from 'src/store' const router = useRouter() const toast = useToast() @@ -105,11 +105,7 @@ section.home-page template(#header) h2 Open Recent File .content - InputGroup - Button.submit( - label='Browse...' - @click='onFind' - ) + p Not Yet Implemented p or... Panel template(#header) @@ -145,7 +141,11 @@ section.home-page template(#header) h2 Open An Existing File .content - p Not Yet Implemented + InputGroup + Button.submit( + label='Browse...' + @click='onFind' + ) </template> <style scoped lang="sass"> diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index fc81239..021d977 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1,7 +1,7 @@ -/// <reference types="vite/client" /> +/// <reference types='vite/client' /> -declare module "*.vue" { - import type { DefineComponent } from "vue"; - const component: DefineComponent<{}, {}, any>; - export default component; +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component } diff --git a/tsconfig.json b/tsconfig.json index f4b1232..b2d6c4d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,10 @@ { "compilerOptions": { + "baseUrl": "./", + "paths": { + "src/*": ["./src/*"] + }, + "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", diff --git a/vite.config.ts b/vite.config.ts index a55076c..240061c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,13 +1,24 @@ -import { defineConfig } from "vite"; -import vue from "@vitejs/plugin-vue"; +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import * as path from 'path' -// @ts-expect-error process is a nodejs global -const host = process.env.TAURI_DEV_HOST; +// //@ts-expect-error process is a nodejs global +const host = process.env.TAURI_DEV_HOST // https://vitejs.dev/config/ export default defineConfig(async () => ({ - plugins: [vue()], - + plugins: [vue({ + template: { + preprocessOptions: { + basedir: path.resolve(__dirname, './') + }, + } + })], + resolve: { + alias: { + 'src': path.resolve(__dirname, './src'), + }, + }, // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // // 1. prevent vite from obscuring rust errors @@ -19,14 +30,14 @@ export default defineConfig(async () => ({ host: host || false, hmr: host ? { - protocol: "ws", + protocol: 'ws', host, port: 1421, } : undefined, watch: { // 3. tell vite to ignore watching `src-tauri` - ignored: ["**/src-tauri/**"], + ignored: ['**/src-tauri/**'], }, }, -})); +}))