migrated presets.vue to ts

This commit is contained in:
arabcoders 2025-07-26 20:08:49 +03:00
parent 4b0522e72e
commit 5942d12f2e
3 changed files with 66 additions and 74 deletions

View file

@ -241,7 +241,7 @@ const emitter = defineEmits<{
const props = defineProps<{ const props = defineProps<{
reference?: string | null reference?: string | null
preset: Preset preset: Partial<Preset>
addInProgress?: boolean addInProgress?: boolean
presets?: Preset[] presets?: Preset[]
}>() }>()

View file

@ -1,13 +1,3 @@
<style scoped>
table.is-fixed {
table-layout: fixed;
}
div.is-centered {
justify-content: center;
}
</style>
<template> <template>
<main> <main>
<div class="mt-1 columns is-multiline"> <div class="mt-1 columns is-multiline">
@ -35,7 +25,7 @@ div.is-centered {
</button> </button>
</p> </p>
<p class="control"> <p class="control">
<button class="button is-info" @click="reloadContent" :class="{ 'is-loading': isLoading }" <button class="button is-info" @click="reloadContent()" :class="{ 'is-loading': isLoading }"
:disabled="!socket.isConnected || isLoading" v-if="presets && presets.length > 0"> :disabled="!socket.isConnected || isLoading" v-if="presets && presets.length > 0">
<span class="icon"><i class="fas fa-refresh" /></span> <span class="icon"><i class="fas fa-refresh" /></span>
</button> </button>
@ -71,9 +61,13 @@ div.is-centered {
</thead> </thead>
<tbody> <tbody>
<tr v-for="item in presetsNoDefault" :key="item.id"> <tr v-for="item in presetsNoDefault" :key="item.id">
<td class="is-vcentered"> <td class="is-text-overflow is-vcentered">
<div class="is-text-overflow"> <div> {{ item.name }}</div>
{{ item.name }} <div class="is-unselectable">
<span class="icon-text" v-if="item.cookies">
<span class="icon"><i class="fa-solid fa-cookie" /></span>
<span>Cookies</span>
</span>
</div> </div>
</td> </td>
<td class="is-vcentered is-items-center"> <td class="is-vcentered is-items-center">
@ -210,24 +204,25 @@ div.is-centered {
</main> </main>
</template> </template>
<script setup> <script setup lang="ts">
import { useStorage } from '@vueuse/core' import { useStorage } from '@vueuse/core'
import type { Preset } from '~/types/presets'
const toast = useNotification() const toast = useNotification()
const config = useConfigStore() const config = useConfigStore()
const socket = useSocketStore() const socket = useSocketStore()
const box = useConfirm() const box = useConfirm()
const display_style = useStorage("preset_display_style", "cards") const display_style = useStorage<string>('preset_display_style', 'cards')
const presets = ref([]) const presets = ref<Preset[]>([])
const preset = ref({}) const preset = ref<Partial<Preset>>({})
const presetRef = ref("") const presetRef = ref<string | null>('')
const toggleForm = ref(false) const toggleForm = ref(false)
const isLoading = ref(true) const isLoading = ref(true)
const initialLoad = ref(true) const initialLoad = ref(true)
const addInProgress = ref(false) const addInProgress = ref(false)
const remove_keys = ["raw", "toggle_description"] const remove_keys = ['raw', 'toggle_description']
const presetsNoDefault = computed(() => presets.value.filter((t) => !t.default)) const presetsNoDefault = computed(() => presets.value.filter((t) => !t.default))
@ -237,7 +232,7 @@ watch(
if (!config.app.basic_mode) { if (!config.app.basic_mode) {
return return
} }
await navigateTo("/") await navigateTo('/')
}, },
) )
@ -251,24 +246,24 @@ watch(() => socket.isConnected, async () => {
const reloadContent = async (fromMounted = false) => { const reloadContent = async (fromMounted = false) => {
try { try {
isLoading.value = true isLoading.value = true
const response = await request("/api/presets") const response = await request('/api/presets')
if (fromMounted && !response.ok) { if (fromMounted && !response.ok) {
return return
} }
const data = await response.json() const data = await response.json()
if (data.length < 1) { if (0 === data.length) {
return return
} }
presets.value = data presets.value = data
} catch (e) { } catch (e: any) {
if (fromMounted) { if (fromMounted) {
return return
} }
console.error(e) console.error(e)
toast.error("Failed to fetch page content.") toast.error('Failed to fetch page content.')
} finally { } finally {
isLoading.value = false isLoading.value = false
} }
@ -283,14 +278,14 @@ const resetForm = (closeForm = false) => {
} }
} }
const updatePresets = async (items) => { const updatePresets = async (items: Preset[]): Promise<boolean | undefined> => {
let data let data: any
try { try {
addInProgress.value = true addInProgress.value = true
const response = await request("/api/presets", { const response = await request('/api/presets', {
method: "PUT", method: 'PUT',
headers: { "Content-Type": "application/json" }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(items.filter((t) => !t.default)), body: JSON.stringify(items.filter((t) => !t.default)),
}) })
@ -304,44 +299,49 @@ const updatePresets = async (items) => {
presets.value = data presets.value = data
resetForm(true) resetForm(true)
return true return true
} catch (e) { } catch (e: any) {
toast.error(`Failed to update presets. ${data?.error}. ${e.message}`) toast.error(`Failed to update presets. ${data?.error}. ${e.message}`)
} finally { } finally {
addInProgress.value = false addInProgress.value = false
} }
} }
const deleteItem = async (item) => { const deleteItem = async (item: Preset) => {
if (true !== box.confirm(`Delete preset '${item.name}'?`, true)) { if (true !== box.confirm(`Delete preset '${item.name}'?`, true)) {
return return
} }
const index = presets.value.findIndex((t) => t?.id === item.id) const index = presets.value.findIndex((t) => t?.id === item.id)
if (index > -1) { if (-1 === index) {
presets.value.splice(index, 1) toast.error('Preset not found.')
} else {
toast.error("Preset not found.")
return return
} }
const status = await updatePresets(presets.value) presets.value.splice(index, 1)
const status = await updatePresets(presets.value)
if (!status) { if (!status) {
return return
} }
toast.success("Preset deleted.") toast.success('Preset deleted.')
} }
const updateItem = async ({ reference, preset }) => { const updateItem = async ({
preset = cleanObject(preset, remove_keys) reference,
preset: item,
}: {
reference: string | null
preset: Preset
}) => {
item = cleanObject(item, remove_keys) as Preset
if (reference) { if (reference) {
const index = presets.value.findIndex((t) => t?.id === reference) const index = presets.value.findIndex((t) => t?.id === reference)
if (index > -1) { if (-1 !== index) {
presets.value[index] = preset presets.value[index] = item
} }
} else { } else {
presets.value.push(preset) presets.value.push(item)
} }
const status = await updatePresets(presets.value) const status = await updatePresets(presets.value)
@ -349,66 +349,56 @@ const updateItem = async ({ reference, preset }) => {
return return
} }
toast.success(`Preset ${reference ? "updated" : "added"}.`) toast.success(`Preset ${reference ? 'updated' : 'added'}.`)
resetForm(true) resetForm(true)
} }
const filterItem = item => { const filterItem = (item: Preset) => {
const rest = cleanObject(item, remove_keys) const rest = cleanObject(item, remove_keys)
if ("default" in rest) { if ('default' in rest) {
delete rest.default delete rest.default
} }
return JSON.stringify(rest, null, 2) return JSON.stringify(rest, null, 2)
} }
const editItem = item => { const editItem = (item: Preset) => {
preset.value = JSON.parse(filterItem(item)) preset.value = JSON.parse(filterItem(item))
presetRef.value = item.id presetRef.value = item.id ?? null
toggleForm.value = true toggleForm.value = true
} }
onMounted(async () => (socket.isConnected ? await reloadContent(true) : "")) onMounted(async () => (socket.isConnected ? await reloadContent(true) : ''))
const exportItem = item => { const exportItem = (item: Preset) => {
let data = JSON.parse(JSON.stringify(item)) const keys = ['id', 'default', 'raw', 'cookies', 'toggle_description']
const keys = ["id", "default", "raw", "cookies", "toggle_description"] const data = JSON.parse(JSON.stringify(item))
keys.forEach(key => {
for (const key of keys) {
if (key in data) { if (key in data) {
delete data[key] delete data[key]
} }
}) }
let userData = {}
const userData: Record<string, any> = {}
for (const key of Object.keys(data)) { for (const key of Object.keys(data)) {
if (!data[key]) { if (data[key]) {
continue userData[key] = data[key]
} }
userData[key] = data[key]
} }
if (config?.app?.ytdlp_cli) { if (config?.app?.ytdlp_cli) {
const val = `# exported from ytdlp.cli #\n${config.app.ytdlp_cli}\n# exported from ytdlp.cli #\n` const val = `# exported from ytdlp.cli #\n${config.app.ytdlp_cli}\n# exported from ytdlp.cli #\n`
if (userData.cli) { userData.cli = userData.cli ? val + '\n' + userData.cli : val
userData.cli = val + "\n" + userData.cli
} else {
userData.cli = val
}
} }
userData['_type'] = 'preset' userData['_type'] = 'preset'
userData['_version'] = '2.5' userData['_version'] = '2.5'
return copyText(encode(userData)) copyText(encode(userData))
} }
const calcPath = (path) => { const calcPath = (path?: string): string => {
const loc = config.app.download_path || "/downloads" const loc = config.app.download_path || '/downloads'
return path ? loc + '/' + sTrim(path, '/') : loc
if (path) {
return loc + "/" + sTrim(path, "/")
}
return loc
} }
</script> </script>

View file

@ -7,6 +7,8 @@ type Preset = {
description: string description: string
folder: string folder: string
template: string template: string
raw?:boolean
toggle_description?: boolean
} }
type PresetImport = Preset & { type PresetImport = Preset & {