mirror of https://github.com/wg-easy/wg-easy
42 changed files with 348 additions and 502 deletions
@ -1,11 +1,11 @@ |
|||||
<script setup lang="ts"> |
|
||||
const { text } = defineProps<{ |
|
||||
text: string; |
|
||||
}>(); |
|
||||
</script> |
|
||||
|
|
||||
<template> |
<template> |
||||
<h2 class="flex-1 text-2xl font-medium"> |
<h2 class="flex-1 text-2xl font-medium"> |
||||
{{ text }} |
{{ text }} |
||||
</h2> |
</h2> |
||||
</template> |
</template> |
||||
|
|
||||
|
<script setup lang="ts"> |
||||
|
const { text } = defineProps<{ |
||||
|
text: string; |
||||
|
}>(); |
||||
|
</script> |
||||
|
@ -1,45 +0,0 @@ |
|||||
<template> |
|
||||
<SelectRoot v-model="langProxy" :default-value="locale"> |
|
||||
<SelectTrigger |
|
||||
class="inline-flex h-[35px] min-w-[160px] items-center justify-between gap-[5px] rounded px-[15px] text-[13px] leading-none dark:bg-neutral-500 dark:text-white" |
|
||||
aria-label="Customize language" |
|
||||
> |
|
||||
<SelectValue :placeholder="$t('setup.chooseLang')" /> |
|
||||
<IconsArrowDown class="size-4" /> |
|
||||
</SelectTrigger> |
|
||||
|
|
||||
<SelectPortal> |
|
||||
<SelectContent |
|
||||
class="min-w-[160px] rounded bg-white dark:bg-neutral-500" |
|
||||
:side-offset="5" |
|
||||
> |
|
||||
<SelectViewport class="p-[5px]"> |
|
||||
<SelectItem |
|
||||
v-for="(option, index) in langs" |
|
||||
:key="index" |
|
||||
:value="option.code" |
|
||||
class="text-grass11 relative flex h-[25px] items-center rounded-[3px] pl-[25px] pr-[35px] text-[13px] leading-none hover:bg-red-800 hover:text-white dark:text-white" |
|
||||
> |
|
||||
<SelectItemText> |
|
||||
{{ option.name }} |
|
||||
</SelectItemText> |
|
||||
</SelectItem> |
|
||||
</SelectViewport> |
|
||||
</SelectContent> |
|
||||
</SelectPortal> |
|
||||
</SelectRoot> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
// TODO: improve |
|
||||
|
|
||||
const { locales, locale, setLocale } = useI18n(); |
|
||||
|
|
||||
const langProxy = ref(locale); |
|
||||
|
|
||||
watchEffect(() => { |
|
||||
setLocale(langProxy.value); |
|
||||
}); |
|
||||
|
|
||||
const langs = locales.value.sort((a, b) => a.code.localeCompare(b.code)); |
|
||||
</script> |
|
@ -1,83 +1,59 @@ |
|||||
<template> |
<template> |
||||
<div> |
<div> |
||||
<p class="p-8 text-center text-lg"> |
<p class="p-8 text-center text-lg"> |
||||
{{ $t('setup.messageSetupCreateAdminUser') }} |
{{ $t('setup.createAdminDesc') }} |
||||
</p> |
</p> |
||||
<form id="newAccount"></form> |
<div class="flex flex-col gap-3"> |
||||
<div> |
<div class="flex flex-col"> |
||||
<Label for="username">{{ $t('username') }}</Label> |
<FormNullTextField |
||||
<input |
id="username" |
||||
id="username" |
v-model="username" |
||||
v-model="username" |
autocomplete="username" |
||||
form="newAccount" |
:label="$t('general.username')" |
||||
type="text" |
/> |
||||
autocomplete="username" |
</div> |
||||
class="mb-5 w-full rounded-lg border-2 border-gray-100 px-3 py-2 text-sm text-gray-500 focus:border-red-800 focus:outline-0 focus:ring-0 dark:border-neutral-800 dark:bg-neutral-700 dark:text-gray-200 dark:placeholder:text-neutral-400 dark:focus:border-red-800" |
<div class="flex flex-col"> |
||||
/> |
<FormPasswordField |
||||
|
id="password" |
||||
|
v-model="password" |
||||
|
autocomplete="new-password" |
||||
|
:label="$t('general.password')" |
||||
|
/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<BaseButton @click="submit">{{ $t('setup.createAccount') }}</BaseButton> |
||||
|
</div> |
||||
</div> |
</div> |
||||
<div> |
|
||||
<Label for="password">{{ $t('setup.newPassword') }}</Label> |
|
||||
<input |
|
||||
id="password" |
|
||||
v-model="password" |
|
||||
form="newAccount" |
|
||||
type="password" |
|
||||
autocomplete="new-password" |
|
||||
class="mb-5 w-full rounded-lg border-2 border-gray-100 px-3 py-2 text-sm text-gray-500 focus:border-red-800 focus:outline-0 focus:ring-0 dark:border-neutral-800 dark:bg-neutral-700 dark:text-gray-200 dark:placeholder:text-neutral-400 dark:focus:border-red-800" |
|
||||
/> |
|
||||
</div> |
|
||||
<div> |
|
||||
<Label for="accept">{{ $t('setup.accept') }}</Label> |
|
||||
<input |
|
||||
id="accept" |
|
||||
v-model="accept" |
|
||||
form="newAccount" |
|
||||
type="checkbox" |
|
||||
class="ml-2" |
|
||||
/> |
|
||||
</div> |
|
||||
<BaseButton @click="newAccount">Create Account</BaseButton> |
|
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<script lang="ts" setup> |
<script lang="ts" setup> |
||||
import { FetchError } from 'ofetch'; |
|
||||
const { t } = useI18n(); |
|
||||
|
|
||||
definePageMeta({ |
definePageMeta({ |
||||
layout: 'setup', |
layout: 'setup', |
||||
}); |
}); |
||||
|
|
||||
const setupStore = useSetupStore(); |
const setupStore = useSetupStore(); |
||||
setupStore.setStep(2); |
setupStore.setStep(2); |
||||
const router = useRouter(); |
|
||||
const username = ref<null | string>(null); |
|
||||
const password = ref<null | string>(null); |
|
||||
const accept = ref<boolean>(true); |
|
||||
|
|
||||
const toast = useToast(); |
const username = ref<null | string>(null); |
||||
|
const password = ref<string>(''); |
||||
async function newAccount() { |
|
||||
try { |
|
||||
if (!username.value || !password.value) { |
|
||||
toast.showToast({ |
|
||||
type: 'error', |
|
||||
title: t('setup.requirements'), |
|
||||
message: t('setup.emptyFields'), |
|
||||
}); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
await setupStore.step2(username.value, password.value, accept.value); |
const _submit = useSubmit( |
||||
await router.push('/setup/3'); |
'/api/setup/2', |
||||
} catch (error) { |
{ |
||||
if (error instanceof FetchError) { |
method: 'post', |
||||
toast.showToast({ |
}, |
||||
type: 'error', |
{ |
||||
title: t('setup.requirements'), |
revert: async (success) => { |
||||
message: error.data.message, |
if (success) { |
||||
}); |
await navigateTo('/setup/3'); |
||||
} |
} |
||||
|
}, |
||||
|
noSuccessToast: true, |
||||
} |
} |
||||
|
); |
||||
|
|
||||
|
function submit() { |
||||
|
return _submit({ username: username.value, password: password.value }); |
||||
} |
} |
||||
</script> |
</script> |
||||
|
@ -1,71 +1,59 @@ |
|||||
<template> |
<template> |
||||
<div> |
<div> |
||||
<p class="p-8 text-center text-lg"> |
<p class="p-8 text-center text-lg"> |
||||
{{ $t('setup.messageSetupHostPort') }} |
{{ $t('setup.setupConfigDesc') }} |
||||
</p> |
</p> |
||||
<div> |
<div class="flex flex-col gap-3"> |
||||
<Label for="host">{{ $t('setup.host') }}</Label> |
<div class="flex flex-col"> |
||||
<input |
<FormNullTextField |
||||
id="host" |
id="host" |
||||
v-model="host" |
v-model="host" |
||||
type="text" |
type="text" |
||||
class="mb-5 w-full rounded-lg border-2 border-gray-100 px-3 py-2 text-sm text-gray-500 focus:border-red-800 focus:outline-0 focus:ring-0 dark:border-neutral-800 dark:bg-neutral-700 dark:text-gray-200 dark:placeholder:text-neutral-400 dark:focus:border-red-800" |
:label="$t('general.host')" |
||||
placeholder="vpn.example.com" |
placeholder="vpn.example.com" |
||||
/> |
/> |
||||
|
</div> |
||||
|
<div class="flex flex-col"> |
||||
|
<FormNumberField |
||||
|
id="port" |
||||
|
v-model="port" |
||||
|
type="number" |
||||
|
:label="$t('general.port')" |
||||
|
/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<BaseButton @click="submit">{{ $t('general.continue') }}</BaseButton> |
||||
|
</div> |
||||
</div> |
</div> |
||||
<div> |
|
||||
<Label for="port">{{ $t('setup.port') }}</Label> |
|
||||
<input |
|
||||
id="port" |
|
||||
v-model="port" |
|
||||
type="number" |
|
||||
:min="1" |
|
||||
:max="65535" |
|
||||
class="mb-5 w-full rounded-lg border-2 border-gray-100 px-3 py-2 text-sm text-gray-500 focus:border-red-800 focus:outline-0 focus:ring-0 dark:border-neutral-800 dark:bg-neutral-700 dark:text-gray-200 dark:placeholder:text-neutral-400 dark:focus:border-red-800" |
|
||||
/> |
|
||||
</div> |
|
||||
<BaseButton @click="updateHostPort">Continue</BaseButton> |
|
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<script setup lang="ts"> |
<script setup lang="ts"> |
||||
import { FetchError } from 'ofetch'; |
|
||||
|
|
||||
definePageMeta({ |
definePageMeta({ |
||||
layout: 'setup', |
layout: 'setup', |
||||
}); |
}); |
||||
|
|
||||
const { t } = useI18n(); |
|
||||
|
|
||||
const setupStore = useSetupStore(); |
const setupStore = useSetupStore(); |
||||
setupStore.setStep(4); |
setupStore.setStep(4); |
||||
const router = useRouter(); |
|
||||
const host = ref<null | string>(null); |
const host = ref<null | string>(null); |
||||
const port = ref<number>(51820); |
const port = ref<number>(51820); |
||||
|
|
||||
const toast = useToast(); |
const _submit = useSubmit( |
||||
|
'/api/setup/4', |
||||
async function updateHostPort() { |
{ |
||||
if (!host.value || !port.value) { |
method: 'post', |
||||
toast.showToast({ |
}, |
||||
type: 'error', |
{ |
||||
title: t('setup.requirements'), |
revert: async (success) => { |
||||
message: t('setup.emptyFields'), |
if (success) { |
||||
}); |
await navigateTo('/setup/5'); |
||||
return; |
} |
||||
|
}, |
||||
} |
} |
||||
|
); |
||||
|
|
||||
try { |
function submit() { |
||||
await setupStore.step4(host.value, port.value); |
return _submit({ host: host.value, port: port.value }); |
||||
await router.push('/setup/success'); |
|
||||
} catch (error) { |
|
||||
if (error instanceof FetchError) { |
|
||||
toast.showToast({ |
|
||||
type: 'error', |
|
||||
title: t('setup.requirements'), |
|
||||
message: error.data.message, |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
} |
||||
</script> |
</script> |
||||
|
Loading…
Reference in new issue