mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-16 22:20:51 +01:00
fixed sync locale and theme
This commit is contained in:
@ -11,9 +11,12 @@ export default defineNuxtConfig({
|
|||||||
"@vueuse/nuxt",
|
"@vueuse/nuxt",
|
||||||
"@nuxt/icon",
|
"@nuxt/icon",
|
||||||
"nuxt-snackbar",
|
"nuxt-snackbar",
|
||||||
"nuxt-svgo-loader",
|
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
imports: {
|
imports: {
|
||||||
dirs: ["composables/**", "stores/**", "components/**", "pages/**", "types/**"],
|
dirs: ["composables/**", "stores/**", "components/**", "pages/**", "types/**"],
|
||||||
},
|
},
|
||||||
@ -26,10 +29,23 @@ export default defineNuxtConfig({
|
|||||||
scan: true,
|
scan: true,
|
||||||
includeCustomCollections: true,
|
includeCustomCollections: true,
|
||||||
},
|
},
|
||||||
serverBundle: { collections: ["mdi", "line-md", "solar", "gg", "emojione"] }
|
serverBundle: { collections: ["mdi", "line-md", "solar", "gg", "emojione"] },
|
||||||
//collections: ["mdi", "line-md"]
|
|
||||||
|
customCollections: [
|
||||||
|
{
|
||||||
|
prefix: 'my-icon',
|
||||||
|
dir: './src/assets/icons/'
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* svgo: {
|
||||||
|
autoImportPath: '~/assets/svg/',
|
||||||
|
dts: true,
|
||||||
|
}, */
|
||||||
|
|
||||||
i18n: {
|
i18n: {
|
||||||
strategy: "prefix_and_default",
|
strategy: "prefix_and_default",
|
||||||
defaultLocale: "de",
|
defaultLocale: "de",
|
||||||
@ -90,4 +106,4 @@ export default defineNuxtConfig({
|
|||||||
strictPort: true,
|
strictPort: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
28
package.json
28
package.json
@ -15,12 +15,12 @@
|
|||||||
"drizzle:migrate": "drizzle-kit migrate"
|
"drizzle:migrate": "drizzle-kit migrate"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@libsql/client": "^0.15.4",
|
"@libsql/client": "^0.15.6",
|
||||||
"@nuxt/icon": "1.11.0",
|
"@nuxt/icon": "1.11.0",
|
||||||
"@nuxt/image": "1.10.0",
|
"@nuxt/image": "1.10.0",
|
||||||
"@nuxtjs/i18n": "^9.5.3",
|
"@nuxtjs/i18n": "^9.5.4",
|
||||||
"@pinia/nuxt": "^0.11.0",
|
"@pinia/nuxt": "^0.11.0",
|
||||||
"@tailwindcss/vite": "^4.1.5",
|
"@tailwindcss/vite": "^4.1.7",
|
||||||
"@tauri-apps/api": "^2.5.0",
|
"@tauri-apps/api": "^2.5.0",
|
||||||
"@tauri-apps/plugin-dialog": "^2.2.1",
|
"@tauri-apps/plugin-dialog": "^2.2.1",
|
||||||
"@tauri-apps/plugin-fs": "^2.2.1",
|
"@tauri-apps/plugin-fs": "^2.2.1",
|
||||||
@ -29,27 +29,29 @@
|
|||||||
"@tauri-apps/plugin-os": "^2.2.1",
|
"@tauri-apps/plugin-os": "^2.2.1",
|
||||||
"@tauri-apps/plugin-sql": "~2.2.0",
|
"@tauri-apps/plugin-sql": "~2.2.0",
|
||||||
"@tauri-apps/plugin-store": "^2.2.0",
|
"@tauri-apps/plugin-store": "^2.2.0",
|
||||||
"@vueuse/core": "^13.1.0",
|
"@vueuse/core": "^13.2.0",
|
||||||
"@vueuse/nuxt": "^13.1.0",
|
"@vueuse/nuxt": "^13.2.0",
|
||||||
"drizzle-orm": "^0.43.0",
|
"drizzle-orm": "^0.43.1",
|
||||||
"flyonui": "^2.1.0",
|
"flyonui": "^2.1.0",
|
||||||
"nuxt": "^3.17.0",
|
"nuxt": "^3.17.3",
|
||||||
|
"nuxt-icons": "3.2.1",
|
||||||
"nuxt-snackbar": "1.3.0",
|
"nuxt-snackbar": "1.3.0",
|
||||||
|
"nuxt-svgo": "4.1.2",
|
||||||
"nuxt-svgo-loader": "0.5.0",
|
"nuxt-svgo-loader": "0.5.0",
|
||||||
"nuxt-zod-i18n": "^1.11.5",
|
"nuxt-zod-i18n": "^1.11.5",
|
||||||
"tailwindcss": "^4.1.5",
|
"tailwindcss": "^4.1.7",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.14",
|
||||||
"zod": "^3.24.3"
|
"zod": "^3.25.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@egoist/tailwindcss-icons": "^1.9.0",
|
"@egoist/tailwindcss-icons": "^1.9.0",
|
||||||
"@iconify/json": "^2.2.338",
|
"@iconify/json": "^2.2.339",
|
||||||
"@iconify/tailwind4": "^1.0.6",
|
"@iconify/tailwind4": "^1.0.6",
|
||||||
"@tauri-apps/cli": "^2.5.0",
|
"@tauri-apps/cli": "^2.5.0",
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.4",
|
||||||
"drizzle-kit": "^0.31.1",
|
"drizzle-kit": "^0.31.1",
|
||||||
"typescript": "~5.8.3",
|
"typescript": "~5.8.3",
|
||||||
"vite": "^6.3.3",
|
"vite": "^6.3.5",
|
||||||
"vue-tsc": "^2.2.10"
|
"vue-tsc": "^2.2.10"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39",
|
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39",
|
||||||
|
|||||||
3212
pnpm-lock.yaml
generated
3212
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
1678
src/assets/icons/extensions-overview.svg
Normal file
1678
src/assets/icons/extensions-overview.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 164 KiB |
@ -1,5 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<UiDropdown activator-class="btn btn-text btn-circle">
|
<UiDropdown
|
||||||
|
activator-class="btn btn-text btn-circle "
|
||||||
|
dropdown-class="[--offset:20]"
|
||||||
|
>
|
||||||
<template #activator>
|
<template #activator>
|
||||||
<div
|
<div
|
||||||
class="size-9.5 rounded-full items-center justify-center text-base-content text-base"
|
class="size-9.5 rounded-full items-center justify-center text-base-content text-base"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="dropdown relative inline-flex">
|
<div class="dropdown relative inline-flex" :class="dropdownClass">
|
||||||
<button
|
<button
|
||||||
:id
|
:id
|
||||||
class="dropdown-toggle"
|
class="dropdown-toggle"
|
||||||
@ -47,6 +47,7 @@ const { itemIs = 'li' } = defineProps<{
|
|||||||
items?: T[]
|
items?: T[]
|
||||||
itemIs?: string
|
itemIs?: string
|
||||||
activatorClass?: string
|
activatorClass?: string
|
||||||
|
dropdownClass?: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
defineEmits<{ select: [T] }>()
|
defineEmits<{ select: [T] }>()
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<fieldset class="join w-full">
|
<fieldset class="join w-full pt-0.5">
|
||||||
<slot name="prepend" />
|
<slot name="prepend" />
|
||||||
|
|
||||||
<div class="input join-item">
|
<div class="input join-item">
|
||||||
|
|||||||
@ -1,33 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<aside
|
<aside
|
||||||
class="flex shrink-0 transition-[width] ease-in duration-300 z-30 h-full overflow-hidden fixed sm:relative left-0 shadow border-r border-base-300"
|
class="flex shrink-0 transition-[width] ease-in duration-300 z-30 h-full overflow-hidden fixed sm:relative left-0 shadow border-r border-base-300/90"
|
||||||
>
|
>
|
||||||
<div class="sm:flex flex-col w-14 bg-base-200 shrink-0 h-full hidden">
|
<div class="sm:flex flex-col w-14 bg-base-200 shrink-0 h-full hidden">
|
||||||
<img src="/logo.svg" class="bg-primary p-3 size-16" />
|
<img src="/logo.svg" class="bg-primary p-3 size-16" />
|
||||||
|
|
||||||
<div class="flex flex-col justify-between h-full overflow-y-scroll z-10">
|
<div class="flex flex-col justify-between h-full overflow-y-scroll z-10">
|
||||||
<div class="flex flex-col space-y-2 text-base-content/90">
|
<div class="flex flex-col space-y-2 text-base-content/90"></div>
|
||||||
<template v-for="item in menu.top">
|
|
||||||
<UiSidebarLink v-if="item.to" v-bind="item" />
|
|
||||||
|
|
||||||
<UiSidebarButton v-else :icon="item.icon" :label="$t(item.label)" @click="item.click" />
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-col space-y-2 text-base-content/90">
|
|
||||||
<template v-for="item in menu.bottom">
|
|
||||||
<UiSidebarLink v-if="item.to" v-bind="item" />
|
|
||||||
|
|
||||||
<UiSidebarButton v-else :icon="item.icon" :label="$t(item.label)" @click="item.click" />
|
|
||||||
</template>
|
|
||||||
<!-- <UiSidebarLink
|
|
||||||
v-for="item in menu.bottom"
|
|
||||||
:icon="item.icon"
|
|
||||||
:to="item.to ?? ''"
|
|
||||||
:label="item.label"
|
|
||||||
@click="item.click"
|
|
||||||
/> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -76,11 +55,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
defineProps({
|
defineProps({
|
||||||
menu: {
|
menu: {
|
||||||
type: Object as PropType<ISidebarMenu>,
|
type: Object as PropType<ISidebarItem>,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
//const show = ref(true);
|
|
||||||
const { show } = storeToRefs(useSidebarStore());
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<li
|
<li
|
||||||
@click="triggerNavigate"
|
@click="triggerNavigate"
|
||||||
class="hover:text-primary rounded"
|
class="hover:text-primary rounded"
|
||||||
:class="{ ['bg-base-300']: isActive }"
|
:class="{ ['bg-base-200 text-base-content']: isActive }"
|
||||||
>
|
>
|
||||||
<UiTooltip :tooltip="tooltip ?? name" direction="right-start">
|
<UiTooltip :tooltip="tooltip ?? name" direction="right-start">
|
||||||
<NuxtLinkLocale
|
<NuxtLinkLocale
|
||||||
@ -18,24 +18,27 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { type ISidebarItem } from "#imports";
|
import { type ISidebarItem } from '#imports'
|
||||||
|
|
||||||
const props = defineProps<ISidebarItem>();
|
const props = defineProps<ISidebarItem>()
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter()
|
||||||
|
|
||||||
console.log("to", props.to);
|
console.log('to', props.to)
|
||||||
const isActive = computed(() => {
|
const isActive = computed(() => {
|
||||||
if (props.to?.name === "haexExtension") {
|
if (props.to?.name === 'haexExtension') {
|
||||||
return getSingleRouteParam(router.currentRoute.value.params.extensionId) === props.id;
|
return (
|
||||||
|
getSingleRouteParam(router.currentRoute.value.params.extensionId) ===
|
||||||
|
props.id
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return props.to?.name === router.currentRoute.value.meta.name;
|
return props.to?.name === router.currentRoute.value.meta.name
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
const linkRef = useTemplateRef("linkRef");
|
const linkRef = useTemplateRef('linkRef')
|
||||||
|
|
||||||
const triggerNavigate = () => linkRef.value?.$el.click();
|
const triggerNavigate = () => linkRef.value?.$el.click()
|
||||||
|
|
||||||
/* computed(() => {
|
/* computed(() => {
|
||||||
const found = useRouter()
|
const found = useRouter()
|
||||||
|
|||||||
@ -43,9 +43,9 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { save } from '@tauri-apps/plugin-dialog'
|
import { save } from '@tauri-apps/plugin-dialog'
|
||||||
|
import { onKeyStroke } from '@vueuse/core'
|
||||||
import { useVaultStore } from '~/stores/vault'
|
import { useVaultStore } from '~/stores/vault'
|
||||||
import { vaultDatabaseSchema } from './schema'
|
import { vaultDatabaseSchema } from './schema'
|
||||||
import { onKeyStroke } from '@vueuse/core'
|
|
||||||
|
|
||||||
onKeyStroke('Enter', (e) => {
|
onKeyStroke('Enter', (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
@click="onLoadDatabase"
|
@click="onLoadDatabase"
|
||||||
>
|
>
|
||||||
<Icon name="mdi:folder-open-outline" />
|
<Icon name="mdi:folder-open-outline" />
|
||||||
{{ t("database.open") }}
|
{{ t('database.open') }}
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -22,62 +22,60 @@
|
|||||||
|
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<UiButton class="btn-error" @click="onClose">
|
<UiButton class="btn-error" @click="onClose">
|
||||||
{{ t("abort") }}
|
{{ t('abort') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
|
|
||||||
<UiButton type="submit" class="btn-primary" @click="onOpenDatabase">
|
<UiButton type="submit" class="btn-primary" @click="onOpenDatabase">
|
||||||
{{ t("open") }}
|
{{ t('open') }}
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</template>
|
</template>
|
||||||
</UiDialog>
|
</UiDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { open } from "@tauri-apps/plugin-dialog";
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { vaultDatabaseSchema } from "./schema";
|
import { vaultDatabaseSchema } from './schema'
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
|
|
||||||
const isOpen = defineModel("isOpen", { type: Boolean });
|
const isOpen = defineModel('isOpen', { type: Boolean })
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
path: String,
|
path: String,
|
||||||
});
|
})
|
||||||
|
|
||||||
const check = ref(false);
|
const check = ref(false)
|
||||||
|
|
||||||
const database = reactive<{
|
const database = reactive<{
|
||||||
name: string;
|
name: string
|
||||||
password: string;
|
password: string
|
||||||
path: string | null;
|
path: string | null
|
||||||
type: "password" | "text";
|
type: 'password' | 'text'
|
||||||
}>({
|
}>({
|
||||||
name: "",
|
name: '',
|
||||||
password: "",
|
password: '',
|
||||||
path: "",
|
path: '',
|
||||||
type: "password",
|
type: 'password',
|
||||||
});
|
})
|
||||||
|
|
||||||
const initDatabase = () => {
|
const initDatabase = () => {
|
||||||
database.name = "";
|
database.name = ''
|
||||||
database.password = "";
|
database.password = ''
|
||||||
database.path = "";
|
database.path = ''
|
||||||
database.type = "password";
|
database.type = 'password'
|
||||||
};
|
}
|
||||||
|
|
||||||
initDatabase();
|
initDatabase()
|
||||||
|
|
||||||
const { add } = useSnackbar();
|
const { add } = useSnackbar()
|
||||||
|
|
||||||
const handleError = (error: unknown) => {
|
const handleError = (error: unknown) => {
|
||||||
isOpen.value = false;
|
isOpen.value = false
|
||||||
console.log("handleError", error, typeof error);
|
console.error('handleError', error, typeof error)
|
||||||
add({ type: "error", text: "Passwort falsch" });
|
add({ type: 'error', text: 'Passwort falsch' })
|
||||||
//console.error(error);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const { openAsync } = useVaultStore();
|
const { openAsync } = useVaultStore()
|
||||||
//const { show } = storeToRefs(useSidebarStore());
|
|
||||||
|
|
||||||
const onLoadDatabase = async () => {
|
const onLoadDatabase = async () => {
|
||||||
try {
|
try {
|
||||||
@ -86,75 +84,77 @@ const onLoadDatabase = async () => {
|
|||||||
directory: false,
|
directory: false,
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
name: "HaexVault",
|
name: 'HaexVault',
|
||||||
extensions: ["db"],
|
extensions: ['db'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
})
|
||||||
|
|
||||||
if (!database.path) return;
|
if (!database.path) return
|
||||||
|
|
||||||
isOpen.value = true;
|
isOpen.value = true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error);
|
handleError(error)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const localePath = useLocalePath();
|
const localePath = useLocalePath()
|
||||||
|
|
||||||
const { currentVault, currentVaultId } = storeToRefs(useVaultStore());
|
const { syncLocaleAsync, syncThemeAsync, syncVaultNameAsync } = useVaultStore()
|
||||||
const onOpenDatabase = async () => {
|
const onOpenDatabase = async () => {
|
||||||
try {
|
try {
|
||||||
check.value = true;
|
check.value = true
|
||||||
const path = database.path || props.path;
|
const path = database.path || props.path
|
||||||
const pathCheck = vaultDatabaseSchema.path.safeParse(path);
|
const pathCheck = vaultDatabaseSchema.path.safeParse(path)
|
||||||
const passwordCheck = vaultDatabaseSchema.password.safeParse(database.password);
|
const passwordCheck = vaultDatabaseSchema.password.safeParse(
|
||||||
|
database.password
|
||||||
|
)
|
||||||
|
|
||||||
if (!pathCheck.success || !passwordCheck.success || !path) {
|
if (!pathCheck.success || !passwordCheck.success || !path) {
|
||||||
add({
|
add({
|
||||||
type: "error",
|
type: 'error',
|
||||||
text: `Params falsch. Path: ${pathCheck.error} | Password: ${passwordCheck.error}`,
|
text: `Params falsch. Path: ${pathCheck.error} | Password: ${passwordCheck.error}`,
|
||||||
});
|
})
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("try to open", path);
|
|
||||||
|
|
||||||
const vaultId = await openAsync({
|
const vaultId = await openAsync({
|
||||||
path,
|
path,
|
||||||
password: database.password,
|
password: database.password,
|
||||||
});
|
})
|
||||||
|
|
||||||
if (!vaultId) {
|
if (!vaultId) {
|
||||||
add({
|
add({
|
||||||
type: "error",
|
type: 'error',
|
||||||
text: "Vault konnte nicht geöffnet werden. \n Vermutlich ist das Passwort falsch",
|
text: 'Vault konnte nicht geöffnet werden. \n Vermutlich ist das Passwort falsch',
|
||||||
});
|
})
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose();
|
onClose()
|
||||||
|
|
||||||
currentVaultId.value = vaultId;
|
|
||||||
console.log("vault before navigation", currentVault.value, currentVaultId.value, vaultId);
|
|
||||||
await navigateTo(
|
await navigateTo(
|
||||||
localePath({
|
localePath({
|
||||||
name: "vaultOverview",
|
name: 'vaultOverview',
|
||||||
params: {
|
params: {
|
||||||
vaultId,
|
vaultId,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
|
await Promise.allSettled([
|
||||||
|
syncLocaleAsync(),
|
||||||
|
syncThemeAsync(),
|
||||||
|
syncVaultNameAsync(),
|
||||||
|
])
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
handleError(error)
|
||||||
handleError(error);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const onClose = () => {
|
const onClose = () => {
|
||||||
initDatabase();
|
initDatabase()
|
||||||
isOpen.value = false;
|
isOpen.value = false
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<i18n lang="json">
|
<i18n lang="json">
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col p-1 relative">
|
<div class="flex flex-col p-1 relative h-full">
|
||||||
<UiButton
|
<div class="flex" v-if="extensionStore.availableExtensions.length">
|
||||||
class="fixed top-20 right-4 btn-square btn-primary"
|
<UiButton
|
||||||
@click="loadExtensionManifestAsync"
|
class="fixed top-20 right-4 btn-square btn-primary"
|
||||||
>
|
@click="loadExtensionManifestAsync"
|
||||||
<Icon name="mdi:plus" size="1.5em" />
|
>
|
||||||
</UiButton>
|
<Icon name="mdi:plus" size="1.5em" />
|
||||||
<h1>{{ t("title") }}</h1>
|
</UiButton>
|
||||||
|
|
||||||
<div class="flex">
|
|
||||||
<HaexExtensionCard
|
<HaexExtensionCard
|
||||||
v-for="extension in extensionStore.availableExtensions"
|
v-for="extension in extensionStore.availableExtensions"
|
||||||
v-bind="extension"
|
v-bind="extension"
|
||||||
@ -16,9 +15,25 @@
|
|||||||
>
|
>
|
||||||
</HaexExtensionCard>
|
</HaexExtensionCard>
|
||||||
</div>
|
</div>
|
||||||
<!-- <UiButton @click="loadExtensionManifestAsync">
|
|
||||||
{{ t("extension.add") }}
|
<!-- <SvgoExtensionsOverview class="h-screen w-screen" /> -->
|
||||||
</UiButton> -->
|
<!-- <nuxt-icon name="extensions-overview" class="size-full" /> -->
|
||||||
|
<div v-else class="h-full w-full">
|
||||||
|
<Icon
|
||||||
|
name="my-icon:extensions-overview"
|
||||||
|
class="size-full md:size-2/3 md:translate-x-1/5 md:translate-y-1/3"
|
||||||
|
/>
|
||||||
|
<div class="fixed top-30 right-10">
|
||||||
|
<UiTooltip :tooltip="t('extension.add')">
|
||||||
|
<UiButton
|
||||||
|
class="btn-square btn-primary btn-xl btn-gradient rotate-45"
|
||||||
|
@click="loadExtensionManifestAsync"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:plus" size="1.5em" class="rotate-45" />
|
||||||
|
</UiButton>
|
||||||
|
</UiTooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<HaexExtensionManifestConfirm
|
<HaexExtensionManifestConfirm
|
||||||
:manifest="extension.manifest"
|
:manifest="extension.manifest"
|
||||||
@ -26,7 +41,6 @@
|
|||||||
@confirm="addExtensionAsync"
|
@confirm="addExtensionAsync"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{{ showRemoveDialog }}
|
|
||||||
<HaexExtensionDialogRemove
|
<HaexExtensionDialogRemove
|
||||||
v-model:open="showRemoveDialog"
|
v-model:open="showRemoveDialog"
|
||||||
:extension="extensionToBeRemoved"
|
:extension="extensionToBeRemoved"
|
||||||
@ -37,121 +51,126 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { join } from "@tauri-apps/api/path";
|
import { join } from '@tauri-apps/api/path'
|
||||||
import { open } from "@tauri-apps/plugin-dialog";
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { readTextFile } from "@tauri-apps/plugin-fs";
|
import { readTextFile } from '@tauri-apps/plugin-fs'
|
||||||
import type { IHaexHubExtension, IHaexHubExtensionManifest } from "~/types/haexhub";
|
import type {
|
||||||
|
IHaexHubExtension,
|
||||||
|
IHaexHubExtensionManifest,
|
||||||
|
} from '~/types/haexhub'
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
name: "extensionOverview",
|
name: 'extensionOverview',
|
||||||
});
|
})
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n()
|
||||||
const extensionStore = useExtensionsStore();
|
const extensionStore = useExtensionsStore()
|
||||||
|
|
||||||
const showConfirmation = ref(false);
|
const showConfirmation = ref(false)
|
||||||
|
|
||||||
const extension = reactive<{
|
const extension = reactive<{
|
||||||
manifest: IHaexHubExtensionManifest | null | undefined;
|
manifest: IHaexHubExtensionManifest | null | undefined
|
||||||
path: string | null;
|
path: string | null
|
||||||
}>({
|
}>({
|
||||||
manifest: null,
|
manifest: null,
|
||||||
path: "",
|
path: '',
|
||||||
});
|
})
|
||||||
|
|
||||||
onMounted(() => console.log("extension overview"));
|
|
||||||
|
|
||||||
const loadExtensionManifestAsync = async () => {
|
const loadExtensionManifestAsync = async () => {
|
||||||
try {
|
try {
|
||||||
extension.path = await open({ directory: true, recursive: true });
|
extension.path = await open({ directory: true, recursive: true })
|
||||||
if (!extension.path) return;
|
if (!extension.path) return
|
||||||
|
|
||||||
const manifestFile = JSON.parse(
|
const manifestFile = JSON.parse(
|
||||||
await readTextFile(await join(extension.path, "manifest.json"))
|
await readTextFile(await join(extension.path, 'manifest.json'))
|
||||||
);
|
)
|
||||||
|
|
||||||
if (!extensionStore.checkManifest(manifestFile))
|
if (!extensionStore.checkManifest(manifestFile))
|
||||||
throw new Error(`Manifest fehlerhaft ${JSON.stringify(manifestFile)}`);
|
throw new Error(`Manifest fehlerhaft ${JSON.stringify(manifestFile)}`)
|
||||||
|
|
||||||
extension.manifest = manifestFile;
|
extension.manifest = manifestFile
|
||||||
showConfirmation.value = true;
|
showConfirmation.value = true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Fehler loadExtensionManifestAsync:", error);
|
console.error('Fehler loadExtensionManifestAsync:', error)
|
||||||
add({ type: "error", text: JSON.stringify(error) });
|
add({ type: 'error', text: JSON.stringify(error) })
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const { add } = useSnackbar();
|
const { add } = useSnackbar()
|
||||||
|
|
||||||
const addExtensionAsync = async () => {
|
const addExtensionAsync = async () => {
|
||||||
try {
|
try {
|
||||||
await extensionStore.installAsync(extension.path);
|
await extensionStore.installAsync(extension.path)
|
||||||
await extensionStore.loadExtensionsAsync();
|
await extensionStore.loadExtensionsAsync()
|
||||||
console.log("Modul erfolgreich geladen");
|
|
||||||
add({
|
|
||||||
type: "success",
|
|
||||||
title: t("extension.success.title", { extension: extension.manifest?.name }),
|
|
||||||
text: t("extension.success.text"),
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Fehler addExtensionAsync:", error);
|
|
||||||
add({ type: "error", text: JSON.stringify(error) });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const showRemoveDialog = ref(false);
|
add({
|
||||||
const extensionToBeRemoved = ref<IHaexHubExtension>();
|
type: 'success',
|
||||||
|
title: t('extension.success.title', {
|
||||||
|
extension: extension.manifest?.name,
|
||||||
|
}),
|
||||||
|
text: t('extension.success.text'),
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fehler addExtensionAsync:', error)
|
||||||
|
add({ type: 'error', text: JSON.stringify(error) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const showRemoveDialog = ref(false)
|
||||||
|
const extensionToBeRemoved = ref<IHaexHubExtension>()
|
||||||
|
|
||||||
const onShowRemoveDialog = (extension: IHaexHubExtension) => {
|
const onShowRemoveDialog = (extension: IHaexHubExtension) => {
|
||||||
extensionToBeRemoved.value = extension;
|
extensionToBeRemoved.value = extension
|
||||||
showRemoveDialog.value = true;
|
showRemoveDialog.value = true
|
||||||
};
|
}
|
||||||
|
|
||||||
const removeExtensionAsync = async () => {
|
const removeExtensionAsync = async () => {
|
||||||
if (!extensionToBeRemoved.value?.id || !extensionToBeRemoved.value?.version) {
|
if (!extensionToBeRemoved.value?.id || !extensionToBeRemoved.value?.version) {
|
||||||
add({ type: "error", text: "Erweiterung kann nicht gelöscht werden" });
|
add({ type: 'error', text: 'Erweiterung kann nicht gelöscht werden' })
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await extensionStore.removeExtensionAsync(
|
await extensionStore.removeExtensionAsync(
|
||||||
extensionToBeRemoved.value.id,
|
extensionToBeRemoved.value.id,
|
||||||
extensionToBeRemoved.value.version
|
extensionToBeRemoved.value.version
|
||||||
);
|
)
|
||||||
await extensionStore.loadExtensionsAsync();
|
await extensionStore.loadExtensionsAsync()
|
||||||
add({
|
add({
|
||||||
type: "success",
|
type: 'success',
|
||||||
title: t("extension.remove.success.title", {
|
title: t('extension.remove.success.title', {
|
||||||
extensionName: extensionToBeRemoved.value.name,
|
extensionName: extensionToBeRemoved.value.name,
|
||||||
}),
|
}),
|
||||||
text: t("extension.remove.success.text", { extensionName: extensionToBeRemoved.value.name }),
|
text: t('extension.remove.success.text', {
|
||||||
});
|
extensionName: extensionToBeRemoved.value.name,
|
||||||
|
}),
|
||||||
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
add({
|
add({
|
||||||
type: "error",
|
type: 'error',
|
||||||
title: t("extension.remove.error.title"),
|
title: t('extension.remove.error.title'),
|
||||||
text: t("extension.remove.error.text", { error: JSON.stringify(error) }),
|
text: t('extension.remove.error.text', { error: JSON.stringify(error) }),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<i18n lang="yaml">
|
<i18n lang="yaml">
|
||||||
de:
|
de:
|
||||||
title: "Erweiterung installieren"
|
title: 'Erweiterung installieren'
|
||||||
extension:
|
extension:
|
||||||
remove:
|
remove:
|
||||||
success:
|
success:
|
||||||
text: "Erweiterung {extensionName} wurde erfolgreich entfernt"
|
text: 'Erweiterung {extensionName} wurde erfolgreich entfernt'
|
||||||
title: "{extensionName} entfernt"
|
title: '{extensionName} entfernt'
|
||||||
error:
|
error:
|
||||||
text: "Erweiterung {extensionName} konnte nicht entfernt werden. \n {error}"
|
text: "Erweiterung {extensionName} konnte nicht entfernt werden. \n {error}"
|
||||||
title: "Fehler beim Entfernen von {extensionName}"
|
title: 'Fehler beim Entfernen von {extensionName}'
|
||||||
|
|
||||||
add: "Erweiterung hinzufügen"
|
add: 'Erweiterung hinzufügen'
|
||||||
success:
|
success:
|
||||||
title: "{extension} hinzugefügt"
|
title: '{extension} hinzugefügt'
|
||||||
text: "Die Erweiterung wurde erfolgreich hinzugefügt"
|
text: 'Die Erweiterung wurde erfolgreich hinzugefügt'
|
||||||
en:
|
en:
|
||||||
title: "Install extension"
|
title: 'Install extension'
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|||||||
@ -43,17 +43,16 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const openVaults = ref<IOpenVaults | undefined>();
|
const openVaults = ref<IOpenVaults>({});
|
||||||
|
|
||||||
const currentVault = ref<IVault | undefined>();
|
const currentVault = computed(() => openVaults.value?.[currentVaultId.value ?? ""]) //ref<IVault>();
|
||||||
|
|
||||||
watch(
|
/* watch(
|
||||||
currentVaultId,
|
currentVaultId,
|
||||||
async () => {
|
() => {
|
||||||
currentVault.value = openVaults.value?.[currentVaultId.value ?? ""];
|
currentVault.value = openVaults.value?.[currentVaultId.value ?? ""];
|
||||||
},
|
}
|
||||||
{ immediate: true }
|
); */
|
||||||
);
|
|
||||||
|
|
||||||
const hostKey = computedAsync(async () => "".concat(type(), version(), await hostname() ?? ""))
|
const hostKey = computedAsync(async () => "".concat(type(), version(), await hostname() ?? ""))
|
||||||
|
|
||||||
@ -106,11 +105,7 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { addVaultAsync } = useLastVaultStore();
|
const { addVaultAsync } = useLastVaultStore();
|
||||||
addVaultAsync({ path });
|
await addVaultAsync({ path })
|
||||||
|
|
||||||
syncLocaleAsync()
|
|
||||||
syncThemeAsync()
|
|
||||||
syncVaultNameAsync()
|
|
||||||
|
|
||||||
return vaultId;
|
return vaultId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -158,8 +153,6 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
|||||||
const syncLocaleAsync = async () => {
|
const syncLocaleAsync = async () => {
|
||||||
try {
|
try {
|
||||||
const app = useNuxtApp()
|
const app = useNuxtApp()
|
||||||
app.$i18n.availableLocales
|
|
||||||
//const { availableLocales, defaultLocale, setLocale, locale } = useI18n()
|
|
||||||
|
|
||||||
const currentLocaleRow = await currentVault.value?.drizzle
|
const currentLocaleRow = await currentVault.value?.drizzle
|
||||||
.select()
|
.select()
|
||||||
@ -197,7 +190,7 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
|||||||
await currentVault.value?.drizzle.insert(schema.haexSettings).values({
|
await currentVault.value?.drizzle.insert(schema.haexSettings).values({
|
||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
key: 'theme',
|
key: 'theme',
|
||||||
value: currentTheme.value.name,
|
value: currentTheme.value.value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,6 +227,9 @@ export const useVaultStore = defineStore("vaultStore", () => {
|
|||||||
openVaults,
|
openVaults,
|
||||||
read_only,
|
read_only,
|
||||||
refreshDatabaseAsync,
|
refreshDatabaseAsync,
|
||||||
|
syncLocaleAsync,
|
||||||
|
syncThemeAsync,
|
||||||
|
syncVaultNameAsync,
|
||||||
updateVaultNameAsync,
|
updateVaultNameAsync,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user