reuse rootdirs component in settings

This commit is contained in:
cwilvx
2025-10-07 20:01:31 +03:00
parent 6fd93a759d
commit a4cb04d261
10 changed files with 89 additions and 66 deletions

View File

@@ -1,10 +1,7 @@
<template>
<div class="account">
<div class="avatarbox rounded-sm">
<!-- <Avatar :name="username"/> -->
<!-- <LogoSvg /> -->
</div>
<form class="createadmin" @submit.prevent="createAccount">
<Avatar class="avatar" :name="username" :size="48"/>
<div>
<div class="heading">Create admin account</div>
<div class="description">This account will be used to manage your server.</div>
@@ -13,7 +10,7 @@
<div class="form">
<div class="names">
<label for="username">Username</label>
<Input :placeholder="username" input-id="username" @input="input => (username = input)" />
<Input :placeholder="username" input-id="username" required @input="input => (username = input)" />
</div>
<div class="passwords">
<div class="names">
@@ -47,8 +44,9 @@
import { onMounted, ref } from 'vue'
import { addNewUser } from '@/requests/auth'
import Input from '@/components/shared/Input.vue'
import Avatar from '@/components/shared/Avatar.vue'
const username = ref('admin')
const username = ref('')
const password = ref('✶✶✶✶✶✶✶✶')
const confirmPassword = ref('✶✶✶✶✶✶✶✶')
@@ -92,32 +90,6 @@ onMounted(() => {
<style lang="scss">
.account {
display: grid;
grid-template-columns: 1fr 1.25fr;
gap: 1.5rem;
width: 100%;
margin: 0 $medium 0 $medium;
.avatarbox {
width: 100%;
height: 100%;
// background gradient
background: linear-gradient(37deg, $pink, $purple);
display: flex;
// margin-left: $medium;
align-items: center;
justify-content: center;
padding: $small;
svg {
transform: scale(2);
}
background: url('https://images.unsplash.com/photo-1632516643720-e7f5d7d6ecc9?q=80&w=2022&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D')
no-repeat center center;
background-size: cover;
}
.passwords {
display: flex;
flex-direction: row;
@@ -128,10 +100,19 @@ onMounted(() => {
.createadmin {
width: 100%;
height: 100%;
// outline: solid 1px;
position: relative;
.heading {
margin-bottom: $smaller;
}
.avatar {
position: absolute;
top: 0;
right: 0;
// outline: solid 1px;
}
}
form {

View File

@@ -20,12 +20,7 @@
<span
><button
class="btn-finish"
@click="
$emit(
'submitDirs',
Array.from(selectedFolders.values()).map(index => folders[index].path)
)
"
@click="$emit('submitDirs', finalSelection.length ? finalSelection : [currentPath])"
>
Continue
</button></span
@@ -106,6 +101,9 @@ const renderedFolders = computed(() => {
const lastSelectedIndex = ref<number>(-1)
const selectedFolders = ref<Set<number>>(new Set())
const finalSelection = computed(() =>
Array.from(selectedFolders.value.values()).map(index => folders.value[index].path)
)
function isFirstSelected(index: number): boolean {
if (!selectedFolders.value.has(index)) return false

View File

@@ -36,7 +36,7 @@
</div>
<br />
<div class="btn-container">
<button class="btn-continue" @click="handleContinue">Continue</button>
<button class="btn-continue" @click="handleContinue">{{ fromSettings ? 'Update' : 'Continue' }}</button>
</div>
</div>
<div v-if="rootDirs.length > 0 && !homeDirSelected" class="selected-folders rounded-sm">
@@ -55,12 +55,18 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { paths } from '@/config'
import { router } from '@/router'
import useAxios from '@/requests/useAxios'
import useSettingsStore from '@/stores/settings'
import { getAllSettings } from '@/requests/settings'
import { addRootDirs } from '@/requests/settings/rootdirs'
import FilePicker from './FilePicker.vue'
import CheckSvg from '@/assets/icons/check.filled.svg'
import FolderSvg from '@/assets/icons/folder.svg'
import SubtractSvg from '@/assets/icons/subtract.svg'
import useAxios from '@/requests/useAxios'
import { paths } from '@/config'
import CheckSvg from '@/assets/icons/check.filled.svg'
// SECTION: Props & Emits
const props = defineProps<{
@@ -76,6 +82,9 @@ const emit = defineEmits<{
// SECTION: Properties
const showFilePicker = ref(false)
const rootDirs = ref<string[]>([])
const removedDirs = ref<string[]>([])
const fromSettings = computed(() => router.currentRoute.value.params.step === 'dirconfig')
const finalRootDirs = computed(() => {
if (rootDirs.value.length <= 1) {
return rootDirs.value
@@ -135,19 +144,37 @@ function handleSubmitDirs(dirs: string[]) {
function handleRemoveFolder(folder: string) {
rootDirs.value = rootDirs.value.filter(dir => dir !== folder)
removedDirs.value.push(folder)
}
function handleContinue() {
async function handleContinue() {
if (!rootDirs.value.length) {
emit('error', 'Please select a root directory')
return
}
emit('setRootDirs', rootDirs.value)
if (fromSettings.value) {
await addRootDirs(finalRootDirs.value, removedDirs.value)
// INFO: Go back to previous page
return router.go(-1)
}
emit('setRootDirs', finalRootDirs.value)
}
onMounted(async () => {
console.log('props.userhome', props.userhome)
if (fromSettings.value) {
const settings = useSettingsStore()
// INFO: If root dirs are not loaded, fetch from server
// NOTE: this path is executed when you reload this page
if (!settings.root_dirs.length) {
const { settings: data } = await getAllSettings()
settings.mapDbSettings(data)
}
rootDirs.value = settings.root_dirs
}
if (!props.userhome) {
const res = await useAxios({
@@ -164,8 +191,6 @@ onMounted(async () => {
} else {
userHome.value = props.userhome
}
console.log('userHome', userHome.value)
})
</script>

View File

@@ -24,9 +24,9 @@
/>
<CrudPage
v-if="modal.component == modal.options.page"
v-bind="modal.props"
@hideModal="hideModal"
@setTitle="setTitle"
v-bind="modal.props"
/>
<UpdatePlaylist
v-if="modal.component == modal.options.updatePlaylist"
@@ -43,7 +43,7 @@
</div>
<SetRootDirs v-if="modal.component == modal.options.setRootDirs" @hideModal="hideModal" />
<RootDirsPrompt v-if="modal.component == modal.options.rootDirsPrompt" @hideModal="hideModal" />
<Settings @set-title="setTitle" v-if="modal.component == modal.options.settings" />
<Settings v-if="modal.component == modal.options.settings" @set-title="setTitle" />
</div>
</div>
</template>

View File

@@ -1,20 +1,20 @@
<template>
<div
v-auto-animate
class="settingsmodal"
:class="{
isSmallPhone,
}"
v-auto-animate
>
<Sidebar
v-if="!(isSmallPhone && showContent)"
:current-group="(currentGroup as SettingGroup)"
@set-tab="tab => (currentTab = tab)"
v-if="!(isSmallPhone && showContent)"
/>
<div class="content" v-if="showContent">
<div class="head" v-auto-animate>
<div v-if="showContent" class="content">
<div v-auto-animate class="head">
<div class="h2">
<button class="back" v-if="isSmallPhone" @click="handleGoBack">
<button v-if="isSmallPhone" class="back" @click="handleGoBack">
<ArrowSvg />
</button>
{{ currentGroup?.title }}
@@ -64,6 +64,8 @@ const currentGroup = computed(() => {
}
}
}
return null
})
const showContent = computed(() => {
@@ -81,6 +83,7 @@ $modalheight: 38rem;
.settingsmodal {
display: grid;
grid-template-columns: 15rem 1fr;
height: 100%;
.content {
display: grid;

View File

@@ -18,7 +18,7 @@ defineProps<{
width: 100%;
padding: 0 1rem;
height: 100%;
max-height: calc(100vh - 6.85rem);
// max-height: calc(100vh - 6.85rem);
overflow: auto;
overflow-x: hidden;
scrollbar-gutter: stable;

View File

@@ -3,6 +3,8 @@
:size="size || 80"
:name="name"
:square="false"
:variant="'beam'"
:colors="['#3a3a3c']"
/>
</template>

View File

@@ -210,8 +210,9 @@ const PageView = {
}
const OnboardingView = {
path: '/onboarding',
path: '/onboarding/:step?',
name: 'Onboarding',
alias: ['/manconfig/:step?'],
component: Onboarding,
}

View File

@@ -5,6 +5,7 @@ import { manageRootDirsStrings as data } from '../strings'
import useModalStore from '@/stores/modal'
import settings from '@/stores/settings'
import { router, Routes } from '@/router'
const text = data.settings
@@ -12,8 +13,11 @@ const change_root_dirs: Setting = {
title: text.change,
type: SettingType.button,
state: null,
button_text: () => `\xa0 \xa0 ${settings().root_dirs.length ? 'Modify' : 'Configure'} \xa0 \xa0`,
action: () => useModalStore().showRootDirsPromptModal(),
button_text: () => `\xa0 \xa0 ${settings().root_dirs.length ? 'Update' : 'Configure'} \xa0 \xa0`,
action: () => {
useModalStore().hideModal()
return router.push({ path: '/manconfig/dirconfig' })
},
}
const list_root_dirs: Setting = {

View File

@@ -6,7 +6,7 @@
v-on="steps[currentStepIndex]?.events ?? {}"
/>
<div class="progressbar">
<div v-if="showProgressBar" class="progressbar">
<div
v-for="(step, index) in steps"
:key="step.name"
@@ -24,24 +24,24 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import { onMounted, ref } from 'vue'
import useModal from '@/stores/modal'
import { router, Routes } from '@/router'
import useInterface from '@/stores/interface'
import useModal from '@/stores/modal'
const UI = useInterface()
import { Waiter } from '@/composables/waiter'
import { addRootDirs } from '@/requests/settings/rootdirs'
import ErrorSvg from '@/assets/icons/toast/error.svg'
import Finish from '@/components/Onboarding/Finish.vue'
import Welcome from '@/components/Onboarding/Welcome.vue'
import Account from '@/components/Onboarding/Account.vue'
import RootDirs from '@/components/Onboarding/RootDirs.vue'
import { addRootDirs } from '@/requests/settings/rootdirs'
import { storeToRefs } from 'pinia'
import { Waiter } from '@/composables/waiter'
const errorText = ref('')
const userhome = ref('')
const showProgressBar = ref(true)
const UI = useInterface()
const { onboardingStep: currentStepIndex } = storeToRefs(UI)
const steps = [
@@ -104,6 +104,15 @@ async function handleFinish() {
name: Routes.Home,
})
}
onMounted(() => {
const step = router.currentRoute.value.params.step as string
if (step) {
currentStepIndex.value = steps.findIndex(s => s.name === step) || 0
showProgressBar.value = false
}
})
</script>
<style lang="scss">