feat: allow running elk with a single server (#1606)

This commit is contained in:
Joaquín Sánchez 2023-02-05 13:10:19 +01:00 committed by GitHub
parent 61428cd9cd
commit 53d0812efd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 232 additions and 79 deletions

View file

@ -5,6 +5,7 @@ import {
isCommandPanelOpen,
isConfirmDialogOpen,
isEditHistoryDialogOpen,
isErrorDialogOpen,
isFavouritedBoostedByDialogOpen,
isMediaPreviewOpen,
isPreviewHelpOpen,
@ -87,6 +88,9 @@ const handleFavouritedBoostedByClose = () => {
<ModalDialog v-model="isConfirmDialogOpen" py-4 px-8 max-w-125>
<ModalConfirm v-if="confirmDialogLabel" v-bind="confirmDialogLabel" @choice="handleConfirmChoice" />
</ModalDialog>
<ModalDialog v-model="isErrorDialogOpen" py-4 px-8 max-w-125>
<ModalError v-if="errorDialogData" v-bind="errorDialogData" />
</ModalDialog>
<ModalDialog
v-model="isFavouritedBoostedByDialogOpen"
max-w-180

View file

@ -0,0 +1,31 @@
<script setup lang="ts">
import type { ErrorDialogData } from '~/types'
defineProps<ErrorDialogData>()
</script>
<template>
<div flex="~ col" gap-6>
<div font-bold text-lg text-center>
{{ title }}
</div>
<div
flex="~ col"
gap-1 text-sm
pt-1 ps-2 pe-1 pb-2
text-red-600 dark:text-red-400
border="~ base rounded red-600 dark:red-400"
>
<ol ps-2 sm:ps-1>
<li v-for="(message, i) in messages" :key="i" flex="~ col sm:row" gap-y-1 sm:gap-x-2>
{{ message }}
</li>
</ol>
</div>
<div flex justify-end gap-2>
<button btn-text @click="closeErrorDialog()">
{{ close }}
</button>
</div>
</div>
</template>

View file

@ -1,3 +1,7 @@
<script setup>
const { busy, oauth, singleInstanceServer } = useSignIn()
</script>
<template>
<VDropdown v-if="isHydrated && currentUser" sm:hidden>
<div style="-webkit-touch-callout: none;">
@ -15,7 +19,24 @@
<UserSwitcher ref="switcher" @click="hide()" />
</template>
</VDropdown>
<button v-else btn-solid text-sm px-2 py-1 text-center xl:hidden @click="openSigninDialog()">
{{ $t('action.sign_in') }}
</button>
<template v-else>
<button
v-if="singleInstanceServer"
flex="~ row"
gap-x-1 items-center justify-center btn-solid text-sm px-2 py-1 xl:hidden
:disabled="busy"
@click="oauth()"
>
<span v-if="busy" aria-hidden="true" block animate animate-spin preserve-3d class="rtl-flip">
<span block i-ri:loader-2-fill aria-hidden="true" />
</span>
<span v-else aria-hidden="true" block i-ri:login-circle-line class="rtl-flip" />
<i18n-t keypath="action.sign_in_to">
<strong>{{ currentServer }}</strong>
</i18n-t>
</button>
<button v-else btn-solid text-sm px-2 py-1 text-center xl:hidden @click="openSigninDialog()">
{{ $t('action.sign_in') }}
</button>
</template>
</template>

View file

@ -1,66 +1,21 @@
<script setup lang="ts">
import Fuse from 'fuse.js'
import { $fetch } from 'ofetch'
const input = $ref<HTMLInputElement>()
let server = $ref<string>('')
let busy = $ref<boolean>(false)
let error = $ref<boolean>(false)
let displayError = $ref<boolean>(false)
const input = ref<HTMLInputElement | undefined>()
let knownServers = $ref<string[]>([])
let autocompleteIndex = $ref(0)
let autocompleteShow = $ref(false)
const users = useUsers()
const userSettings = useUserSettings()
async function oauth() {
if (busy)
return
busy = true
error = false
displayError = false
await nextTick()
if (server)
server = server.split('/')[0]
try {
const url = await (globalThis.$fetch as any)(`/api/${server || publicServer.value}/login`, {
method: 'POST',
body: {
force_login: users.value.some(u => u.server === server),
origin: location.origin,
lang: userSettings.value.language,
},
})
location.href = url
}
catch (err) {
console.error(err)
displayError = true
error = true
await nextTick()
input?.focus()
await nextTick()
setTimeout(() => {
busy = false
error = false
}, 512)
}
}
const { busy, error, displayError, server, oauth } = useSignIn(input)
let fuse = $shallowRef(new Fuse([] as string[]))
const filteredServers = $computed(() => {
if (!server)
if (!server.value)
return []
const results = fuse.search(server, { limit: 6 }).map(result => result.item)
if (results[0] === server)
const results = fuse.search(server.value, { limit: 6 }).map(result => result.item)
if (results[0] === server.value)
return []
return results
@ -78,12 +33,12 @@ function isValidUrl(str: string) {
}
async function handleInput() {
const input = server.trim()
const input = server.value.trim()
if (input.startsWith('https://'))
server = input.replace('https://', '')
server.value = input.replace('https://', '')
if (input.length)
displayError = false
displayError.value = false
if (
isValidUrl(`https://${input}`)
@ -110,7 +65,7 @@ function move(delta: number) {
function onEnter(e: KeyboardEvent) {
if (autocompleteShow === true && filteredServers[autocompleteIndex]) {
server = filteredServers[autocompleteIndex]
server.value = filteredServers[autocompleteIndex]
e.preventDefault()
autocompleteShow = false
}
@ -124,16 +79,16 @@ function escapeAutocomplete(evt: KeyboardEvent) {
}
function select(index: number) {
server = filteredServers[index]
server.value = filteredServers[index]
}
onMounted(async () => {
input?.focus()
input?.value?.focus()
knownServers = await (globalThis.$fetch as any)('/api/list-servers')
fuse = new Fuse(knownServers, { shouldSort: true })
})
onClickOutside($$(input), () => {
onClickOutside(input, () => {
autocompleteShow = false
})
</script>

View file

@ -1,3 +1,7 @@
<script setup lang="ts">
const { busy, oauth, singleInstanceServer } = useSignIn()
</script>
<template>
<div p8 lg:flex="~ col gap2" hidden>
<p v-if="isHydrated" text-sm>
@ -8,7 +12,19 @@
<p text-sm text-secondary>
{{ $t('user.sign_in_desc') }}
</p>
<button btn-solid rounded-3 text-center mt-2 select-none @click="openSigninDialog()">
<button
v-if="singleInstanceServer"
flex="~ row" gap-x-2 items-center justify-center btn-solid text-center rounded-3
:disabled="busy"
@click="oauth()"
>
<span v-if="busy" aria-hidden="true" block animate animate-spin preserve-3d class="rtl-flip">
<span block i-ri:loader-2-fill aria-hidden="true" />
</span>
<span v-else aria-hidden="true" block i-ri:login-circle-line class="rtl-flip" />
{{ $t('action.sign_in') }}
</button>
<button v-else btn-solid rounded-3 text-center mt-2 select-none @click="openSigninDialog()">
{{ $t('action.sign_in') }}
</button>
</div>

View file

@ -6,6 +6,7 @@ const emit = defineEmits<{
}>()
const all = useUsers()
const { busy, singleInstanceServer, oauth } = useSignIn()
const sorted = computed(() => {
return [
@ -21,6 +22,12 @@ const clickUser = (user: UserLogin) => {
else
switchUser(user)
}
const processSignIn = () => {
if (singleInstanceServer)
oauth()
else
openSigninDialog()
}
</script>
<template>
@ -43,7 +50,7 @@ const clickUser = (user: UserLogin) => {
:text="$t('user.add_existing')"
icon="i-ri:user-add-line"
w-full
@click="openSigninDialog"
@click="processSignIn"
/>
<CommonDropdownItem
is="button"